Alert message goes here
diff --git a/packages/boba/gateway/src/components/pageFooter/PageFooter.js b/packages/boba/gateway/src/components/pageFooter/PageFooter.js
deleted file mode 100644
index e982324aa4..0000000000
--- a/packages/boba/gateway/src/components/pageFooter/PageFooter.js
+++ /dev/null
@@ -1,176 +0,0 @@
-import { Telegram, Twitter } from '@mui/icons-material'
-import DiscordIcon from 'components/icons/DiscordIcon'
-import React from 'react'
-import BobaLogo from '../../images/boba2/logo-boba2.svg'
-import GasSwitcher from '../mainMenu/gasSwitcher/GasSwitcher'
-import * as S from './PageFooter.styles'
-import { useMediaQuery, useTheme } from '@mui/material'
-import { LAYER, ROUTES_PATH, WALLET_VERSION } from 'util/constant'
-import { useSelector } from 'react-redux'
-import {
- selectLayer,
- selectActiveNetwork,
- selectActiveNetworkType,
-} from 'selectors'
-import { getBlockExplorerUrl } from 'util/network/network.util'
-
-
-const PageFooter = ({ maintenance }) => {
- const theme = useTheme()
- const isMobile = useMediaQuery(theme.breakpoints.down('md'))
- const [isDiscordHover, setIsDiscordHover] = React.useState(false)
-
- const layer = useSelector(selectLayer())
- const network = useSelector(selectActiveNetwork())
- const networkType = useSelector(selectActiveNetworkType())
-
- if (maintenance) {
- return (
-
-
-
-
-
-
-
-
-
-
- Boba Docs
-
-
-
-
-
-
-
- setIsDiscordHover(true)}
- onMouseLeave={() => setIsDiscordHover(false)}
- >
-
-
-
-
-
-
- Boba Website
-
-
-
-
- )
- }
- return (
-
-
-
-
-
-
- setIsDiscordHover(true)}
- onMouseLeave={() => setIsDiscordHover(false)}
- >
-
-
-
-
-
-
- {!isMobile && }
-
-
-
-
-
-
-
- FAQs
-
-
- Dev Tools
-
- BobaScope
-
- Blockexplorer
-
-
- Boba Docs
-
-
-
-
-
- Boba Website
-
-
-
- v{WALLET_VERSION}
-
-
- )
-}
-
-export default PageFooter
diff --git a/packages/boba/gateway/src/components/pageFooter/PageFooter.styles.js b/packages/boba/gateway/src/components/pageFooter/PageFooter.styles.js
deleted file mode 100644
index 15ff38add2..0000000000
--- a/packages/boba/gateway/src/components/pageFooter/PageFooter.styles.js
+++ /dev/null
@@ -1,168 +0,0 @@
-import { styled } from '@mui/material/styles'
-import { Box, Divider } from '@mui/material'
-import { NavLink } from 'react-router-dom'
-import { IconButton } from '@mui/material'
-
-export const Wrapper = styled(Box)(({ theme }) => ({
- display: 'flex',
- flexDirection: 'column',
- justifyContent: 'flex-start',
- alignItems: 'center',
- //margin: '0',
- //padding: '0 20px',
- //bottom: 0,
- //width: '100%',
- //height: '184px',
- background: theme.palette.background.footer,
- [theme.breakpoints.down('md')]: {
- marginTop: '10px',
- maxHeight: '400px',
- justifyContent: 'flex-start',
- padding: '0 20px',
- },
- color: 'rgba(255, 255, 255, 0.65)'
-}))
-
-export const ContentWrapper = styled(Box)(({ theme }) => ({
- display: 'flex',
- justifyContent: 'space-between',
- width: '70%',
- margin: '30px 0',
- [theme.breakpoints.between('sm', 'md')]: {
- width: '90%',
- margin: '20px 0',
- flexDirection: 'column',
- justifyContent: 'center',
- gap: '20px',
- },
- [theme.breakpoints.down('md')]: {
- margin: '20px 0',
- width: '100%',
- flexDirection: 'column',
- justifyContent: 'center',
- gap: '20px',
- },
-
-}))
-
-export const FooterLink = styled(NavLink)(({ theme }) => ({
- //marginLeft: theme.spacing(1),
- marginTop: theme.spacing(1),
- fontSize: '14px',
- textDecoration: 'none',
- cursor: 'pointer',
- color: 'unset',
- '&:hover': {
- color: theme.palette.secondary.main,
- },
-}))
-
-export const FooterLinkExt = styled(Box)(({ theme }) => ({
- //marginLeft: theme.spacing(1),
- marginTop: theme.spacing(1),
- fontSize: '14px',
- textDecoration: 'none',
- cursor: 'pointer',
- color: 'unset',
- '&:hover': {
- color: theme.palette.secondary.main,
- },
-}))
-
-export const FooterLogoWrapper = styled(Box)(({ theme }) => ({
- display: 'flex',
- alignSelf: 'flex-start',
- justifyContent: 'center',
- alignItems: 'center',
-
-}))
-
-export const FooterDivider = styled(Divider)(({ theme }) => ({
- background: 'rgba(49,49,49, 1)',
- boxSizing: 'border-box',
- width: '100%',
-}))
-
-export const FooterDividerMobile = styled(Divider)(({ theme }) => ({
- display: 'none',
- [theme.breakpoints.down('md')]: {
- display: 'block',
- background: 'rgba(255, 255, 255, 0.04)',
- boxSizing: 'border-box',
- boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.25)',
- width: '100%',
- },
-}))
-
-export const FooterLinkWrapperLeft = styled(Box)(({ theme }) => ({}))
-
-export const FooterLinkWrapper = styled(Box)(({ theme }) => ({
- display: 'flex',
- alignSelf: 'flex-start',
- justifyContent: 'space-between',
- alignItems: 'center',
- width: '70%',
- [theme.breakpoints.down('md')]: {
- width: '100%',
- justifyContent: 'space-around',
- flexDirection: 'column',
- margin: '0',
- marginTop: '20px',
- alignItems: 'flex-start',
- },
-}))
-
-export const LinkWrapper = styled(Box)(({ theme }) => ({
- display: 'flex',
- width: '40%',
- justifyContent: 'flex-start',
- gap: '10px',
- [theme.breakpoints.down('md')]: {
- flexDirection: 'column',
- alignItems: 'flex-start',
- margin: '10px 0',
- width: '100%',
- gap: 0,
- },
- [theme.breakpoints.down('sm')]: {
- width: '100%',
- },
-}))
-
-export const SocialWrapper = styled(Box)(({ theme }) => ({
- display: 'flex',
- width: '20%',
- justifyContent: 'flex-start',
- gap: '10px',
- a: {
- cursor: 'pointer',
- },
- [theme.breakpoints.down('md')]: {
- justifyContent: 'center',
- margin: '10px 0',
- width: '100%',
- },
- [theme.breakpoints.down('sm')]: {
- width: '100%',
- },
-}))
-
-export const SocialButton = styled(IconButton)(({ theme }) => ({
- svg: {
- path: {
- fill: 'rgba(255, 255, 255, 0.65)',
- fillOpacity: 1,
- },
- },
- color: 'rgba(255, 255, 255, 1)',
- opacity: 0.65,
- '&:hover': {
- background: 'none',
- svg: {
- path: {
- fill: theme.palette.secondary.main,
- fillOpacity: 1,
- },
- },
- },
-}))
diff --git a/packages/boba/gateway/src/components/pageHeader/PageHeader.js b/packages/boba/gateway/src/components/pageHeader/PageHeader.js
deleted file mode 100644
index 4ee4c2aedf..0000000000
--- a/packages/boba/gateway/src/components/pageHeader/PageHeader.js
+++ /dev/null
@@ -1,181 +0,0 @@
-import React, { useState } from 'react'
-import BobaLogo from '../icons/BobaLogo'
-import { ReactComponent as BobaLogoM } from '../../images/boba2/logo-boba2-m.svg'
-import { useSelector } from 'react-redux'
-import {
- HeaderWrapper,
- StyleDrawer,
- HeaderActionButton,
- DrawerHeader,
- WrapperCloseIcon,
- HeaderDivider,
-} from './PageHeader.styles'
-import {
- Box,
- Container,
- Drawer,
- IconButton,
- Typography,
- useMediaQuery,
- useTheme,
-} from '@mui/material'
-
-import NavIcon from 'components/icons/NavIcon'
-import WalletIcon from 'components/icons/WalletIcon'
-import CloseIcon from 'components/icons/CloseIcon'
-import networkService from 'services/networkService'
-import { makeStyles } from '@mui/styles'
-import {
- Copy,
- Disconnect,
- MenuItems,
- ThemeSwitcher,
- FeeSwitcher,
- NetworkSwitcher,
-} from 'components'
-import { selectAccountEnabled, selectLayer, selectMonster } from 'selectors'
-import { LAYER } from 'util/constant'
-
-const useStyles = makeStyles({
- root: {
- width: '100%',
- color: 'f00',
- },
-})
-
-const PageHeader = ({ maintenance }) => {
- const classes = useStyles()
- const [open, setOpen] = useState(false)
- const [walletOpen, setWalletOpen] = useState(false)
- const [feeOpen, setFeeOpen] = useState(false)
-
- const theme = useTheme()
- const accountEnabled = useSelector(selectAccountEnabled())
- const layer = useSelector(selectLayer())
- const monsterNumber = useSelector(selectMonster())
- const isMobile = useMediaQuery(theme.breakpoints.down('md'))
-
- const Logo = monsterNumber > 0 ? BobaLogoM : BobaLogo
-
- if (maintenance) {
- return (
-
-
-
-
- )
- }
-
- return (
- <>
- {isMobile ? (
-
-
-
-
- setFeeOpen(!feeOpen)}
- sx={{ cursor: 'pointer' }}
- >
-
- Fee
-
-
- setWalletOpen(!walletOpen)}
- sx={{ cursor: 'pointer' }}
- >
-
-
- setOpen(!open)} sx={{ cursor: 'pointer' }}>
-
-
-
- setOpen(false)}
- classes={{ paper: classes.root }}
- >
-
-
-
-
- Menu
-
- setOpen(false)}>
-
-
-
-
-
-
-
-
-
- setWalletOpen(false)}
- classes={{ paper: classes.root }}
- >
-
-
-
-
- Connect wallet
-
- setWalletOpen(false)}
- >
-
-
-
-
-
-
-
-
- setFeeOpen(false)}
- classes={{ paper: classes.root }}
- >
-
-
-
-
- Select Fee
-
- setFeeOpen(false)}>
-
-
-
-
-
- {layer === LAYER.L2 ? : null}
-
-
-
-
- ) : (
-
-
-
- {layer === LAYER.L2 ? : null}
-
- {!!accountEnabled ? (
- <>
-
-
- >
- ) : null}
-
-
- )}
- >
- )
-}
-
-export default PageHeader
diff --git a/packages/boba/gateway/src/components/pageHeader/PageHeader.styles.js b/packages/boba/gateway/src/components/pageHeader/PageHeader.styles.js
deleted file mode 100644
index 1685957079..0000000000
--- a/packages/boba/gateway/src/components/pageHeader/PageHeader.styles.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { Box, Divider } from "@mui/material"
-import { styled } from '@mui/material/styles'
-
-export const HeaderWrapper = styled(Box)(({ theme }) => ({
- width: '100%',
- height: '64px',
- gap: '10px',
- display: 'flex',
- justifyContent: 'space-around',
- alignItems: 'center',
- padding: '20px',
- [ theme.breakpoints.down('md') ]: {
- justifyContent: 'space-between',
- padding: '20px 0',
- }
-}))
-
-export const HeaderActionButton = styled(Box)(({ theme }) => ({
- gap: '10px',
- display: 'flex',
- justifyContent: 'space-around',
- alignItems: 'center',
-}))
-
-export const DrawerHeader = styled(Box)`
- display: flex;
- flex-direction: column;
- gap: 30px;
- padding: 20px 24px;
-`;
-
-export const HeaderDivider = styled(Divider)(({ theme }) => ({
- background: `${ theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.04)' : 'rgba(3, 19, 19, 0.04)'}`,
- boxSizing: 'border-box',
- boxShadow: `${ theme.palette.mode === 'dark' ? '0px 4px 4px rgba(0, 0, 0, 0.25)' : 'none'}`,
- width: '100%'
-}))
-
-export const WrapperCloseIcon = styled(Box)`
- display: flex;
- justify-content: space-between;
- align-items: center;
-`;
-
-export const StyleDrawer = styled(Box)`
- background-color: ${(props) => props.theme.palette.mode === 'light' ? 'white' : '#111315'};
- height: 100%;
-`;
diff --git a/packages/boba/gateway/src/components/pageHeader/PageHeader.styles.tsx b/packages/boba/gateway/src/components/pageHeader/PageHeader.styles.tsx
deleted file mode 100644
index ef3d6858e6..0000000000
--- a/packages/boba/gateway/src/components/pageHeader/PageHeader.styles.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import styled, { css } from 'styled-components'
-
-export const HeaderWrapper = styled.div`
- display: flex;
- width: 100%;
- height: 64px;
- gap: 10px;
- justify-content: space-around;
- align-items: center;
- padding: '20px';
-
- @media (max-width: 980px) {
- justify-content: space-between;
- padding: 20px 0;
- }
-`
-
-export const HeaderActionButton = styled.div`
- gap: 10px;
- display: flex;
- justify-content: space-around;
- align-items: center;
-`
-
-export const DrawerHeader = styled.div`
- display: flex;
- flex-direction: column;
- gap: 30px;
- padding: 20px 24px;
-`
-
-export const HeaderDivider = styled.div`
- ${(props) =>
- props.theme.name === 'light' &&
- css`
- background: ${props.theme.colors.gray[700]};
- `}
- ${(props) =>
- props.theme.name === 'dark' &&
- css`
- background: ${props.theme.colors.gray[800]};
- `}
- box-sizing: border-box;
- box-shadow: ${(props) => props.theme.boxShadow};
- width: 100%;
-`
-
-export const WrapperCloseIcon = styled.div`
- display: flex;
- justify-content: space-between;
- align-items: center;
-`
-
-export const StyleDrawer = styled.div`
- height: 100%;
-
- ${(props) =>
- props.theme.name === 'light' &&
- css`
- background: ${props.theme.colors.gray[50]};
- `}
- ${(props) =>
- props.theme.name === 'dark' &&
- css`
- background: ${props.theme.colors.gray[800]};
- `}
-`
diff --git a/packages/boba/gateway/src/components/seven/FastExit.js b/packages/boba/gateway/src/components/seven/FastExit.js
index 0aba0b2171..38cf3ce590 100644
--- a/packages/boba/gateway/src/components/seven/FastExit.js
+++ b/packages/boba/gateway/src/components/seven/FastExit.js
@@ -18,17 +18,13 @@ import React from 'react'
import { Typography } from '@mui/material'
import * as S from './Transaction.styles'
+import { ExitWrapper, ExitsWrapper, Hash, HashContainer } from './styles'
import networkService from 'services/networkService'
function FastExit({
- link,
- status,
- chain,
blockNumber,
- oriChain,
oriHash,
- age,
unixTime
}) {
@@ -44,7 +40,7 @@ function FastExit({
let timeLabel = `Fast Exit was started ${secondsAgo} seconds ago`
return (
-
+
-
+
{blockNumber}
{timeLabel}
-
+
Hash:
-
{oriHash}
-
-
-
+
+
+
-
+
)
}
diff --git a/packages/boba/gateway/src/components/seven/Seven.js b/packages/boba/gateway/src/components/seven/Seven.js
index 83b80e7d2d..bf1c66d80f 100644
--- a/packages/boba/gateway/src/components/seven/Seven.js
+++ b/packages/boba/gateway/src/components/seven/Seven.js
@@ -18,17 +18,13 @@ import React from 'react'
import { Typography } from '@mui/material'
import * as S from './Transaction.styles'
+import { Hash, ExitsWrapper, ExitWrapper, HashContainer } from './styles'
import networkService from 'services/networkService'
function Seven({
- link,
- status,
- chain,
blockNumber,
- oriChain,
oriHash,
- age,
unixTime
}) {
@@ -57,7 +53,7 @@ function Seven({
}
return (
-
+
-
+
{blockNumber}
{overdue < 0 &&
@@ -84,21 +80,20 @@ function Seven({
{timeLabel}
}
-
+
Hash:
-
{oriHash}
-
-
-
+
+
+
-
+
)
}
diff --git a/packages/boba/gateway/src/components/seven/styles.ts b/packages/boba/gateway/src/components/seven/styles.ts
new file mode 100644
index 0000000000..cf67669e97
--- /dev/null
+++ b/packages/boba/gateway/src/components/seven/styles.ts
@@ -0,0 +1,59 @@
+import styled, { css } from 'styled-components'
+import { Typography } from 'components/global'
+
+export const ExitsWrapper = styled.div`
+ background: ${(props) => props.theme.colors.popup};
+ padding: 10px;
+ border-radius: 12px;
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ border: solid 1px ${props.theme.colors.gray[400]};
+ &:hover {
+ background: ${props.theme.colors.gray[300]};
+ border: solid 1px ${props.theme.colors.gray[500]};
+ }
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ border: solid 1px ${props.theme.colors.gray[300]};
+ &:hover {
+ background: ${props.theme.colors.gray[300]};
+ }
+ `}
+`
+
+export const ExitWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: flex-start;
+ gap: 5px;
+`
+
+export const HashContainer = styled(Typography)`
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ color: ${props.theme.colors.gray[700]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ color: ${props.theme.colors.gray[50]};
+ `}
+`
+
+export const Hash = styled.a`
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ color: ${props.theme.colors.gray[700]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ color: ${props.theme.colors.gray[50]};
+ `}
+`
diff --git a/packages/boba/gateway/src/components/stake/transactionList/index.tsx b/packages/boba/gateway/src/components/stake/transactionList/index.tsx
new file mode 100644
index 0000000000..bc00a6c0c9
--- /dev/null
+++ b/packages/boba/gateway/src/components/stake/transactionList/index.tsx
@@ -0,0 +1,103 @@
+import React from 'react'
+import dayjs from 'dayjs'
+import duration from 'dayjs/plugin/duration'
+
+dayjs.extend(duration)
+
+import { useDispatch } from 'react-redux'
+import { openAlert, openError } from 'actions/uiAction'
+import { withdrawFS_Savings } from 'actions/fixedAction'
+
+import { Button } from 'components/global/button'
+import { Typography } from 'components/global/typography'
+import { ModalTypography } from 'components/global/modalTypography'
+
+import { TransactionListInterface } from './types'
+import { StakeItemDetails, Token, Flex } from './styles'
+import { getCoinImage } from 'util/coinImage'
+
+const TransactionList = ({ stakeInfo }: TransactionListInterface) => {
+ const dispatch = useDispatch
()
+
+ const timeDeposit = dayjs.unix(stakeInfo.depositTimestamp)
+ const timeNow = dayjs()
+
+ const duration_Days = timeNow.diff(timeDeposit, 'day')
+ const earned = stakeInfo.depositAmount * (0.05 / 365.0) * duration_Days
+
+ const unlocktimeNextBegin = timeDeposit.add(14, 'day')
+
+ const unlocktimeNextEnd = unlocktimeNextBegin.add(2, 'day')
+
+ /* finalize the migration to DAYJs next deploy*/
+ const timeDeposit_S = stakeInfo.depositTimestamp
+ const timeNow_S = Math.round(Date.now() / 1000)
+
+ const duration_S = timeNow_S - timeDeposit_S
+
+ const twoWeeks = 14 * 24 * 60 * 60
+ const twoDays = 2 * 24 * 60 * 60
+ const residual_S = duration_S % (twoWeeks + twoDays)
+
+ const handleUnstake = async () => {
+ const withdrawTX = await dispatch(withdrawFS_Savings(stakeInfo.stakeId))
+
+ if (withdrawTX !== null && withdrawTX !== undefined) {
+ openAlert('Your BOBA were unstaked')
+ } else {
+ openError('Failed to unstake BOBA')
+ }
+ }
+
+ let locked = true
+ if (residual_S > twoWeeks) {
+ locked = false
+ }
+
+ return (
+
+
+
+
+ {timeDeposit.format('DD MMM YYYY hh:mm A')}
+
+
+
+
+ Amount Staked
+
+ {stakeInfo.depositAmount
+ ? `${stakeInfo.depositAmount.toLocaleString(undefined, {
+ maximumFractionDigits: 2,
+ })}`
+ : `0`}
+
+
+
+ Earned
+ {earned.toFixed(3)}
+
+
+
+ Next unstake window:{' '}
+
+
+ {` ${unlocktimeNextBegin.format('DD')}-${unlocktimeNextEnd.format(
+ 'DD MMM YYYY hh:mm A'
+ )}`}
+
+
+
+
+
+
+
+ )
+}
+
+export default TransactionList
diff --git a/packages/boba/gateway/src/components/stake/transactionList/styles.ts b/packages/boba/gateway/src/components/stake/transactionList/styles.ts
new file mode 100644
index 0000000000..0575888b4c
--- /dev/null
+++ b/packages/boba/gateway/src/components/stake/transactionList/styles.ts
@@ -0,0 +1,69 @@
+import styled, { css } from 'styled-components'
+import { sdesktop, tablet, mobile } from 'themes/screens'
+export const Wrapper = styled.div`
+ border-radius: 0;
+ background: ${(props) => props.theme.background.secondary};
+`
+
+export const Entry = styled.div`
+ padding: 20px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background: ${(props) => props.theme.background.secondary};
+`
+
+export const GridCoontainer = styled.div``
+export const GridItemTag = styled.div`
+ text-align: left;
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: center;
+`
+
+export const StakeItemDetails = styled.div`
+ display: flex;
+ width: 100%;
+ justify-content: space-between;
+ align-items: center;
+ background: ${(props) => props.theme.colors.box.background};
+ border: 1px solid ${(props) => props.theme.colors.box.border};
+ box-sizing: border-box;
+ padding: 20px 35px;
+ border-radius: 8px;
+
+ > div {
+ display: flex;
+ margin: 0px auto;
+ white-space: break-spaces;
+ align-items: center;
+ &:first-of-type {
+ margin-left: 0px;
+ width: 200px;
+ margin-right: 10px;
+ }
+ &:last-of-type {
+ margin-right: 0px;
+ margin-left: 15px;
+ }
+ }
+`
+
+export const Flex = styled.div`
+ display: flex;
+ justify-content: space-between;
+ gap: 0px 10px;
+
+ > div {
+ display: flex;
+ gap: 0px 5px;
+ white-space: initial;
+ }
+`
+export const Token = styled.img`
+ max-width: 32px;
+ width: 100%;
+ height: auto;
+ margin-right: 10px;
+`
diff --git a/packages/boba/gateway/src/components/stake/transactionList/types.ts b/packages/boba/gateway/src/components/stake/transactionList/types.ts
new file mode 100644
index 0000000000..1e297d6e4b
--- /dev/null
+++ b/packages/boba/gateway/src/components/stake/transactionList/types.ts
@@ -0,0 +1,10 @@
+type TransactionType = {
+ stakeId: number
+ depositTimestamp: number
+ depositAmount: number
+ isActive: boolean
+}
+
+export interface TransactionListInterface {
+ stakeInfo: TransactionType
+}
diff --git a/packages/boba/gateway/src/components/transaction/Transaction.js b/packages/boba/gateway/src/components/transaction/Transaction.js
deleted file mode 100644
index 971f001087..0000000000
--- a/packages/boba/gateway/src/components/transaction/Transaction.js
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
-Copyright 2021-present Boba Network.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License. */
-
-import React, { useState } from 'react'
-
-import { Typography, Fade, useMediaQuery, useTheme } from '@mui/material'
-import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
-
-import * as S from './Transaction.styles'
-
-import truncate from 'truncate-middle'
-import networkService from 'services/networkService'
-import { formatDate } from 'util/dates'
-
-function Transaction({
- time,
- timeLabel = null,
- chain,
- typeTX,
- blockNumber,
- detail,
- oriChain,
- oriHash,
- amountTx,
- completion = '',
- tx_ref = null,
- eventType,
- toChain,
-}) {
- const [dropDownBox, setDropDownBox] = useState(false)
-
- const theme = useTheme()
- const isMobile = useMediaQuery(theme.breakpoints.down('md'))
- const isNotFullScreen = useMediaQuery(theme.breakpoints.down(1920))
-
- const chainLink = ({ chain, hash }) => {
- const network = networkService.networkConfig
- if (!!network && !!network[chain]) {
- return `${network[chain].transaction}${hash}`
- }
- return ''
- }
-
- function renderDetailRedesign() {
- if (!detail) {
- return null
- }
-
- let prefix = 'L2'
- if (oriChain === 'L2') prefix = 'L1'
-
- return (
-
-
-
-
- {prefix} Hash:
-
- {isMobile ? truncate(detail.hash, 6, 6, '...') : detail.hash}
-
-
-
-
- {prefix} Block: {detail.blockNumber}
-
-
- {prefix} Block Hash:
-
- {detail.blockHash}
-
-
-
- {prefix} From:
-
- {detail.from}
-
-
-
- {prefix} To:
-
- {detail.to}
-
-
-
-
-
- )
- }
-
- return (
-
-
-
-
-
-
-
-
-
- {blockNumber}
-
-
- {typeTX}
-
- {eventType ? (
-
- {eventType}
-
- ) : null}
- {amountTx ? (
-
- {amountTx}
-
- ) : null}
-
-
-
-
- {!!detail && (
- {
- setDropDownBox(!dropDownBox)
- }}
- >
- More Information{' '}
-
-
- )}
-
-
-
- {dropDownBox ? renderDetailRedesign() : null}
-
- )
-}
-
-export default Transaction
diff --git a/packages/boba/gateway/src/components/transaction/Transaction.styles.js b/packages/boba/gateway/src/components/transaction/Transaction.styles.js
deleted file mode 100644
index a7564b9b46..0000000000
--- a/packages/boba/gateway/src/components/transaction/Transaction.styles.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import { styled } from '@mui/material/styles'
-import { Box, Grid } from '@mui/material'
-
-export const Wrapper = styled(Box)(({ theme, ...props }) => ({
- borderBottom: theme.palette.mode === 'light' ? '1px solid #c3c5c7' : '1px solid #192537',
- borderRadius: '0',
- background: theme.palette.background.secondary,
- [theme.breakpoints.down('md')]: {
- //padding: '30px 10px',
- },
- [theme.breakpoints.up('md')]: {
- padding: '10px',
- },
-}));
-
-export const GridContainer = styled(Grid)(({theme})=>({
- [theme.breakpoints.down('md')]:{
- justifyContent: 'flex-start'
- }
-}))
-
-export const GridItemTag = styled(Grid)(({ theme, ...props }) => ({
- display: 'flex',
- alignItems: 'center',
- [theme.breakpoints.down('md')]:{
- padding: `${props.xs === 12 ? '20px 0px 0px': 'inherit'}`
- }
-}))
-
-export const DropdownWrapper = styled(Box)`
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- align-items: flex-start;
- gap: 5px;
- width: 100%;
- margin-top: 10px;
- padding: 12px;
- background-color: ${props => props.theme.palette.background.secondary};
- text-align: center;
-`;
-
-export const DropdownContent = styled(Box)(({ theme }) => ({
- display: 'flex',
- justifyContent: 'space-between',
- [theme.breakpoints.down('md')]: {
- flexDirection: 'column',
- gap: '5px',
- padding: '5px'
- },
- [theme.breakpoints.up('md')]: {
- flexDirection: 'row',
- gap: '16px',
- },
-}));
-
diff --git a/packages/boba/gateway/src/containers/Bridging/BridgeHeader/index.tsx b/packages/boba/gateway/src/containers/Bridging/BridgeHeader/index.tsx
index 62ae9fdf0f..6e434cb672 100644
--- a/packages/boba/gateway/src/containers/Bridging/BridgeHeader/index.tsx
+++ b/packages/boba/gateway/src/containers/Bridging/BridgeHeader/index.tsx
@@ -27,7 +27,7 @@ const BridgeHeader = (props: Props) => {
diff --git a/packages/boba/gateway/src/containers/Bridging/BridgeInput/EmergencySwap/index.tsx b/packages/boba/gateway/src/containers/Bridging/BridgeInput/EmergencySwap/index.tsx
new file mode 100644
index 0000000000..31448bcf9d
--- /dev/null
+++ b/packages/boba/gateway/src/containers/Bridging/BridgeInput/EmergencySwap/index.tsx
@@ -0,0 +1,88 @@
+import React, { FC, useEffect, useState } from 'react'
+import { useDispatch, useSelector } from 'react-redux'
+import {
+ selectAccountEnabled,
+ selectActiveNetwork,
+ selectLayer,
+ selectlayer2Balance,
+} from 'selectors'
+import networkService from 'services/networkService'
+
+import { getETHMetaTransaction } from 'actions/setupAction'
+import { openAlert } from 'actions/uiAction'
+import BN from 'bignumber.js'
+import { isEqual } from 'lodash'
+import { logAmount } from 'util/amountConvert'
+import { LAYER } from 'util/constant'
+import { NETWORK } from 'util/network/network.util'
+import { SwapAction, SwapAlert, SwapContainer } from './styles'
+
+interface Props {}
+
+const EmergencySwap: FC = (props) => {
+ const network = useSelector(selectActiveNetwork())
+ const accountEnabled = useSelector(selectAccountEnabled())
+ const l2Balances = useSelector(selectlayer2Balance, isEqual)
+ const layer = useSelector(selectLayer())
+ const [tooSmallSec, setTooSmallSec] = useState(false)
+ const dispatch = useDispatch()
+
+ useEffect(() => {
+ if (accountEnabled && l2Balances.length > 0) {
+ const l2BalanceSec = l2Balances.find(
+ (i: any) => i.symbol === networkService.L1NativeTokenSymbol
+ )
+
+ if (l2BalanceSec && l2BalanceSec.balance) {
+ // FOR ETH MIN BALANCE 0.003ETH for other secondary tokens 1
+ const minBalance = network === NETWORK.ETHEREUM ? 0.003 : 1
+ setTooSmallSec(
+ new BN(logAmount(l2BalanceSec.balance, 18)).lt(new BN(minBalance))
+ )
+ } else {
+ // in case of zero ETH balance we are setting tooSmallSec
+ setTooSmallSec(true)
+ }
+ }
+ }, [l2Balances, accountEnabled, network])
+
+ const emergencySwap = async () => {
+ const res = await dispatch(getETHMetaTransaction())
+ if (res) {
+ dispatch(openAlert('Emergency Swap submitted'))
+ }
+ }
+
+ const alertContent = () => {
+ if (NETWORK.ETHEREUM === network) {
+ return `Using BOBA requires a minimum ETH balance (of 0.002 ETH) regardless of your fee setting,
+ otherwise MetaMask may incorrectly reject transactions. If you ran out of ETH, use EMERGENCY SWAP to swap BOBA
+ for 0.005 ETH at market rates.`
+ } else {
+ return `Using ${networkService.L1NativeTokenSymbol} requires a minimum BOBA
+ balance (of 1 BOBA) regardless of your fee setting, otherwise
+ MetaMask may incorrectly reject transactions. If you ran out of
+ BOBA, use EMERGENCY SWAP to swap ${networkService.L1NativeTokenSymbol} for 1 BOBA at market rates.`
+ }
+ }
+
+ if (layer === LAYER.L2 && tooSmallSec) {
+ return (
+
+ {alertContent()}
+ {
+ emergencySwap()
+ }}
+ label="Emergency Swap"
+ />
+
+ )
+ } else {
+ return null
+ }
+}
+
+export default EmergencySwap
diff --git a/packages/boba/gateway/src/containers/Bridging/BridgeInput/EmergencySwap/styles.ts b/packages/boba/gateway/src/containers/Bridging/BridgeInput/EmergencySwap/styles.ts
new file mode 100644
index 0000000000..c09d41d002
--- /dev/null
+++ b/packages/boba/gateway/src/containers/Bridging/BridgeInput/EmergencySwap/styles.ts
@@ -0,0 +1,35 @@
+import { Button, Typography } from 'components/global'
+import styled from 'styled-components'
+
+export const SwapContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ padding: 10px;
+ gap: 8px;
+ border-radius: 8px;
+ border: 1px solid
+ ${({ theme: { colors, name } }) =>
+ name === 'light' ? colors.gray[600] : colors.green[300]};
+ background: ${({ theme: { name } }) =>
+ name === 'light' ? 'transparant' : 'rgba(238, 238, 238, 0.05)'};
+`
+export const SwapAlert = styled(Typography).attrs({
+ variant: 'body3',
+})`
+ font-weight: 400;
+ line-height: normal;
+ color: ${({ theme, color }) =>
+ color
+ ? color
+ : theme.name === 'light'
+ ? theme.colors.gray[700]
+ : theme.colors.gray[100]};
+`
+export const SwapAction = styled(Button)`
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-item: center;
+ justify-content: center;
+`
diff --git a/packages/boba/gateway/src/containers/Bridging/BridgeInput/Fee/index.tsx b/packages/boba/gateway/src/containers/Bridging/BridgeInput/Fee/index.tsx
index ac625ee971..fdc4b968bc 100644
--- a/packages/boba/gateway/src/containers/Bridging/BridgeInput/Fee/index.tsx
+++ b/packages/boba/gateway/src/containers/Bridging/BridgeInput/Fee/index.tsx
@@ -43,7 +43,11 @@ const Fee = (props: Props) => {
const estimateTime = () => {
if (bridgeType === BRIDGE_TYPE.CLASSIC) {
- return '7 days'
+ if (layer === LAYER.L1) {
+ return '13 ~ 14mins.'
+ } else {
+ return '7 days'
+ }
} else {
if (layer === LAYER.L1) {
return '1 ~ 5min.'
diff --git a/packages/boba/gateway/src/containers/Bridging/BridgeInput/index.tsx b/packages/boba/gateway/src/containers/Bridging/BridgeInput/index.tsx
index 6ace07b910..06296d56ae 100644
--- a/packages/boba/gateway/src/containers/Bridging/BridgeInput/index.tsx
+++ b/packages/boba/gateway/src/containers/Bridging/BridgeInput/index.tsx
@@ -1,4 +1,4 @@
-import React, { FC } from 'react'
+import React, { FC, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { openModal } from 'actions/uiAction'
import { selectAccountEnabled, selectTokenToBridge } from 'selectors'
@@ -24,6 +24,8 @@ import {
TokenSymbol,
} from './styles'
import { SectionLabel } from '../chain/styles'
+import bobaLogo from 'assets/images/Boba_Logo_White_Circle.png'
+import EmergencySwap from './EmergencySwap'
type Props = {}
@@ -47,12 +49,16 @@ const BridgeInput: FC = (props) => {
- Amount
+ Token
openTokenPicker()}>
{token && (
= (props) => {
)}
{token && }
+
)
}
diff --git a/packages/boba/gateway/src/containers/Bridging/BridgeInput/styles.ts b/packages/boba/gateway/src/containers/Bridging/BridgeInput/styles.ts
index 32eb1836bc..6097abcfca 100644
--- a/packages/boba/gateway/src/containers/Bridging/BridgeInput/styles.ts
+++ b/packages/boba/gateway/src/containers/Bridging/BridgeInput/styles.ts
@@ -1,6 +1,6 @@
import { Svg, Typography } from 'components/global'
import styled, { css } from 'styled-components'
-import ArrowDown from 'images/icons/arrowdown.svg'
+import ArrowDown from 'assets/images/icons/arrowdown.svg'
import { mobile } from 'themes/screens'
export const BridgeInputContainer = styled.div`
@@ -88,10 +88,10 @@ export const TokenLabel = styled(Typography).attrs({
export const TokenPickerIcon = styled.div`
justify-self: flex-end;
`
-export const DownArrow = styled(Svg).attrs({
+export const DownArrow = styled(Svg).attrs(({ theme }) => ({
src: ArrowDown,
- fill: '#fff',
-})``
+ fill: `${theme.name === 'light' ? '#000' : '#fff'}`,
+}))``
export const ReceiveAmount = styled(Typography).attrs({
variant: 'title',
diff --git a/packages/boba/gateway/src/containers/Bridging/BridgeTypeSelector/style.ts b/packages/boba/gateway/src/containers/Bridging/BridgeTypeSelector/style.ts
index 6936c8150b..5acb28a195 100644
--- a/packages/boba/gateway/src/containers/Bridging/BridgeTypeSelector/style.ts
+++ b/packages/boba/gateway/src/containers/Bridging/BridgeTypeSelector/style.ts
@@ -22,7 +22,6 @@ export const BridgeTabItem = styled.div<{
font-style: normal;
font-weight: 700;
line-height: normal;
- border-radius: 8px;
font-size: ${(props) => props.theme.text.body1};
cursor: pointer;
background: transparent;
@@ -40,4 +39,11 @@ export const BridgeTabItem = styled.div<{
: props.theme.colors.gray[600]};
background: ${props.theme.colors.green[300]};
`};
+
+ &:nth-child(odd) {
+ border-radius: 8px 0 0 8px;
+ }
+ &:nth-child(even) {
+ border-radius: 0 8px 8px 0;
+ }
`
diff --git a/packages/boba/gateway/src/containers/Bridging/chain/styles.ts b/packages/boba/gateway/src/containers/Bridging/chain/styles.ts
index 010231019c..c2426b93a6 100644
--- a/packages/boba/gateway/src/containers/Bridging/chain/styles.ts
+++ b/packages/boba/gateway/src/containers/Bridging/chain/styles.ts
@@ -1,8 +1,8 @@
import { Svg, Typography } from 'components/global'
import styled from 'styled-components'
-import ArrowDown from 'images/icons/arrowdown.svg'
-import Switch from 'images/icons/switchIcon.svg'
+import ArrowDown from 'assets/images/icons/arrowdown.svg'
+import Switch from 'assets/images/icons/switchIcon.svg'
export const ChainContainer = styled.div`
display: flex;
@@ -44,7 +44,8 @@ export const ChainPicker = styled.div`
export const ChainIcon = styled.div`
display: flex;
- align-items: center;
+ width: 30px;
+ height: 30px;
`
export const ChainPickerPlaceHolder = styled(Typography).attrs({
variant: 'body1',
diff --git a/packages/boba/gateway/src/containers/Global.styles.js b/packages/boba/gateway/src/containers/Global.styles.js
index 6209b36ece..b98b035631 100644
--- a/packages/boba/gateway/src/containers/Global.styles.js
+++ b/packages/boba/gateway/src/containers/Global.styles.js
@@ -101,13 +101,14 @@ export const footerLink = styled(IconButton)(({ theme }) => ({
export const PageSwitcher = styled(Box)(({ theme }) => ({
width: 'fit-content',
padding: '3px',
- background: theme.palette.mode === 'light' ? 'rgba(3, 19, 19, 0.04)' : 'rgba(255, 255, 255, 0.04)',
+ background: theme.palette.mode === 'light' ? '#F0F1EA' : '#262626',
cursor: 'pointer',
display: 'flex',
borderRadius: '12px',
height: '48px',
+ border:theme.palette.mode === 'light' ? '1px solid #DEE0D8' : '0px',
'span': {
- padding: '2px 15px',
+ padding: '2px 25px',
fontWeight: 'bold',
borderRadius: '12px',
display: 'flex',
@@ -115,7 +116,7 @@ export const PageSwitcher = styled(Box)(({ theme }) => ({
alignItems: 'center',
'&.active': {
color: '#031313',
- background: theme.palette.mode === 'dark'? '#BAE21A' :'#1CD6D1',
+ background: '#AEDB01',
}
},
[ theme.breakpoints.down('sm') ]: {
diff --git a/packages/boba/gateway/src/containers/VoteAndDao/Vote/Pools/poolListItem.js b/packages/boba/gateway/src/containers/VoteAndDao/Vote/Pools/poolListItem.js
index 7fa0438fd0..88de76bbdd 100644
--- a/packages/boba/gateway/src/containers/VoteAndDao/Vote/Pools/poolListItem.js
+++ b/packages/boba/gateway/src/containers/VoteAndDao/Vote/Pools/poolListItem.js
@@ -17,7 +17,7 @@ import React, { useEffect, useState } from 'react'
import { Box, Typography, Slider, styled } from '@mui/material'
import Button from 'components/button/Button'
-import bobaLogo from 'images/boba-token.svg'
+import bobaLogo from 'assets/images/boba-token.svg'
import * as G from 'containers/Global.styles'
diff --git a/packages/boba/gateway/src/containers/VoteAndDao/Vote/VeNfts/VeNfts.list.js b/packages/boba/gateway/src/containers/VoteAndDao/Vote/VeNfts/VeNfts.list.js
index b399b6eb84..cd0bb99e52 100644
--- a/packages/boba/gateway/src/containers/VoteAndDao/Vote/VeNfts/VeNfts.list.js
+++ b/packages/boba/gateway/src/containers/VoteAndDao/Vote/VeNfts/VeNfts.list.js
@@ -5,7 +5,7 @@ import CheckMarkIcon from '@mui/icons-material/CheckCircleOutline'
import Carousel from 'react-multi-carousel'
import "react-multi-carousel/lib/styles.css";
-import BobaNFTGlass from 'images/boba2/BobaNFTGlass.svg'
+import BobaNFTGlass from 'assets/images/boba2/BobaNFTGlass.svg'
import * as G from 'containers/Global.styles'
diff --git a/packages/boba/gateway/src/containers/bobaScope/BobaScope.js b/packages/boba/gateway/src/containers/bobaScope/BobaScope.js
index d81279ebf4..648bf5aba7 100644
--- a/packages/boba/gateway/src/containers/bobaScope/BobaScope.js
+++ b/packages/boba/gateway/src/containers/bobaScope/BobaScope.js
@@ -28,7 +28,6 @@ import { fetchSevens, fetchFastExits } from 'actions/networkAction'
import { selectBaseEnabled, selectActiveDataTab, selectSevens, selectFastExits } from 'selectors'
import Tabs from 'components/tabs/Tabs'
-import Input from 'components/input/Input'
import Sevens from './Sevens'
import FastExits from './FastExits'
@@ -36,7 +35,9 @@ import FastExits from './FastExits'
import useInterval from 'hooks/useInterval'
import { POLL_INTERVAL } from 'util/constant'
-import { ContentContainer, Header, ScopePageContainer } from './History.styles';
+import {Header, BobaScopeContainer, ContentContainer} from './styles'
+import { TabComponent } from 'components/global/tabs';
+import { SearchInput } from 'components/global/searchInput';
function BobaScope() {
@@ -70,43 +71,32 @@ function BobaScope() {
}, POLL_INTERVAL)
return (
-
+
- { dispatch(setActiveDataTab(tab)) }}
- activeTab={activeTab}
- tabs={[ 'Seven Day Queue', 'Fast Exits' ]}
+ )
+ },
+ {label:"Fast Exits",
+ content:( )
+ }
+ ]}
/>
-
- {activeTab === 'Seven Day Queue' && (
-
- )}
- {activeTab === 'Fast Exits' && (
-
- )}
-
+
);
}
diff --git a/packages/boba/gateway/src/containers/bobaScope/FastExits.js b/packages/boba/gateway/src/containers/bobaScope/FastExits.js
index e6bfb7d9ff..bb349abc83 100644
--- a/packages/boba/gateway/src/containers/bobaScope/FastExits.js
+++ b/packages/boba/gateway/src/containers/bobaScope/FastExits.js
@@ -23,7 +23,7 @@ import { Pager } from 'components'
import FastExit from 'components/seven/FastExit'
import styles from './Transactions.module.scss'
-import * as S from './History.styles'
+import { HistoryContainer, Content } from './styles'
const PER_PAGE = 10
@@ -50,7 +50,7 @@ function FastExits({ searchData, data }) {
return (
-
+
-
+
{!paginatedData.length && !loading && (
Scanning for pending fast exits...
)}
@@ -80,10 +80,10 @@ function FastExits({ searchData, data }) {
/>
)
})}
-
+
-
+
);
}
diff --git a/packages/boba/gateway/src/containers/bobaScope/History.styles.js b/packages/boba/gateway/src/containers/bobaScope/History.styles.js
deleted file mode 100644
index a295c76449..0000000000
--- a/packages/boba/gateway/src/containers/bobaScope/History.styles.js
+++ /dev/null
@@ -1,118 +0,0 @@
-import styled from 'styled-components';
-import {Typography, Box} from '@mui/material'
-
-export const HistoryContainer = styled.div`
- background: ${props => props.theme.palette.background.secondary};
- border-radius: 8px;
- margin-bottom: 20px;
-`;
-
-export const TableHeading = styled(Box)`
- padding: 10px 20px;
- border-radius: 6px;
- display: flex;
- align-items: flex-start;
- justify-content: space-between;
-`;
-
-export const TableHeadingItem = styled(Typography)`
- width: 20%;
- gap: 5px;
- text-align: flex-start;
- opacity: 0.7;
-`;
-
-export const Content = styled(Box)`
- display: flex;
- flex-direction: column;
- gap: 5px;
- margin-bottom: 10px;
- padding: 10px 20px;
- border-radius: 6px;
-`;
-
-export const Header = styled(Box)(({ theme }) => ({
- display: 'flex',
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- marginBottom: '20px',
- [theme.breakpoints.down('md')]: {
- flexDirection: 'column',
- alignItems: 'flex-start',
- gap: '20px',
- },
-}));
-
-
-export const ScopePageContainer = styled(Box)(({ theme }) => ({
- margin: '0px auto',
- display: 'flex',
- flexDirection: 'column',
- justifyContent: 'space-around',
- padding: '10px',
- paddingTop: '0px',
- width: '70%',
- [ theme.breakpoints.between('md', 'lg') ]: {
- width: '90%',
- padding: '0px',
- },
- [ theme.breakpoints.between('sm', 'md') ]: {
- width: '90%',
- padding: '0px',
- },
- [ theme.breakpoints.down('sm') ]: {
- width: '100%',
- padding: '0px',
- },
-}));
-
-
-export const LayerAlert = styled(Box)(({ theme }) => ({
- width: "100%",
- display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'center',
- gap: '30px',
- borderRadius: '8px',
- margin: '20px 0px',
- padding: '25px',
- background: theme.palette.background.secondary,
- [ theme.breakpoints.up('md') ]: {
- padding: '25px 50px',
- },
-
-}));
-
-export const AlertText = styled(Typography)(({ theme }) => ({
- marginLeft: '10px',
- flex: 4,
- [ theme.breakpoints.up('md') ]: {
- },
-}));
-
-export const AlertInfo = styled(Box)`
- display: flex;
- justify-content: space-around;
- align-items: center;
- flex: 1;
-`;
-
-
-export const SearchInputContainer = styled.div`
- width: 250px !important;
- @media (max-width: 768px) {
- width: 100% !important;
- }
-
-`
-
-export const ContentContainer = styled.div`
- display: flex;
- flex-direction: row;
- width: 100%;
- @media (max-width: 768px) {
- flex-direction: column;
- }
-`
-
diff --git a/packages/boba/gateway/src/containers/bobaScope/Sevens.js b/packages/boba/gateway/src/containers/bobaScope/Sevens.js
index 1f599aa13e..0a823b2bc5 100644
--- a/packages/boba/gateway/src/containers/bobaScope/Sevens.js
+++ b/packages/boba/gateway/src/containers/bobaScope/Sevens.js
@@ -23,7 +23,7 @@ import { Pager } from 'components'
import Seven from 'components/seven/Seven'
import styles from './Transactions.module.scss'
-import * as S from './History.styles'
+import { HistoryContainer, Content } from './styles'
const PER_PAGE = 10
@@ -49,8 +49,8 @@ function Sevens({ searchData, sevens }) {
if (totalNumberOfPages === 0) totalNumberOfPages = 1
return (
-
-
+
+
-
+
{!paginatedSevens.length && !loading && (
Scanning for pending 7 day exits...
)}
@@ -80,10 +80,10 @@ function Sevens({ searchData, sevens }) {
/>
)
})}
-
+
-
+
);
}
diff --git a/packages/boba/gateway/src/containers/bobaScope/styles.ts b/packages/boba/gateway/src/containers/bobaScope/styles.ts
new file mode 100644
index 0000000000..3254df52cd
--- /dev/null
+++ b/packages/boba/gateway/src/containers/bobaScope/styles.ts
@@ -0,0 +1,39 @@
+import styled, { css } from 'styled-components'
+import { mobile, screen, sdesktop } from 'themes/screens'
+import { Svg, Typography } from 'components/global'
+
+export const HistoryContainer = styled.div`
+ border-radius: 8px;
+ margin-bottom: 20px;
+`
+
+export const Header = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+`
+
+export const BobaScopeContainer = styled.div`
+ margin: 0px auto;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-around;
+ padding: 10px;
+ width: 70%;
+`
+
+export const ContentContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+`
+
+export const Content = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ margin-bottom: 10px;
+ border-radius: 6px;
+`
diff --git a/packages/boba/gateway/src/containers/bridge/Bridge.styles.js b/packages/boba/gateway/src/containers/bridge/Bridge.styles.js
index f4b337e86f..4408e3c0b0 100644
--- a/packages/boba/gateway/src/containers/bridge/Bridge.styles.js
+++ b/packages/boba/gateway/src/containers/bridge/Bridge.styles.js
@@ -1,6 +1,6 @@
import styled from '@emotion/styled'
import {Box, Typography} from "@mui/material"
-import bobaGlassIcon from 'images/boba2/boba_glass.svg'
+import bobaGlassIcon from 'assets/images/boba2/boba_glass.svg'
export const PageContainer = styled(Box)(({ theme }) => ({
margin: '20px auto',
marginBottom: theme.palette.spacing.toFooter,
diff --git a/packages/boba/gateway/src/containers/bridge/bobaBridge/bobaBridge.js b/packages/boba/gateway/src/containers/bridge/bobaBridge/bobaBridge.js
index 1a042d0fc5..15a981f68d 100644
--- a/packages/boba/gateway/src/containers/bridge/bobaBridge/bobaBridge.js
+++ b/packages/boba/gateway/src/containers/bridge/bobaBridge/bobaBridge.js
@@ -35,30 +35,25 @@ import {
selectBridgeTokens,
selectMultiBridgeMode,
selectActiveNetworkIcon,
- selectActiveNetworkName,
} from 'selectors'
import { resetToken, setMultiBridgeMode } from 'actions/bridgeAction'
import { setConnectETH, setConnectBOBA } from 'actions/setupAction'
-import { L1_ICONS, L2_ICONS } from 'util/network/network.util'
-import { DEFAULT_NETWORK, LAYER } from 'util/constant'
+import { LAYER } from 'util/constant'
import { AvailableBridges } from 'components'
+import { ChainLabel } from 'components/bridge/ChainLabel'
-
-function BobaBridge() {
+const BobaBridge = () => {
const layer = useSelector(selectLayer())
const accountEnabled = useSelector(selectAccountEnabled())
const multibridgeMode = useSelector(selectMultiBridgeMode())
const tokens = useSelector(selectBridgeTokens())
- const networkName = useSelector(selectActiveNetworkName())
- const icon = useSelector(selectActiveNetworkIcon())
const userWallet = useSelector(selectWalletAddress())
- const L1Icon = L1_ICONS[icon]
- const L2Icon = L2_ICONS[icon]
+
const dispatch = useDispatch()
const [toL2, setToL2] = useState(true)
@@ -73,7 +68,7 @@ function BobaBridge() {
setToL2(isL1);
}, [isL1]);
- async function switchDirection() {
+ const switchDirection = async () => {
if (accountEnabled) {
if (isL1) dispatch(setConnectBOBA(true))
else dispatch(setConnectETH(true))
@@ -90,19 +85,7 @@ function BobaBridge() {
await dispatch(multibridgeMode ? resetToken() : setMultiBridgeMode(!multibridgeMode))
}
- const L1ChainLabel = () => {
- return (
-
- {networkName[ 'l1' ] || DEFAULT_NETWORK.NAME.L1}
- )
- }
- const L2ChainLabel = () => {
- return (
-
- {networkName[ 'l2' ] || DEFAULT_NETWORK.NAME.L2}
- )
- }
const ChainSwitchIcon = () => {
return {
- const config = () => ({
- from: toL2? : ,
- to: toL2? :
- });
return (
<>
@@ -141,7 +120,7 @@ function BobaBridge() {
From
- { config().from }
+
- { config().to }
+
diff --git a/packages/boba/gateway/src/containers/dao/OldDao.js b/packages/boba/gateway/src/containers/dao/OldDao.js
index 9afbb7951e..c420906816 100644
--- a/packages/boba/gateway/src/containers/dao/OldDao.js
+++ b/packages/boba/gateway/src/containers/dao/OldDao.js
@@ -146,7 +146,9 @@ const OldDao = () => {
}}
>
- BOBA:
+
+ BOBA:
+
{
- xBOBA:
+
+ xBOBA:
+
({
- margin: '0px auto',
- marginBottom: theme.palette.spacing.toFooter,
- display: 'flex',
- flexDirection: 'column',
- justifyContent: 'space-around',
- padding: '10px',
- paddingTop: '0px',
- width: '70%',
- gap: '10px',
- [theme.breakpoints.between('md', 'lg')]: {
- width: '90%',
- padding: '0px',
- },
- [theme.breakpoints.between('sm', 'md')]: {
- width: '90%',
- padding: '0px',
- },
- [theme.breakpoints.down('sm')]: {
- width: '100%',
- padding: '0px',
- },
+export const DaoPageContainer = styled.div`
+ margin: 0px auto;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-around;
+ padding: 10px
+ padding-top: 0px;
+ width:100%;
+ max-width:1200px;
+ gap: '10px';
+ ${mobile(css`
+ text-align: center;
+ overflow: hidden;
+ padding:0px 15px;
+ `)}
+`
-}));
+export const DaoPageContent = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: flex-start;
+ padding-top: 0px;
+ gap: 10px 35px;
+ ${tablet(css`
+ flex-direction: column;
+ padding:0px;
+ `)}
+`
-export const DaoPageContent = styled(Box)(({ theme }) => ({
- display: 'flex',
- flexDirection: 'row',
- justifyContent: 'center',
- alignItems: 'flex-start',
- paddingTop: '0px',
- gap: '10px 35px',
- [theme.breakpoints.down('sm')]: {
- flexDirection: 'column'
- },
-}));
+export const DaoWalletContainer = styled.div`
+ display: 'flex';
+ flex-direction: column;
+ padding: 0px 20px;
+ width: 30%;
+ min-width: 330px;
+ gap: 10px;
+ background: ${(props)=> props.theme.colors.box.background};
-export const DaoWalletContainer = styled(Box)(({ theme }) => ({
- display: 'flex',
- flexDirection: 'column',
- padding: '0px 20px',
- width: '30%',
- minWidth: '330px',
- gap: '10px',
- borderRadius: theme.palette.primary.borderRadius,
- background: theme.palette.background.glassy,
- [theme.breakpoints.down('sm')]: {
- width: '100%',
- },
-}));
+ ${tablet(css`
+ width: 100%;
+ `)}
+`
-export const VerticalDivisor = styled(Box)(({ theme }) => ({
- width:'1px',
- background:"rgba(84, 84, 84, 1)",
- height:'47px',
- margin:'0px 50px'
-}));
+export const VerticalDivisor = styled.div`
+ width:1px;
+ background:rgba(84, 84, 84, 1);
+ height:47px;
+ margin:0px 50px;
+`
-export const DaoProposalContainer = styled(Box)(({ theme }) => ({
- width: '70%',
- display: 'flex',
- flexDirection: 'column',
- justifyContent: 'flex-start',
- padding: '0',
- minHeight: '500px',
- [theme.breakpoints.down('sm')]: {
- width: '100%',
- padding: '0 20px',
- },
-}));
+export const DaoProposalContainer = styled.div`
+ width: 70%;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ padding: 0;
+ min-height: 500px;
+ ${tablet(css`
+ width: 100%;
+ padding:0px;
+ `)}
-export const DaoProposalHead = styled(Box)(({ theme }) => ({
- display: 'flex',
- alignItems: 'center',
- alignSelf: 'flex-start',
- justifyContent: 'space-between',
- padding: '15px 0px',
- width: '100%',
- margin: '5px',
- [theme.breakpoints.down('sm')]: {
- padding: '0px',
- },
-}))
+`
-export const DaoProposalListContainer = styled(Box)(({ theme }) => ({
- display:'flex',
- flexDirection:'column',
- margin: '10px auto',
- borderRadius: '8px',
- padding: '20px 0px 20px 0px',
- width: '100%',
- gap:'10px 0px',
- '.loadingContainer' : {
+export const DaoProposalHead = styled.div`
+ display: flex;
+ align-items: center;
+ align-self: flex-start;
+ justify-content: space-between;
+ padding: 15px 0px;
+ width: 100%;
+ margin: 5px;
+ ${mobile(css`
+ padding:0px;
+ `)}
+`
+
+export const DaoProposalListContainer = styled.div`
+ display:flex;
+ flex-direction:column;
+ margin: 10px auto;
+ border-radius: 8px;
+ padding: 20px 0px 20px 0px;
+ width: 100%;
+ gap:10px 0px;
+
+ .loadingContainer {
padding: '10px auto',
- },
- [theme.breakpoints.down('sm')]: {
- padding: '0px',
- },
-}))
+ };
+
+ ${mobile(css`
+ padding: 0px;
+ `)}
+`
-export const DaoWalletAction = styled(Box)(({ theme }) => ({
- display: 'flex',
- justifyContent: 'space-around',
- width: '100%',
-}));
+export const DaoWalletAction = styled.div`
+ display: flex;
+ justify-content: space-around;
+ width: 100%;
+`
diff --git a/packages/boba/gateway/src/containers/earn/Earn.js b/packages/boba/gateway/src/containers/earn/Earn.js
index d799756d29..9887f84780 100644
--- a/packages/boba/gateway/src/containers/earn/Earn.js
+++ b/packages/boba/gateway/src/containers/earn/Earn.js
@@ -19,7 +19,6 @@
import React, { useState, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux';
-import { Box, FormControlLabel, Checkbox, Typography, useMediaQuery, useTheme } from '@mui/material'
import { HelpOutline } from '@mui/icons-material'
import {
@@ -44,21 +43,22 @@ import LayerSwitcher from 'components/mainMenu/layerSwitcher/LayerSwitcher'
import networkService from 'services/networkService'
-import * as S from './Earn.styles'
-import * as G from 'containers/Global.styles'
+import * as S from './styles'
import { fetchBalances } from 'actions/networkAction';
import { TableHeader } from 'components/global/table'
+import { CheckboxWithLabel } from 'components/global/checkbox'
+import { tableHeaderOptions } from './consts'
+import { Typography } from 'components/global/typography'
+import { toLayer } from './types'
-function Earn() {
- const [showMDO, setShowMDO] = useState(false)
- const [showMSO, setShowMSO] = useState(false)
- const [lpChoice, setLpChoice] = useState(networkService.L1orL2 === 'L1' ? 'L1LP' : 'L2LP')
- const [poolTab, setPoolTab] = useState(networkService.L1orL2 === 'L1' ? 'Ethereum Pool' : 'Boba L2 Pool')
+import { BridgeTooltip } from './tooltips'
+const Earn = () => {
const dispatch = useDispatch();
- const theme = useTheme();
- const isMobile = useMediaQuery(theme.breakpoints.down('md'));
+
+ const activeNetworkName = useSelector(selectActiveNetworkName())
+ const layer = useSelector(selectLayer())
const userInfo = useSelector(selectUserInfo())
const poolInfo = useSelector(selectPoolInfo())
@@ -68,9 +68,25 @@ function Earn() {
const baseEnabled = useSelector(selectBaseEnabled())
const accountEnabled = useSelector(selectAccountEnabled())
- const layer = useSelector(selectLayer())
- const activeNetworkName = useSelector(selectActiveNetworkName())
+ const [showMDO, setShowMDO] = useState(false)
+ const [showMSO, setShowMSO] = useState(false)
+ const [lpChoice, setLpChoice] = useState(
+ networkService.L1orL2 === 'L1' ? 'L1LP' : 'L2LP'
+ )
+
+ const isLp1 = lpChoice === 'L1LP';
+ const isLp2 = lpChoice === 'L2LP';
+
+ const [poolTab, setPoolTab] = useState(
+ activeNetworkName[layer?.toLowerCase()]
+ )
+
+ useEffect(()=> {
+ setPoolTab(activeNetworkName[layer?.toLowerCase()])
+ }, [layer, networkService])
+
+
useEffect(() => {
if (baseEnabled) {
dispatch(getEarnInfo())
@@ -82,154 +98,118 @@ function Earn() {
}, [dispatch, baseEnabled, accountEnabled])
- function getBalance(address, chain) {
- const tokens = chain === 'L1' ? Object.values(layer1Balance) : chain === 'L2' ? Object.values(layer2Balance) : []
+ const getBalance = (address, chain) => {
+ const tokens =
+ chain === 'L1'
+ ? Object.values(layer1Balance)
+ : chain === 'L2'
+ ? Object.values(layer2Balance)
+ : []
const token = tokens.find(t => t.address.toLowerCase() === address.toLowerCase())
return token ? [token.balance, token.decimals] : [0, 0]
}
- const tableHeaderOptions = [
- {name:'Token', width:225},
- {name:'Available Balance', tooltip: 'Available Balance refers to the amount of funds currently in each pool.',width:145},
- {name:'Total Staked', tooltip: 'Total staked denotes the funds staked by liquidity providers.', width:115},
- {name:'APR', tooltip: 'The APR is the historical APR, which reflects the fees people paid to bridge and the previous usage patterns for each pool.',width:85},
- {name:'Your Stake',width:90},
- {name:'Earned',width:110},
- ]
const selectedPoolInfo = lpChoice === 'L1LP' ? poolInfo.L1LP : poolInfo.L2LP;
- const selectedNetworkConfig = lpChoice === 'L1LP' ? networkService?.networkConfig?.L1?.chainIdHex : networkService?.networkConfig?.L2?.chainIdHex;
+ const selectedNetworkConfig =
+ lpChoice === 'L1LP'
+ ? networkService?.networkConfig?.L1?.chainIdHex
+ : networkService?.networkConfig?.L2?.chainIdHex
+
+ useEffect(()=>{
+ setLpChoice(networkService.L1orL2 === 'L1' ? 'L1LP' : 'L2LP')
+ },[networkService.L1orL2])
return (
- {((layer === 'L2' && lpChoice === 'L1LP') || (layer === 'L1' && lpChoice === 'L2LP')) && (
+ {((layer === 'L2' && isLp1) || (layer === 'L1' && isLp2)) && (
- You are on {layer}. To transact on {layer === 'L1' ? 'L2' : 'L1'}, SWITCH LAYER to {layer === 'L1' ? 'L2' : 'L1'}
+ You are on {layer}. To transact on {toLayer[layer]}, SWITCH LAYER to {toLayer[layer]}
)}
-
+
-
-
+ {
setLpChoice('L1LP')
- setPoolTab('Ethereum Pool')
- }}
- variant="body2"
- component="span">
- {activeNetworkName['l1']} Pools
-
-
+ {activeNetworkName['l1']} Pools
+
+ {
setLpChoice('L2LP')
- setPoolTab('Boba L2 Pool')
- }}
- variant="body2"
- component="span">
- {activeNetworkName['l2']} Pools
-
-
+ setPoolTab(activeNetworkName['l2'])
+ }}>
+ {activeNetworkName['l2']} Pools
+
+
- setShowMDO(e.target.checked)}
- name="my tokens only"
- color="primary"
- icon={}
- />
- }
- label="My Tokens Only"
- />
- setShowMSO(e.target.checked)}
- name="my stakes only"
- color="primary"
- icon={}
- />
- }
+ setShowMSO(status)}
/>
-
- Bridging fees are proportionally distributed to stakers. The bridges are not farms.
- Your earnings only increase when someone uses the bridge you have staked into.
+ Bridging fees are proportionally distributed to stakers. The bridges
+ are not farms. Your earnings only increase when someone uses the
+ bridge you have staked into.
-
- Staking example. When you stake 10 OMG into the L2 pool, then the pool's liquidity and balance both increase by 10 OMG.
-
- Fast Bridge example. When a user bridges 10 OMG from L1 to L2 using the fast bridge,
- they send 10 OMG to the L1 pool, increasing its balance by 10 OMG. Next, 9.99 OMG flow out from the L2 pool to the user's L2 wallet, completing the bridge.
- Note that bridge operations do not change the pool's liquidity, but only its balance.
- The difference between what was deposited into the L1 pool (10 OMG) and what was sent
- to the user on the L2 (9.99 OMG), equal to 0.01 OMG, is sent to the reward pool, for harvesting by stakers.
-
- Pool rebalancing. In some circumstances, excess balances can accumulate on one chain. For example, if many people
- bridge from L1 to L2, then L1 pool balances will increase, while L2 balances will decrease. When needed, the pool operator can
- rebalance the pools, using 'classic' deposit and exit operations to move funds from one pool to another. Rebalancing takes 7 days, due to the
- 7 day fraud proof window, which also applies to the operator.
-
- Dynamic fees. The pools use an automatic supply-and-demand approach to setting the fees.
- When a pool's liquidity is low, the fees are increased to attract more liquidity into that pool and vice-versa.
-
- }
- >
+ }>
- { !isMobile && (
- )
- }
+
{Object.keys(selectedPoolInfo).map((v, i) => {
const ret = getBalance(v, lpChoice === 'L1LP' ? 'L1' : 'L2');
- if (showMDO && Number(ret[0]) === 0) return null;
+ if (showMDO && Number(ret[0]) === 0) {
+ return null
+ }
return (
);
})}
-
+
)
}
diff --git a/packages/boba/gateway/src/containers/earn/Earn.styles.js b/packages/boba/gateway/src/containers/earn/Earn.styles.js
deleted file mode 100644
index 26be8518f8..0000000000
--- a/packages/boba/gateway/src/containers/earn/Earn.styles.js
+++ /dev/null
@@ -1,189 +0,0 @@
-import { styled } from '@mui/material/styles'
-import { Box, Typography, Grid } from "@mui/material"
-
-export const EarnPageContainer = styled(Box)(({ theme }) => ({
- margin: '0px auto',
- marginBottom: theme.palette.spacing.toFooter,
- display: 'flex',
- flexDirection: 'column',
- justifyContent: 'space-around',
- padding: '10px',
- paddingTop: '0px',
- width: '70%',
- [theme.breakpoints.between('md', 'lg')]: {
- width: '90%',
- padding: '0px',
- },
- [theme.breakpoints.between('sm', 'md')]: {
- width: '90%',
- padding: '0px',
- },
- [theme.breakpoints.down('sm')]: {
- width: '100%',
- padding: '0px',
- },
-}))
-
-export const TableHeading = styled(Box)(({ theme }) => ({
- padding: "20px",
- borderTopLeftRadius: "6px",
- borderTopRightRadius: "6px",
- display: "flex",
- alignItems: "center",
- background: theme.palette.background.secondary,
- [theme.breakpoints.down('md')]: {
- marginBottom: "5px",
- },
-}))
-
-export const LayerAlert = styled(Box)(({ theme }) => ({
- width: "100%",
- display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'center',
- gap: '30px',
- borderRadius: '8px',
- margin: '20px 0px',
- padding: '25px',
- background: theme.palette.background.glassy,
- [theme.breakpoints.up('md')]: {
- padding: '25px 50px',
- },
-}))
-
-export const Help = styled(Box)(({ theme }) => ({
- width: "100%",
- display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'center',
- gap: '30px',
- margin: '10px 0px',
- padding: '10px',
- borderRadius: theme.palette.primary.borderRadius,
- background: theme.palette.background.glassy,
-}))
-
-export const AlertText = styled(Typography)(({ theme }) => ({
- marginLeft: '10px',
- flex: 4,
- [theme.breakpoints.up('md')]: {
- },
-}))
-
-export const AlertInfo = styled(Box)`
- display: flex;
- justify-content: space-around;
- align-items: center;
- flex: 1;
-`;
-
-export const Wrapper = styled(Box)(({ theme, ...props }) => ({
- borderRadius: '8px',
- // background: props.dropDownBox ? theme.palette.background.dropdown : theme.palette.background.secondary,
- [theme.breakpoints.down('md')]: {
- padding: ' 30px 10px',
- },
- [theme.breakpoints.up('md')]: {
- padding: '20px',
- },
-}))
-
-export const GridItemTagContainer = styled(Grid)(({ theme, ...props }) => ({
- spacing: 2,
- flexDirection: 'row',
- justifyContent: "left",
- alignItems: "center",
- [theme.breakpoints.down('md')]: {
- flexDirection: 'column'
- }
-}));
-
-export const GridItemTag = styled(Grid)`
- display: flex;
- flex-direction: row;
- align-items: center;
- gap:5px;
-`;
-
-export const EarnAction = styled(Box)(({theme})=>({
- display: 'flex',
- justifyContent: 'space-around',
- alignItems: 'center',
- [theme.breakpoints.down('md')]: {
- width: '100%'
- }
-}))
-
-export const EarnActionContainer = styled(Box)(({ theme }) => ({
- display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'center',
- [theme.breakpoints.down('md')]: {
- flexDirection: 'column'
- }
-}))
-
-export const EarnListContainer = styled(Box)(({theme})=>({
- [theme.breakpoints.down('md')]: {
- display: 'flex',
- flexDirection: 'column',
- gap: '5px'
- }
-}))
-
-export const BpIcon = styled('span')(({ theme }) => ({
- borderRadius: 3,
- width: 16,
- height: 16,
- boxShadow:
- theme.palette.mode === 'dark'
- ? '0 0 0 1px rgb(16 22 26 / 40%)'
- : 'inset 0 0 0 1px rgba(16,22,26,.2), inset 0 -1px 0 rgba(16,22,26,.1)',
- backgroundColor: theme.palette.mode === 'dark' ? '#394b59' : '#f5f8fa',
- backgroundImage:
- theme.palette.mode === 'dark'
- ? 'linear-gradient(180deg,hsla(0,0%,100%,.05),hsla(0,0%,100%,0))'
- : 'linear-gradient(180deg,hsla(0,0%,100%,.8),hsla(0,0%,100%,0))',
- '.Mui-focusVisible &': {
- outline: '2px auto rgba(19,124,189,.6)',
- outlineOffset: 2,
- },
- 'input:hover ~ &': {
- backgroundColor: theme.palette.mode === 'dark' ? '#30404d' : '#ebf1f5',
- },
- 'input:disabled ~ &': {
- boxShadow: 'none',
- background:
- theme.palette.mode === 'dark' ? 'rgba(57,75,89,.5)' : 'rgba(206,217,224,.5)',
- },
-}))
-
-export const PageSwitcher = styled(Box)(({ theme }) => ({
- width: 'fit-content',
- padding: '3px',
- background: theme.palette.mode === 'light' ? 'rgba(3, 19, 19, 0.04)': 'rgba(255, 255, 255, 0.04)',
- cursor: 'pointer',
- display: 'flex',
- borderRadius: '12px',
- height: '48px',
- 'span': {
- padding: '2px 15px',
- fontWeight: 'bold',
- borderRadius: '12px',
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- '&.active': {
- color: '#031313',
- background: '#BAE21A',
- }
- },
- [ theme.breakpoints.down('sm') ]: {
- width: '100%',
- padding: '0px',
- 'span': {
- width: '50%'
- }
- },
-
-}));
diff --git a/packages/boba/gateway/src/containers/earn/EarnWrapper.js b/packages/boba/gateway/src/containers/earn/EarnWrapper.js
index 3f838b4a76..55ad52b047 100644
--- a/packages/boba/gateway/src/containers/earn/EarnWrapper.js
+++ b/packages/boba/gateway/src/containers/earn/EarnWrapper.js
@@ -2,8 +2,9 @@ import { useMediaQuery, useTheme } from '@mui/material';
import React from 'react';
import Earn from './Earn';
-export default function EarnWrapper({ ...rest }) {
+const EarnWrapper = ({ ...rest }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
return ;
}
+export default EarnWrapper;
\ No newline at end of file
diff --git a/packages/boba/gateway/src/containers/earn/consts.ts b/packages/boba/gateway/src/containers/earn/consts.ts
new file mode 100644
index 0000000000..8e6bfb24e7
--- /dev/null
+++ b/packages/boba/gateway/src/containers/earn/consts.ts
@@ -0,0 +1,36 @@
+import { tabSwitcherTypes } from './types'
+
+export const TabSwitcherEnum: tabSwitcherTypes = {
+ L1LP: {
+ name: 'L1LP',
+ tab: 'Ethereum Pool',
+ },
+ L2LP: {
+ name: 'L2LP',
+ tab: 'Boba L2 Pool',
+ },
+}
+
+export const tableHeaderOptions = [
+ { name: 'Token', width: 225 },
+ {
+ name: 'Available Balance',
+ tooltip:
+ 'Available Balance refers to the amount of funds currently in each pool.',
+ width: 145,
+ },
+ {
+ name: 'Total Staked',
+ tooltip: 'Total staked denotes the funds staked by liquidity providers.',
+ width: 115,
+ },
+ {
+ name: 'APR',
+ tooltip:
+ 'The APR is the historical APR, which reflects the fees people paid to bridge and the previous usage patterns for each pool.',
+ width: 85,
+ },
+ { name: 'Your Stake', width: 90 },
+ { name: 'Earned', width: 110 },
+ { name: 'Actions', width: 75 },
+]
diff --git a/packages/boba/gateway/src/containers/earn/styles.ts b/packages/boba/gateway/src/containers/earn/styles.ts
new file mode 100644
index 0000000000..0210dfc134
--- /dev/null
+++ b/packages/boba/gateway/src/containers/earn/styles.ts
@@ -0,0 +1,147 @@
+import styled, { css } from 'styled-components'
+import { Typography } from 'components/global/typography'
+
+export const EarnPageContainer = styled.div`
+ margin: 0px auto;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-around;
+ padding: 10px;
+ padding-top: 0px;
+ width: 1025px;
+`
+
+export const TableHeading = styled.div`
+ padding: 20px,
+ border-radius: 6px 6px 0 0;
+ display: flex;
+ align-items: center;
+ background: ${(props) => props.theme.colors.box.background};
+`
+
+export const LayerAlert = styled.div`
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 30px;
+ border-radius: 8px;
+ margin: 20px 0px;
+ padding: 25px;
+ background: ${(props) => props.theme.colors.box.background};
+`
+
+export const Help = styled.div`
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 30px;
+ margin: 10px 0px;
+ padding: 10px;
+ border-radius: 8px;
+ background: ${(props) => props.theme.colors.box.background};
+`
+
+export const AlertText = styled(Typography)`
+ margin-left: 10px;
+ flex: 4;
+`
+
+export const AlertInfo = styled.div`
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ flex: 1;
+`
+
+export const Wrapper = styled.div`
+ border-radius: 8px;
+`
+
+export const GridItemTagContainer = styled.div`
+ spacing: 2,
+ flex-direction: row;
+ justify-content: left;
+ align-items: center;
+`
+
+export const GridItemTag = styled.div`
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 5px;
+`
+
+export const EarnAction = styled.div`
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+`
+
+export const EarnActionContainer = styled.div`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+`
+
+export const EarnListContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 10px 0px;
+ padding: 10px 0px;
+`
+
+export const BpIcon = styled.span`
+ border-radius: 3;
+ width: 16;
+ height: 16;
+`
+
+export const PageSwitcher = styled.div`
+ width: fit-content;
+ padding: 3px;
+ cursor: pointer;
+ display: flex;
+ border-radius: 12px;
+ height: 48px;
+ span {
+ padding: 2px 15px;
+ font-weight: bold;
+ border-radius: 12px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ &.active {
+ color: #031313;
+ background: #bae21a;
+ }
+ }
+`
+
+export const TabSwitcherContainer = styled.div`
+ display: flex;
+ padding: 4px;
+ gap: 0px 15px;
+ border-radius: 8px;
+ ${({ theme: { colors, name } }) =>
+ name === 'light'
+ ? css`
+ background: ${colors.gray[50]};
+ `
+ : css`
+ background: ${colors.gray[500]};
+ `}
+`
+
+export const Tab = styled.div<{ active: boolean }>`
+ padding: 8px 24px;
+ border-radius: 8px;
+ cursor: pointer;
+ ${(props) =>
+ props.active &&
+ `
+ color:${props.theme.colors.gray[800]};
+ background:${props.theme.colors.green[300]}
+ `}
+`
diff --git a/packages/boba/gateway/src/containers/earn/tooltips.tsx b/packages/boba/gateway/src/containers/earn/tooltips.tsx
new file mode 100644
index 0000000000..72ab532b85
--- /dev/null
+++ b/packages/boba/gateway/src/containers/earn/tooltips.tsx
@@ -0,0 +1,35 @@
+import React from 'react'
+import { Typography } from 'components/global/typography'
+
+export const BridgeTooltip = () => (
+
+ Staking example. When you stake
+ 10 BOBA into the L2 pool, then the pool's liquidity and balance both
+ increase by 10 BOBA.
+
+
+ Fast Bridge example. When a user
+ bridges 10 BOBA from L1 to L2 using the fast bridge, they send 10 BOBA to
+ the L1 pool, increasing its balance by 10 BOBA. Next, 9.99 BOBA flow out
+ from the L2 pool to the user's L2 wallet, completing the bridge. Note that
+ bridge operations do not change the pool's liquidity, but only its balance.
+ The difference between what was deposited into the L1 pool (10 BOBA) and
+ what was sent to the user on the L2 (9.99 BOBA), equal to 0.01 BOBA, is sent
+ to the reward pool, for harvesting by stakers.
+
+
+ Pool rebalancing. In some
+ circumstances, excess balances can accumulate on one chain. For example, if
+ many people bridge from L1 to L2, then L1 pool balances will increase, while
+ L2 balances will decrease. When needed, the pool operator can rebalance the
+ pools, using 'classic' deposit and exit operations to move funds from one
+ pool to another. Rebalancing takes 7 days, due to the 7 day fraud proof
+ window, which also applies to the operator.
+
+
+ Dynamic fees. The pools use an
+ automatic supply-and-demand approach to setting the fees. When a pool's
+ liquidity is low, the fees are increased to attract more liquidity into that
+ pool and vice-versa.
+
+)
diff --git a/packages/boba/gateway/src/containers/earn/types.ts b/packages/boba/gateway/src/containers/earn/types.ts
new file mode 100644
index 0000000000..363d49a570
--- /dev/null
+++ b/packages/boba/gateway/src/containers/earn/types.ts
@@ -0,0 +1,14 @@
+type poolDetail = {
+ name: string
+ tab: string
+}
+
+export type tabSwitcherTypes = {
+ L1LP: poolDetail
+ L2LP: poolDetail
+}
+
+export enum toLayer {
+ L1 = 'L2',
+ L2 = 'L1',
+}
diff --git a/packages/boba/gateway/src/containers/history/DatePicker.tsx b/packages/boba/gateway/src/containers/history/DatePicker.tsx
new file mode 100644
index 0000000000..98c53df48d
--- /dev/null
+++ b/packages/boba/gateway/src/containers/history/DatePicker.tsx
@@ -0,0 +1,132 @@
+import React, { useRef, useState, useEffect, useCallback } from 'react'
+import { subMonths } from 'date-fns'
+import {
+ DatePickerDropdown,
+ DatePickerHeader,
+ DatePickerContainer,
+} from './styles'
+import { formatDate } from 'util/dates'
+import { DayPicker, DateRange } from 'react-day-picker'
+import 'react-day-picker/dist/style.css'
+
+export interface IDatePickerProps {
+ selected: Date
+ timeFormat?: string
+ onChange: Function
+ minDate?: Date
+ maxDate?: Date
+ range?: boolean
+ onChangeFrom?: Function
+ onChangeTo?: Function
+}
+
+const DatePicker = (props: IDatePickerProps) => {
+ const dropdownRef = useRef(null)
+ useEffect(() => {
+ const handleClickOutside = (e: Event) => {
+ if (
+ dropdownRef.current &&
+ !dropdownRef.current.contains(e.target as Node)
+ ) {
+ setIsOpen(false)
+ }
+ }
+ // Bind the event listener
+ document.addEventListener('mousedown', handleClickOutside)
+ return () => {
+ // Unbind the event listener on clean up
+ document.removeEventListener('mousedown', handleClickOutside)
+ }
+ }, [dropdownRef])
+
+ const [selectedDate, setSelectedDate] = useState(props.selected)
+ const today = new Date()
+ const pastDate = new Date(2015, 7, 30)
+
+ const disabledPeriod = {
+ before: props.minDate ? props.minDate : pastDate,
+ after: props.maxDate ? props.maxDate : today,
+ }
+ const disabledDays = [disabledPeriod]
+
+ const [isOpen, setIsOpen] = useState(false)
+
+ const defaultSelectedRange: DateRange = {
+ from: subMonths(today, 6),
+ to: today,
+ }
+ const [selectedRange, setSelectedRange] = useState(
+ defaultSelectedRange
+ )
+
+ const handleClick = useCallback(() => {
+ setIsOpen(!isOpen)
+ }, [isOpen])
+
+ const handleDateChange = (date: Date | undefined) => {
+ if (date && selectedDate !== date) {
+ setSelectedDate(date)
+ props.onChange(date)
+ }
+ }
+ const handleRangeChange = (range: DateRange | undefined) => {
+ if (range && range !== selectedRange) {
+ setSelectedRange(range)
+ props.onChangeFrom && props.onChangeFrom(range.from)
+ props.onChangeTo && props.onChangeTo(range.to)
+ }
+ }
+
+ if (props.range) {
+ const dateRangeString = `${
+ selectedRange?.from
+ ? formatDate(selectedRange?.from?.getTime() / 1000, props.timeFormat)
+ : 'From'
+ } - ${
+ selectedRange?.to
+ ? formatDate(selectedRange?.to?.getTime() / 1000, props.timeFormat)
+ : 'To'
+ }`
+
+ return (
+
+
+ {dateRangeString}
+
+ {isOpen && (
+
+ handleRangeChange(range)}
+ disabled={disabledDays}
+ />
+
+ )}
+
+ )
+ }
+
+ return (
+
+
+ {formatDate(selectedDate.getTime() / 1000, props.timeFormat)}
+
+ {isOpen && (
+
+ handleDateChange(date)}
+ disabled={disabledDays}
+ />
+
+ )}
+
+ )
+}
+
+export default DatePicker
diff --git a/packages/boba/gateway/src/containers/history/History.js b/packages/boba/gateway/src/containers/history/History.js
deleted file mode 100644
index c6fe04a0f9..0000000000
--- a/packages/boba/gateway/src/containers/history/History.js
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
-Copyright 2021-present Boba Network.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License. */
-
-import React, { useState } from 'react'
-import { useDispatch } from 'react-redux'
-import { isEqual,orderBy } from 'util/lodash';
-
-import { useSelector } from 'react-redux'
-import DatePicker from 'react-datepicker'
-import 'react-datepicker/dist/react-datepicker.css'
-
-import { useMediaQuery, useTheme } from '@mui/material'
-import {isSameOrAfterDate, isSameOrBeforeDate} from 'util/dates'
-import Input from 'components/input/Input'
-
-import { setActiveHistoryTab } from 'actions/uiAction'
-import {
- selectActiveHistoryTab,
- selectTransactions,
- selectAccountEnabled,
- selectLayer
-} from 'selectors'
-
-import { fetchTransactions } from 'actions/networkAction'
-
-import Exits from './TX_Exits'
-import Deposits from './TX_Deposits'
-import All from './TX_All'
-import Pending from './TX_Pending'
-import Transfers from './TX_Transfers'
-
-import * as S from './History.styles'
-import styles from './TX_All.module.scss'
-
-import useInterval from 'hooks/useInterval'
-import Connect from 'containers/connect/Connect'
-import Tabs from 'components/tabs/Tabs'
-
-import { POLL_INTERVAL } from 'util/constant'
-import { selectActiveNetworkName } from 'selectors'
-
-function History() {
-
- const theme = useTheme()
- const isMobile = useMediaQuery(theme.breakpoints.down('md'))
-
- const dispatch = useDispatch()
-
- const now = new Date()
- const last_6months = new Date(
- now.getFullYear(),
- now.getMonth() - 6,
- now.getDate()
- )
-
- const [startDate, setStartDate] = useState(last_6months)
- const [endDate, setEndDate] = useState(now)
- const layer = useSelector(selectLayer())
- const accountEnabled = useSelector(selectAccountEnabled())
-
- const [searchHistory, setSearchHistory] = useState('')
- const activeTab = useSelector(selectActiveHistoryTab, isEqual)
- const networkName = useSelector(selectActiveNetworkName())
-
- const unorderedTransactions = useSelector(selectTransactions, isEqual)
- const orderedTransactions = orderBy(
- unorderedTransactions,
- (i) => i.timeStamp,
- 'desc'
- )
-
- const transactions = orderedTransactions.filter((i) => {
- if (startDate && endDate) {
- return (
- isSameOrAfterDate(i.timeStamp, startDate) &&
- isSameOrBeforeDate(i.timeStamp,endDate)
- )
- }
- return true
- })
-
- useInterval(() => {
- if (accountEnabled) {
- dispatch(fetchTransactions())
- }
- }, POLL_INTERVAL)
-
- return (
-
-
-
-
- {layer && (
- <>
-
-
- {
- setSearchHistory(i.target.value)
- }}
- className={styles.searchBar}
- />
-
-
- {!isMobile ? (
-
- Show period from
-
- ) : null}
-
setStartDate(date)}
- selectsStart
- endDate={new Date(endDate)}
- maxDate={new Date(endDate)}
- calendarClassName={theme.palette.mode}
- placeholderText={isMobile ? 'From' : ''}
- />
- {!isMobile ? (
- to
- ) : null}
- setEndDate(date)}
- selectsEnd
- startDate={new Date(startDate)}
- minDate={new Date(startDate)}
- calendarClassName={theme.palette.mode}
- placeholderText={isMobile ? 'To' : ''}
- />
-
-
-
-
-
{
- dispatch(setActiveHistoryTab(tab))
- }}
- activeTab={activeTab}
- tabs={[
- 'All',
- `${networkName['l1']} to ${networkName['l2']}`,
- `${networkName['l2']} to ${networkName['l1']}`,
- 'Bridge between L1s',
- 'Pending',
- ]}
- />
-
- {activeTab === 'All' && (
-
- )}
-
- {activeTab === `${networkName['l1']} to ${networkName['l2']}` && (
-
- )}
-
- {activeTab === `${networkName['l2']} to ${networkName['l1']}` && (
-
- )}
-
- {activeTab === 'Bridge between L1s' && (
-
- )}
-
- {activeTab === 'Pending' && (
-
- )}
-
-
- >
- )}
-
- )
-}
-
-export default React.memo(History)
diff --git a/packages/boba/gateway/src/containers/history/History.styles.js b/packages/boba/gateway/src/containers/history/History.styles.js
deleted file mode 100644
index ec3cdbb228..0000000000
--- a/packages/boba/gateway/src/containers/history/History.styles.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import styled from '@emotion/styled'
-import { Box } from '@mui/material'
-
-export const HistoryContainer = styled.div`
- background: ${props => props.theme.palette.background.glassy};
- border-radius: 8px;
- margin-bottom: 20px;
-`;
-
-export const HistoryPageContainer = styled(Box)(({ theme }) => ({
- margin: '0px auto',
- marginBottom: theme.palette.spacing.toFooter,
- display: 'flex',
- flexDirection: 'column',
- justifyContent: 'space-around',
- padding: '10px',
- paddingTop: '0px',
- width: '70%',
- [theme.breakpoints.between('md', 'lg')]: {
- width: '90%',
- padding: '0px',
- },
- [theme.breakpoints.between('sm', 'md')]: {
- width: '90%',
- padding: '0px',
- },
- [theme.breakpoints.down('sm')]: {
- width: '100%',
- padding: '0px',
- },
-}))
-
-export const Disclaimer = styled.div`
- margin: 5px 10px;
- margin-top: 20px;
-`;
-
-export const Content = styled(Box)(({ theme }) => ({
- display: 'flex',
- flexDirection: 'column',
- gap: '5px',
- marginBottom: '10px',
- padding: '10px 20px',
- borderRadius: '6px'
-}));
-
-export const Header = styled(Box)(({ theme }) => ({
- display: 'flex',
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- marginBottom: '20px',
- [theme.breakpoints.down('md')]: {
- flexDirection: 'column',
- alignItems: 'flex-start',
- gap: '20px',
- },
-}))
-
-export const TableHeading = styled(Box)(({ theme }) => ({
- padding: "20px",
- borderTopLeftRadius: "6px",
- borderTopRightRadius: "6px",
- display: "flex",
- alignItems: "center",
- background: theme.palette.background.secondary,
- [theme.breakpoints.down('md')]: {
- marginBottom: "5px",
- },
-}))
-
-export const LayerAlert = styled(Box)(({ theme }) => ({
- width: "100%",
- display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'center',
- gap: '30px',
- borderRadius: '8px',
- margin: '20px 0px',
- padding: '25px',
- background: theme.palette.background.secondary,
- [theme.breakpoints.up('md')]: {
- padding: '25px 50px',
- },
-
-}));
diff --git a/packages/boba/gateway/src/containers/history/History.tsx b/packages/boba/gateway/src/containers/history/History.tsx
new file mode 100644
index 0000000000..5616b17acc
--- /dev/null
+++ b/packages/boba/gateway/src/containers/history/History.tsx
@@ -0,0 +1,276 @@
+/*
+Copyright 2021-present Boba Network.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License. */
+
+import React, { useState } from 'react'
+import { useDispatch, useSelector } from 'react-redux'
+import { isEqual } from 'util/lodash'
+import { ValidValuesFromArray } from 'util/objectManipulation'
+
+import { useTheme } from 'styled-components'
+
+import { Button } from 'components/global'
+
+import transctionService from 'services/transaction.service'
+import { NETWORK_TYPE } from 'util/network/network.util'
+import {
+ ALL_NETWORKS,
+ FILTER_OPTIONS,
+ NETWORK_L1_OPTIONS,
+ NETWORK_L2_OPTIONS,
+ TableOptions,
+} from './constants'
+
+import {
+ selectAccountEnabled,
+ selectLayer,
+ selectTransactions,
+} from 'selectors'
+
+import { fetchTransactions } from 'actions/networkAction'
+
+import {
+ Table,
+ NoHistory,
+ HistoryPageContainer,
+ TableHeader,
+ TableFilters,
+ NetworkDropdowns,
+ DateDescriptions,
+ SwitchChainIcon,
+ SwitchIcon,
+ TableTransactionsContainer,
+ DatePickerWrapper,
+ DropdownNetwork,
+ MobileDateDescriptions,
+ MobileDatePickerWrapper,
+} from './styles'
+
+import { setConnect } from 'actions/setupAction'
+import useInterval from 'hooks/useInterval'
+
+import { POLL_INTERVAL } from 'util/constant'
+
+import FilterIcon from 'assets/images/filter.svg'
+import noHistoryIcon from 'assets/images/noHistory.svg'
+import { FilterDropDown } from 'components/filter'
+import { Svg } from 'components/global/svg'
+import { TransactionsTableHeader } from 'components/global/table/themes'
+import { TransactionsResolver } from './TransactionsResolver'
+import { CHAIN_NAME, TRANSACTION_FILTER_STATUS } from './types'
+import { SearchInput } from 'components/global/searchInput'
+
+import { Typography } from 'components/global/typography'
+import DatePicker from './DatePicker'
+
+const History = () => {
+ const [toNetwork, setToNetwork] = useState(ALL_NETWORKS)
+ const [fromNetwork, setFromNetwork] = useState(ALL_NETWORKS)
+ const [transactionsFound, setTransactionsFound] = useState(true)
+ const [switched, setSwitched] = useState(false)
+
+ const theme: any = useTheme()
+
+ const dispatch = useDispatch()
+
+ const now = new Date()
+ const last_6months = new Date(
+ now.getFullYear(),
+ now.getMonth() - 6,
+ now.getDate()
+ )
+ const handleSwitchDropdowns = () => {
+ const temp = fromNetwork
+ setFromNetwork(toNetwork)
+ setToNetwork(temp)
+ setSwitched((current) => !current)
+ }
+
+ const [filterStartDate, setFilterStartDate] = useState(last_6months)
+ const [transactionStatus, setTransactionStatus] = useState('All')
+ const [filterEndDate, setFilterEndDate] = useState(now)
+ const layer = useSelector(selectLayer())
+ const accountEnabled = useSelector(selectAccountEnabled())
+
+ const [searchHistory, setSearchHistory] = useState('')
+
+ const transactions = useSelector(selectTransactions, isEqual)
+
+ // TODO: not working as implementation needs be rewrite.
+ const getDatePicker = (label: string, range: boolean = false) => {
+ const dateSelector = (date: Date) => {
+ label === 'To' ? setFilterEndDate(date) : setFilterStartDate(date)
+ }
+ return (
+
+ date && !Array.isArray(date) && dateSelector(date)
+ }
+ timeFormat="MM/DD/YYYY"
+ range={range}
+ {...(range
+ ? { onChangeFrom: setFilterStartDate, onChangeTo: setFilterEndDate }
+ : {})}
+ {...(label === 'To'
+ ? { minDate: filterStartDate }
+ : { maxDate: filterEndDate })}
+ />
+ )
+ }
+ const syncTransactions = async () => {
+ if (accountEnabled) {
+ const newTransactions = await transctionService.getTransactions()
+ if (newTransactions.length === 0) {
+ setTransactionsFound(false)
+ } else {
+ setTransactionsFound(true)
+ }
+ if (
+ new Set(ValidValuesFromArray(transactions)).size !==
+ new Set(newTransactions).size
+ ) {
+ dispatch(fetchTransactions())
+ }
+ }
+ }
+
+ useInterval(async () => {
+ await syncTransactions()
+ }, POLL_INTERVAL)
+
+ return (
+
+ {layer && (
+ <>
+
+ {
+ setSearchHistory(i.target.value)
+ }}
+ />
+
+
+ Date Range From
+
+ {getDatePicker('From')}
+ To
+ {getDatePicker('To')}
+
+
+
+ Date Range
+
+ {getDatePicker('', true)}
+
+
+
+
+
+
+
+ From
+ setFromNetwork(option)}
+ error={false}
+ headers={[NETWORK_TYPE.MAINNET, NETWORK_TYPE.TESTNET]}
+ />
+ {
+ handleSwitchDropdowns()
+ }}
+ >
+
+
+ To
+ setToNetwork(option)}
+ error={false}
+ headers={[NETWORK_TYPE.MAINNET, NETWORK_TYPE.TESTNET]}
+ />
+
+ {
+ setTransactionStatus(item.value)
+ }}
+ error={false}
+ />
+
+
+
+
+ {transactionsFound && (
+
+ )}
+
+
+ >
+ )}
+ {!transactionsFound && (
+
+
+ No Transactions Found.
+
+ )}
+ {!layer && (
+
+
+ No History.
+
+ )}
+
+ )
+}
+
+export default React.memo(History)
diff --git a/packages/boba/gateway/src/containers/history/TX_All.js b/packages/boba/gateway/src/containers/history/TX_All.js
deleted file mode 100644
index dd895effea..0000000000
--- a/packages/boba/gateway/src/containers/history/TX_All.js
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-Copyright 2021-present Boba Network.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License. */
-
-import React, { useState, useEffect } from 'react'
-import { useSelector } from 'react-redux'
-import "react-datepicker/dist/react-datepicker.css"
-import { Grid, Box } from '@mui/material'
-
-import { selectLoading, selectTokens } from 'selectors'
-import { logAmount } from 'util/amountConvert'
-
-import Transaction from 'components/transaction/Transaction'
-import { Pager } from 'components'
-
-import * as S from './History.styles'
-
-const PER_PAGE = 8
-
-function TX_All({ searchHistory, transactions }) {
-
- const [page, setPage] = useState(1)
-
- const loading = useSelector(selectLoading(['TRANSACTION/GETALL']))
- const tokenList = useSelector(selectTokens)
-
- useEffect(() => {
- setPage(1)
- }, [searchHistory])
-
- const _transactions = transactions.filter(i => {
- return i.hash.includes(searchHistory)
- })
-
- const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE)
- const endingIndex = page * PER_PAGE
- const paginatedTransactions = _transactions.slice(startingIndex, endingIndex)
-
- let totalNumberOfPages = Math.ceil(_transactions.length / PER_PAGE)
-
- //if totalNumberOfPages === 0, set to one so we don't get the strange "page 1 of 0" display
- if (totalNumberOfPages === 0) totalNumberOfPages = 1
-
- return (
-
- setPage(page + 1)}
- onClickBack={() => setPage(page - 1)}
- />
-
-
-
- {!paginatedTransactions.length && !loading && (
- Scanning for transactions...
- )}
- {!paginatedTransactions.length && loading && (
- Loading...
- )}
- {paginatedTransactions.map((i, index) => {
-
- let metaData = ''
-
- if(i.crossDomainMessage && i.crossDomainMessage.fast === 1) {
- metaData = 'Fast Bridge'
- } else if (i.crossDomainMessage && i.crossDomainMessage.fast === 0) {
- metaData = 'Classic Bridge'
- }
-
- let annotation = ''
-
- if(metaData === '' && typeof(i.activity) === 'undefined') {
- //annotation = 'No Idea'
- } else if (typeof(i.activity) === 'undefined') {
- //we only have metaData
- annotation = metaData
- } else if (metaData === '') {
- //we only have activity
- annotation = i.activity
- } else {
- //we have both
- annotation = `${metaData} (${i.activity})`
- }
- const chain = (i.chain === 'L1pending') ? 'L1' : i.chain
-
- let details = null
- let amountTx = null
-
- if (i.action && i.action.token) {
- let token = tokenList[i.action.token.toLowerCase()];
- if (chain === 'L2') {
- token = Object.values(tokenList).find(t => t.addressL2.toLowerCase() === i.action.token.toLowerCase());
- }
- if (!!token) {
- let amount = logAmount(i.action.amount, token.decimals, 3);
- let symbol = token[`symbol${chain}`];
- amountTx = `${amount} ${symbol}`;
- }
- }
-
- if( i.crossDomainMessage && i.crossDomainMessage.l1BlockHash ) {
- details = {
- blockHash: i.crossDomainMessage.l1BlockHash,
- blockNumber: i.crossDomainMessage.l1BlockNumber,
- from: i.crossDomainMessage.l1From,
- hash: i.crossDomainMessage.l1Hash,
- to: i.crossDomainMessage.l1To,
- }
- }
-
- if( i.crossDomainMessage && i.crossDomainMessage.l2BlockHash ) {
- details = {
- blockHash: i.crossDomainMessage.l2BlockHash,
- blockNumber: i.crossDomainMessage.l2BlockNumber,
- from: i.crossDomainMessage.l2From,
- hash: i.crossDomainMessage.l2Hash,
- to: i.crossDomainMessage.l2To,
- }
- }
-
- return (
-
- )
- })}
-
-
-
-
- )
-}
-
-export default React.memo(TX_All)
diff --git a/packages/boba/gateway/src/containers/history/TX_All.module.scss b/packages/boba/gateway/src/containers/history/TX_All.module.scss
deleted file mode 100644
index da7c00e1a9..0000000000
--- a/packages/boba/gateway/src/containers/history/TX_All.module.scss
+++ /dev/null
@@ -1,185 +0,0 @@
-@import 'index.scss';
-
-.container {
- display: flex;
- flex-direction: column;
- padding: 10px;
- padding-top: 0;
- background: $background;
-}
-
-.searchInput {
- width: 250px !important;
- @include mobile {
- width: 100% !important;
- }
-}
-
-.data {
- display: flex;
- flex-direction: row;
- @include mobile {
- flex-direction: column;
- }
-}
-
-.section {
- flex: 1;
- &:first-child {
- margin-right: 20px;
- @include mobile {
- margin-right: 0;
- margin-bottom: 20px;
- }
- }
-}
-
-.transactionSection {
- margin-bottom: 20px;
-}
-
-.disclaimer {
- color: $gray3;
- margin: 5px 10px;
- margin-top: 20px;
-}
-
-.searchBar {
- flex: 1;
- margin-bottom: 0;
- min-width: 250px;
- & > div {
- border: none !important;
- }
-}
-
-.transactions {
- overflow: auto;
- background: $background400;
- border-radius: 8px;
- margin-top: 10px;
- min-height: 100px;
- .transaction {
- padding: 20px 0;
- &:last-child {
- border-bottom: none;
- }
- }
-}
-
-.subTitle {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
-
- margin-bottom: 32px;
- span {
- margin-right: 20px;
- }
-}
-
-.processExitButton {
- color: $blue;
- cursor: pointer;
-}
-
-.actions {
- display: flex;
- justify-content: flex-end;
- align-items: center;
- .datePicker {
- flex: 1;
- margin-bottom: 0;
- min-width: 250px;
- }
- @include mobile {
- width: 100%;
- > div:first-child {
- margin-right: 5px;
- }
- > div:last-child {
- margin-left: 5px;
- }
- }
-}
-
-.datePickerInput {
- border-radius: 8px;
- width: 130px;
- margin: 0 15px;
- position: relative;
- @include mobile {
- width: 100%;
- margin: 0;
- }
-
-
- &::after {
- content: '';
- width: 0;
- height: 0;
- position: absolute;
- right: 10px;
- font-size: 25px;
- bottom: 15px;
- }
-
- input {
- background: rgba(0, 0, 0, 0.09);
- color: rgba(0, 0, 0, 0.87);
- height: 40px;
- width: 130px;
- padding: 0 15px;
- line-height: 40px;
- border: 0;
- border-radius: 8px;
- font-size: 16px;
- text-align: left;
- @include mobile {
- width: 100%;
- }
- }
-}
-
-.datePickerInputDark {
- border-radius: 8px;
- width: 130px;
- margin: 0px 15px;
- position: relative;
- @include mobile {
- width: 100%;
- margin: 0;
- }
-
-
- &::after {
- content: '';
- width: 0;
- height: 0;
- position: absolute;
- right: 10px;
- font-size: 25px;
- bottom: 15px;
- }
-
- input {
- background: #FFFFFF0A;
- color: white;
- height: 40px;
- width: 130px;
- padding: 0 15px;
- line-height: 40px;
- border: 0;
- border-radius: 8px;
- font-size: 16px;
- text-align: left;
- @include mobile {
- width: 100%;
- }
- }
-}
-
-.popperStyle {
- z-index: 3;
-}
diff --git a/packages/boba/gateway/src/containers/history/TX_Deposits.js b/packages/boba/gateway/src/containers/history/TX_Deposits.js
deleted file mode 100644
index e3f4f0fe1b..0000000000
--- a/packages/boba/gateway/src/containers/history/TX_Deposits.js
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-Copyright 2021-present Boba Network.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License. */
-
-import React, { useState, useEffect } from 'react'
-import { Grid, Box } from '@mui/material'
-import { useSelector } from 'react-redux'
-
-import { selectLoading, selectTokens, selectActiveNetworkName } from 'selectors'
-
-import { logAmount } from 'util/amountConvert'
-
-import { Pager } from 'components'
-import Transaction from 'components/transaction/Transaction'
-
-import * as S from './History.styles';
-
-const PER_PAGE = 10
-
-function TX_Deposits({ searchHistory, transactions }) {
-
- const [page, setPage] = useState(1)
-
- const loading = useSelector(selectLoading(['TRANSACTION/GETALL']))
- const tokenList = useSelector(selectTokens)
- const networkName = useSelector(selectActiveNetworkName())
-
- useEffect(() => {
- setPage(1)
- }, [searchHistory])
-
- let _deposits = transactions.filter(i => {
- return i.hash.includes(searchHistory) && i.to !== null && i.depositL2
- })
- // combine the batch onramp
- _deposits = _deposits.reduce((acc, cur) => {
- const index = acc.findIndex(i => i.blockNumber === cur.blockNumber)
- if (index !== -1) {
- acc[index].action = [...acc[index].action, cur.action]
- } else {
- cur.action = [cur.action]
- acc.push(cur)
- }
- return acc
- }, [])
-
- const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE);
- const endingIndex = page * PER_PAGE;
- const paginatedDeposits = _deposits.slice(startingIndex, endingIndex);
-
- let totalNumberOfPages = Math.ceil(_deposits.length / PER_PAGE);
-
- //if totalNumberOfPages === 0, set to one so we don't get the strange "page 1 of 0" display
- if (totalNumberOfPages === 0) totalNumberOfPages = 1
-
- return (
-
- setPage(page + 1)}
- onClickBack={()=>setPage(page - 1)}
- />
-
-
-
-
- {!paginatedDeposits.length && !loading && (
- Scanning for deposits...
- )}
- {!paginatedDeposits.length && loading && (
- Loading...
- )}
- {paginatedDeposits.map((i, index) => {
- const chain = (i.chain === 'L1pending') ? 'L1' : i.chain
-
- let details = null
- let amountTx = ''
-
- let metaData = ''
-
- if(i.crossDomainMessage.fast === 1) {
- metaData = 'Fast Bridge'
- } else if (i.crossDomainMessage.fast === 0) {
- metaData = 'Classic Bridge'
- }
-
- for (const payload of i.action) {
- if (payload.token) {
- const token = tokenList[payload.token.toLowerCase()];
- if (!!token) {
- let amount = logAmount(payload.amount, token.decimals, 3);
- let symbol = token[`symbol${chain}`];
- amountTx += `${amount} ${symbol} `;
- }
- }
- }
-
- if( i.crossDomainMessage && i.crossDomainMessage.l2BlockHash ) {
- details = {
- blockHash: i.crossDomainMessage.l2BlockHash,
- blockNumber: i.crossDomainMessage.l2BlockNumber,
- from: i.crossDomainMessage.l2From,
- hash: i.crossDomainMessage.l2Hash,
- to: i.crossDomainMessage.l2To,
- }
- }
-
- return (
-
- )
- })}
-
-
-
-
- );
-}
-
-export default React.memo(TX_Deposits)
diff --git a/packages/boba/gateway/src/containers/history/TX_Exits.js b/packages/boba/gateway/src/containers/history/TX_Exits.js
deleted file mode 100644
index 039e5049f4..0000000000
--- a/packages/boba/gateway/src/containers/history/TX_Exits.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
-Copyright 2021-present Boba Network.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License. */
-
-import React, { useState } from 'react'
-import {Grid, Box} from '@mui/material'
-import {formatDate, isAfterDate} from 'util/dates'
-import { useSelector } from 'react-redux'
-
-import { selectLoading, selectTokens, selectActiveNetworkName } from 'selectors'
-
-import { logAmount } from 'util/amountConvert'
-
-import Transaction from 'components/transaction/Transaction'
-import { Pager } from 'components'
-
-import networkService from 'services/networkService'
-
-import * as S from './History.styles'
-
-const PER_PAGE = 8
-
-function TX_Exits({ searchHistory, transactions, chainLink }) {
-
- const [ page, setPage ] = useState(1)
- const loading = useSelector(selectLoading(['TRANSACTION/GETALL']))
- const tokenList = useSelector(selectTokens)
- const allAddresses = networkService.getAllAddresses()
- const networkName = useSelector(selectActiveNetworkName())
-
- const _exits = transactions.filter(i => {
- return i.hash.includes(searchHistory) && i.to !== null && i.exitL2
- })
-
- const renderExits = _exits.map((i, index) => {
-
- const chain = (i.chain === 'L1pending') ? 'L1' : i.chain
-
- let metaData = ''
-
- //i.crossDomainMessage.fast can be either 1 or null,
- //where null denotes the classic 7 day exit
-
- if(i.crossDomainMessage.fast === 1) {
- metaData = 'Fast Bridge'
- } else if (i.crossDomainMessage.fast === null) {
- metaData = 'Classic 7-day Bridge'
- }
-
- let isExitable = false
- let details = null
-
- let timeLabel = formatDate(i.timeStamp,'lll')
-
- const to = i.to.toLowerCase()
-
- let amountTx = null;
-
- if (i.action && i.action.token) {
- const token = Object.values(tokenList).find(t => t.addressL2.toLowerCase() === i.action.token.toLowerCase());
- if (!!token) {
- let amount = logAmount(i.action.amount, token.decimals, 3);
- let symbol = token[`symbol${chain}`];
- amountTx = `${amount} ${symbol}`;
- }
- }
-
- //are we dealing with a traditional exit?
- if (to === allAddresses.L2StandardBridgeAddress.toLowerCase()) {
-
- isExitable = isAfterDate(i.crossDomainMessage.crossDomainMessageEstimateFinalizedTime)
-
- if (isExitable) {
- timeLabel = 'Funds were exited to L1 after ' + formatDate(i.crossDomainMessage.crossDomainMessageEstimateFinalizedTime,'lll')
- } else {
- const secondsToGo = i.crossDomainMessage.crossDomainMessageEstimateFinalizedTime - Math.round(Date.now() / 1000)
- const daysToGo = Math.floor(secondsToGo / (3600 * 24))
- const hoursToGo = Math.round((secondsToGo % (3600 * 24)) / 3600)
- const time = formatDate(i.timeStamp)
- timeLabel = `7 day window started ${time}. ${daysToGo} days and ${hoursToGo} hours remaining`
- }
-
- }
-
- if( i.crossDomainMessage && i.crossDomainMessage.l1BlockHash ) {
- details = {
- blockHash: i.crossDomainMessage.l1BlockHash,
- blockNumber: i.crossDomainMessage.l1BlockNumber,
- from: i.crossDomainMessage.l1From,
- hash: i.crossDomainMessage.l1Hash,
- to: i.crossDomainMessage.l1To,
- }
- }
-
- return (
-
- )
- })
-
- const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE)
- const endingIndex = page * PER_PAGE
- const paginatedExits = renderExits.slice(startingIndex, endingIndex)
-
- let totalNumberOfPages = Math.ceil(renderExits.length / PER_PAGE)
-
- //if totalNumberOfPages === 0, set to one so we don't get the strange "Page 1 of 0" display
- if (totalNumberOfPages === 0) totalNumberOfPages = 1
-
- return (
-
- setPage(page + 1)}
- onClickBack={() => setPage(page - 1)}
- />
-
-
-
-
- {!renderExits.length && !loading && (
- Scanning for exits...
- )}
- {!renderExits.length && loading && (
- Loading...
- )}
- {React.Children.toArray(paginatedExits)}
-
-
-
-
- );
-}
-
-export default React.memo(TX_Exits)
diff --git a/packages/boba/gateway/src/containers/history/TX_Pending.js b/packages/boba/gateway/src/containers/history/TX_Pending.js
deleted file mode 100644
index dddf9b40a5..0000000000
--- a/packages/boba/gateway/src/containers/history/TX_Pending.js
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
-Copyright 2021-present Boba Network.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License. */
-
-import React, { useState, useEffect } from 'react'
-import { useSelector } from 'react-redux'
-import "react-datepicker/dist/react-datepicker.css"
-import { Grid, Box } from '@mui/material'
-import { orderBy } from 'util/lodash';
-
-import { selectLoading, selectTokens } from 'selectors'
-import { logAmount } from 'util/amountConvert'
-
-import Transaction from 'components/transaction/Transaction'
-import { Pager } from 'components'
-
-import * as S from './History.styles'
-import { formatDate } from 'util/dates';
-
-const PER_PAGE = 8
-
-function TX_Pending({ searchHistory, transactions }) {
-
- const [page, setPage] = useState(1)
-
- const loading = useSelector(selectLoading(['TRANSACTION/GETALL']))
- const tokenList = useSelector(selectTokens)
-
- useEffect(() => {
- setPage(1)
- }, [searchHistory])
-
- const pending = transactions.filter((i) => {
- if (i.crossDomainMessage &&
- i.crossDomainMessage.crossDomainMessage === 1 &&
- i.crossDomainMessage.crossDomainMessageFinalize === 0 &&
- i.action.status === "pending"
- ) {
- return true
- }
- return false
- })
-
- let pendingL1 = pending.filter((i) => {
- if (i.chain === 'L1pending') return true
- return false
- })
-
- let pendingL2 = pending.filter((i) => {
- if (i.chain === 'L2') return true
- return false
- })
-
- //Part 1 - exit that is not final and we do not have a state root hash yet
- let pendingExitsStage0 = pendingL2.filter((i) => {
- if (!i.stateRoot.stateRootHash && i.action.fast) return true
- return false
- })
- pendingExitsStage0 = pendingExitsStage0.map(v => ({
- ...v,label: 'Bridge to L1',labelStatus: 'Step 0, No SR Hash yet, Pending',
- completion: v.crossDomainMessage.crossDomainMessageEstimateFinalizedTime,
- })
- )
-
- //Part 2 - exit that is not final, but we have a state root hash
- let pendingExitsStage1 = pendingL2.filter((i) => {
- if (i.stateRoot.stateRootHash && i.action.fast) return true
- return false
- })
- pendingExitsStage1 = pendingExitsStage1.map(v => ({
- ...v, label: 'Bridge to L1', labelStatus: 'Step 1, Have SR Hash, Pending',
- completion: v.crossDomainMessage.crossDomainMessageEstimateFinalizedTime,
- })
- )
-
- //Part 3 - exit that is not final, but we have a state root hash, and we ARE NOT using the fast message relayer
- //so this is a traditional exit
- let pendingExitsTrad = pendingL2.filter((i) => {
- if (!i.action.fast) return true
- return false
- })
- pendingExitsTrad = pendingExitsTrad.map(v => ({
- ...v,label: 'Classic 7-day Bridge to L1',labelStatus: 'In 7 day window',
- completion: v.crossDomainMessage.crossDomainMessageEstimateFinalizedTime,
- })
- )
-
- //DEPOSIT Part 1 - deposit that is not final and we do not have a state root hash yet
- let pendingDepositsFast = pendingL1.filter((i) => {
- if (i.action.fast) return true
- return false
- })
- pendingDepositsFast = pendingDepositsFast.map(v => ({
- ...v,label: 'Bridge to L2',labelStatus: 'Pending',
- completion: v.crossDomainMessage.crossDomainMessageEstimateFinalizedTime,
- })
- )
-
- //DEPOSIT Part 3 - we ARE NOT using the fast message relayer
- //so this is a traditional deposit
- let pendingDepositsTrad = pendingL1.filter((i) => {
- if (!i.action.fast) return true
- return false
- })
- pendingDepositsTrad = pendingDepositsTrad.map(v => ({
- ...v, label: 'Classic Bridge to L2', labelStatus: 'Pending',
- completion: v.crossDomainMessage.crossDomainMessageEstimateFinalizedTime,
- })
- )
-
- let pendingTransactions = [
- ...pendingExitsTrad,
- ...pendingExitsStage0,
- ...pendingExitsStage1,
- ...pendingDepositsTrad,
- ...pendingDepositsFast
- ]
-
- // combine the batch onramp
- pendingTransactions = pendingTransactions.reduce((acc, cur) => {
- const index = acc.findIndex(i => i.blockNumber === cur.blockNumber)
- if (index !== -1) {
- acc[index].action = [...acc[index].action, cur.action]
- acc[index].label = 'Bridge to L2 In Batch'
- } else {
- cur.action = [cur.action]
- acc.push(cur)
- }
- return acc
- }, [])
-
- const orderedTransactions = orderBy(pendingTransactions, i => i.timeStamp, 'desc')
-
- const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE)
- const endingIndex = page * PER_PAGE
- const paginatedTransactions = orderedTransactions.slice(startingIndex, endingIndex)
-
- let totalNumberOfPages = Math.ceil(orderedTransactions.length / PER_PAGE)
-
- //if totalNumberOfPages === 0, set to one so we don't get the strange "page 1 of 0" display
- if (totalNumberOfPages === 0) totalNumberOfPages = 1
-
-
-
- return (
-
- setPage(page + 1)}
- onClickBack={() => setPage(page - 1)}
- />
-
-
-
- {!paginatedTransactions.length && !loading && (
- Scanning for pending transactions...
- )}
- {!paginatedTransactions.length && loading && (
- Loading...
- )}
- {paginatedTransactions.map((i, index) => {
-
- let completionTime = 'Not available'
-
- if(i.completion)
- completionTime = formatDate(i.completion,'lll')
-
- const chain = (i.chain === 'L1pending') ? 'L1' : i.chain
-
- let amountTx = ''
-
- for (const payload of i.action) {
- if (payload.token) {
- let token = tokenList[payload.token.toLowerCase()];
- if (chain === 'L2') {
- token = Object.values(tokenList).find(t => t.addressL2.toLowerCase() === payload.token.toLowerCase());
- }
- if (!!token) {
- let amount = logAmount(payload.amount, token.decimals, 3);
- let symbol = token[`symbol${chain}`];
- amountTx += `${amount} ${symbol} `;
- }
- }
- }
-
- let annotation = ''
- if(typeof(i.label) === 'undefined') {
- //annotation = 'No Idea'
- } else {
- annotation = i.label
- }
-
- let completion = ''
- if(typeof(i.labelStatus) === 'undefined') {
- //status = 'No Idea'
- } else {
- completion = i.labelStatus + ' - Completion time: ' + completionTime
- }
-
- return (
-
- )
- })}
-
-
-
-
-
- )
-}
-
-export default React.memo(TX_Pending)
diff --git a/packages/boba/gateway/src/containers/history/TX_Transfers.js b/packages/boba/gateway/src/containers/history/TX_Transfers.js
deleted file mode 100644
index e776444baa..0000000000
--- a/packages/boba/gateway/src/containers/history/TX_Transfers.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
-Copyright 2021-present Boba Network.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License. */
-
-import { Box, Grid } from '@mui/material'
-import React, { useState } from 'react'
-
-
-import { logAmount } from 'util/amountConvert'
-
-import { Pager } from 'components'
-import Transaction from 'components/transaction/Transaction'
-import * as S from './History.styles'
-import { useSelector } from 'react-redux'
-import { selectLoading } from 'selectors'
-
-const PER_PAGE = 8
-
-function TX_Transfers({ searchHistory, transactions, chainLink }) {
-
- const [page, setPage] = useState(1)
- const loading = useSelector(selectLoading(['TRANSACTION/GETALL']))
- const _transfers = transactions.filter(i => {
- return i.hash.includes(searchHistory) && i.to !== null && i.altL1
- })
-
- const renderTransfers = _transfers.map((i, index) => {
-
- const chain = (i.chain === 'L0pending') ? 'L0' : i.chain
-
- let amountTx = `${logAmount(i.amount, 18, 3)} BOBA`;
-
- return (
-
- )
- })
-
- const startingIndex = page === 1 ? 0 : ((page - 1) * PER_PAGE)
- const endingIndex = page * PER_PAGE
- const paginatedExits = renderTransfers.slice(startingIndex, endingIndex)
-
- let totalNumberOfPages = Math.ceil(renderTransfers.length / PER_PAGE)
-
- //if totalNumberOfPages === 0, set to one so we don't get the strange "Page 1 of 0" display
- if (totalNumberOfPages === 0) totalNumberOfPages = 1
-
- return (
-
- setPage(page + 1)}
- onClickBack={() => setPage(page - 1)}
- />
-
-
-
-
- {!renderTransfers.length && !loading && (
- Scanning for exits...
- )}
- {!renderTransfers.length && loading && (
- Loading...
- )}
- {React.Children.toArray(paginatedExits)}
-
-
-
-
- );
-}
-
-export default React.memo(TX_Transfers)
diff --git a/packages/boba/gateway/src/containers/history/TransactionsResolver.tsx b/packages/boba/gateway/src/containers/history/TransactionsResolver.tsx
new file mode 100644
index 0000000000..ad3b780129
--- /dev/null
+++ b/packages/boba/gateway/src/containers/history/TransactionsResolver.tsx
@@ -0,0 +1,348 @@
+import { TransactionsTableContent } from 'components/global/table/themes'
+import dayjs from 'dayjs'
+import React, { useState, useEffect } from 'react'
+import { getCoinImage } from 'util/coinImage'
+import { formatDate, isSameOrAfterDate, isSameOrBeforeDate } from 'util/dates'
+import { ALL_NETWORKS, Chains } from './constants'
+import { Svg } from 'components/global/svg'
+import { TokenInfo } from 'containers/history/tokenInfo'
+
+import {
+ TransactionDate,
+ TransactionAmount,
+ Icon,
+ Status,
+ NoHistory,
+ TransactionDetails,
+ TransactionChainDetails,
+ TransactionToken,
+ TransactionsWrapper,
+ TransactionHash,
+ TransactionChain,
+ IconContainer,
+ Image,
+ IncompleteTransactionHash,
+} from './styles'
+import {
+ ITransactionsResolverProps,
+ ITransaction,
+ IProcessedTransaction,
+ TRANSACTION_STATUS,
+ TRANSACTION_FILTER_STATUS,
+ LAYER,
+} from './types'
+import { orderBy } from 'util/lodash'
+import truncate from 'truncate-middle'
+import { logAmount } from 'util/amountConvert'
+import noHistoryIcon from 'assets/images/noHistory.svg'
+import bobaLogo from 'assets/images/Boba_Logo_White_Circle.png'
+
+export const TransactionsResolver: React.FC = ({
+ transactions,
+ transactionsFilter,
+ loading = false,
+}) => {
+ const [currentTransactions, setCurrentTransactions] = useState<
+ ITransaction[]
+ >([])
+
+ useEffect(() => {
+ setCurrentTransactions(transactions)
+ }, [transactions])
+
+ const orderedTransactions = orderBy(
+ currentTransactions,
+ (i) => i.timeStamp,
+ 'desc'
+ )
+
+ const dateFilter = (transaction: ITransaction) => {
+ const txnAfterStartDate = transactionsFilter.startDate
+ ? isSameOrAfterDate(
+ transaction.timeStamp,
+ dayjs(transactionsFilter.startDate)
+ )
+ : true
+ const txnBeforeEndDate = transactionsFilter.endDate
+ ? isSameOrBeforeDate(
+ transaction.timeStamp,
+ dayjs(transactionsFilter.endDate)
+ )
+ : true
+
+ return txnAfterStartDate && txnBeforeEndDate
+ }
+
+ // should filter out transctions that aren't cross domain
+ const crossDomainFilter = (transaction: ITransaction) => {
+ return (
+ transaction.crossDomainMessage &&
+ transaction.crossDomainMessage.crossDomainMessage
+ )
+ }
+
+ const networkFilter = (transaction: ITransaction) => {
+ let targetFromNetwork = false
+ let targetToNetwork = false
+ switch (transactionsFilter.fromNetworkChainId) {
+ case ALL_NETWORKS.value: {
+ targetFromNetwork = true
+ break
+ }
+ case transaction.originChainId.toString(): {
+ targetFromNetwork = true
+ break
+ }
+ }
+ switch (transactionsFilter.toNetworkChainId) {
+ case ALL_NETWORKS.value: {
+ targetToNetwork = true
+ break
+ }
+ case transaction.destinationChainId.toString(): {
+ targetToNetwork = true
+ break
+ }
+ }
+ return targetFromNetwork && targetToNetwork
+ }
+ const getTransactionStatus = (transaction: ITransaction) => {
+ if (
+ transaction.action &&
+ transaction.crossDomainMessage.crossDomainMessageSendTime
+ ) {
+ switch (transaction.action.status) {
+ case TRANSACTION_STATUS.Succeeded: {
+ return TRANSACTION_FILTER_STATUS.Completed
+ }
+ case TRANSACTION_STATUS.Pending: {
+ return TRANSACTION_FILTER_STATUS.Pending
+ }
+ }
+ }
+ return TRANSACTION_FILTER_STATUS.Canceled
+ }
+ const statusFilter = (transaction: ITransaction) => {
+ const status = getTransactionStatus(transaction)
+ transaction.UserFacingStatus = status
+ if (
+ transactionsFilter.status &&
+ transactionsFilter.status !== TRANSACTION_FILTER_STATUS.All
+ ) {
+ return transactionsFilter.status === transaction.UserFacingStatus
+ }
+
+ return true
+ }
+
+ // filter out transactions whose hash does not match
+ const hashFilter = (transaction: IProcessedTransaction) => {
+ if (transactionsFilter.targetHash) {
+ if (
+ !transaction.fromHash.includes(transactionsFilter.targetHash) &&
+ !transaction.toHash.includes(transactionsFilter.targetHash)
+ ) {
+ return false
+ }
+ }
+ return true
+ }
+ const filteredTransactions = orderedTransactions.filter((transaction) => {
+ return (
+ crossDomainFilter(transaction) &&
+ networkFilter(transaction) &&
+ statusFilter(transaction) &&
+ dateFilter(transaction)
+ )
+ })
+
+ const process_transaction = (transaction: ITransaction) => {
+ let amountString = ''
+ const chain = transaction.layer === 'L1pending' ? 'L1' : transaction.layer
+
+ // TODO: have a unknown token to use
+ let token = {
+ name: 'Etheruem',
+ symbol: 'ETH',
+ decimals: 18,
+ }
+ if (
+ TokenInfo[transaction.originChainId.toString()][
+ transaction.action.token.toLowerCase()
+ ]
+ ) {
+ token =
+ TokenInfo[transaction.originChainId.toString()][
+ transaction.action.token.toLowerCase()
+ ]
+ }
+
+ const symbol = token.symbol
+
+ amountString = logAmount(transaction.action.amount, token.decimals, 4)
+ const fromHash = transaction.hash
+ let toHash = ''
+ if (chain === LAYER.L2 && transaction.crossDomainMessage.l1Hash) {
+ toHash = transaction.crossDomainMessage.l1Hash
+ } else if (chain === LAYER.L1 && transaction.crossDomainMessage.l2Hash) {
+ toHash = transaction.crossDomainMessage.l2Hash
+ }
+ const processedTransaction: IProcessedTransaction = {
+ timeStamp: transaction.timeStamp,
+ from: transaction.from,
+ fromHash,
+ toHash,
+ to: transaction.to,
+ tokenSymbol: symbol,
+ amount: amountString,
+ status: transaction.UserFacingStatus,
+ originChainId: transaction.originChainId,
+ destinationChainId: transaction.destinationChainId,
+ }
+ return processedTransaction
+ }
+
+ const processedTransactions = filteredTransactions.map((transaction) => {
+ return process_transaction(transaction)
+ })
+
+ const filteredProcessedTransactions = processedTransactions.filter(
+ (transaction) => {
+ return hashFilter(transaction)
+ }
+ )
+
+ const getTransactionToken = (symbol: string) => {
+ return (
+
+
+ {symbol === 'BOBA' ? (
+
+ ) : (
+
+ )}
+
+ {symbol}
+
+ )
+ }
+
+ const getTransactionChain = (
+ chainID: string,
+ hash: string,
+ status: string
+ ) => {
+ const linkToHash = `${Chains[chainID].transactionUrlPrefix}${hash}`
+ const networkName = Chains[chainID].name
+ const imgSrc = Chains[chainID].imgSrc
+
+ return (
+
+
+
+
+
+ {networkName}
+ {hash && (
+
+ {`Tx: ${truncate(hash, 4, 4, '...')}`}
+
+ )}
+ {!hash && (
+ {`Tx: ${status}`}
+ )}
+
+
+ )
+ }
+
+ const getTransactionDate = (timeStamp: number) => {
+ return (
+
+ {formatDate(timeStamp, 'DD MMM YYYY hh:mm A')}
+
+ )
+ }
+
+ const getTransactionAmount = (amount: string) => {
+ return amount ? (
+ {amount}
+ ) : (
+ Not Available
+ )
+ }
+ return (
+ <>
+ {transactions.length === 0 && (
+
+
+ Transactions Loading...
+
+ )}
+ {filteredProcessedTransactions && (
+
+ {filteredProcessedTransactions.map(
+ (transaction: IProcessedTransaction, index) => {
+ return (
+ {transaction.status},
+ width: 88,
+ },
+ ]}
+ />
+ )
+ }
+ )}
+
+ )}
+
+ {filteredProcessedTransactions.length === 0 &&
+ transactions.length !== 0 &&
+ !loading && (
+
+
+ No Transactions Matching Filter.
+
+ )}
+ >
+ )
+}
diff --git a/packages/boba/gateway/src/containers/history/constants.ts b/packages/boba/gateway/src/containers/history/constants.ts
new file mode 100644
index 0000000000..e731957835
--- /dev/null
+++ b/packages/boba/gateway/src/containers/history/constants.ts
@@ -0,0 +1,213 @@
+import AllNetworksIcon from 'assets/images/allNetworks.svg'
+import { IDropdownItem } from 'components/global/dropdown'
+import { IFilterDropdownItem } from 'components/filter'
+import { TableHeaderOptionType } from 'components/global/table'
+import { getCoinImage } from 'util/coinImage'
+import { NETWORK_TYPE } from 'util/network/network.util'
+import { CHAIN_NAME, ChainMap } from './types'
+
+import bobaEth from 'assets/bobaEth.svg'
+import bobaBnb from 'assets/bobaBNB.svg'
+import bobaAvax from 'assets/bobaAvax.svg'
+
+import ethIcon from 'assets/ethereum.svg'
+
+export const Chains: ChainMap = {
+ '0': {
+ name: CHAIN_NAME.All_Networks,
+ transactionUrlPrefix: '',
+ symbol: '',
+ imgSrc: ethIcon,
+ },
+ '56': {
+ name: CHAIN_NAME.BNB,
+ transactionUrlPrefix: 'https://bscscan.com/tx/',
+ symbol: 'BNB',
+ imgSrc: getCoinImage('BNB'),
+ },
+ '56288': {
+ name: CHAIN_NAME.Boba_BNB,
+ transactionUrlPrefix: 'https://blockexplorer.bnb.boba.network/tx/',
+ symbol: 'BOBA',
+ imgSrc: bobaBnb,
+ },
+ '97': {
+ name: CHAIN_NAME.BNB_Testnet,
+ transactionUrlPrefix: 'https://testnet.bscscan.com/tx/',
+ symbol: 'BNB',
+ imgSrc: getCoinImage('BNB'),
+ },
+ '9728': {
+ name: CHAIN_NAME.Boba_BNB_Testnet,
+ transactionUrlPrefix: 'https://blockexplorer.testnet.bnb.boba.network/tx/',
+ symbol: 'BOBA',
+ imgSrc: bobaBnb,
+ },
+ '1': {
+ name: CHAIN_NAME.Ethereum,
+ transactionUrlPrefix: 'https://etherscan.io/tx/',
+ symbol: 'ETH',
+ imgSrc: ethIcon,
+ },
+ '288': {
+ name: CHAIN_NAME.Boba_Ethereum,
+ transactionUrlPrefix: 'https://bobascan.com/tx/',
+ symbol: 'BOBA',
+ imgSrc: bobaEth,
+ },
+ '5': {
+ name: CHAIN_NAME.Goerli,
+ transactionUrlPrefix: 'https://goerli.etherscan.io/tx/',
+ symbol: 'ETH',
+ imgSrc: ethIcon,
+ },
+ '2888': {
+ name: CHAIN_NAME.Boba_Goerli,
+ transactionUrlPrefix: 'https://testnet.bobascan.com/tx/',
+ symbol: 'BOBA',
+ imgSrc: bobaEth,
+ },
+ '43114': {
+ name: CHAIN_NAME.Avalanche,
+ transactionUrlPrefix: 'https://snowtrace.io/tx/',
+ symbol: 'AVAX',
+ imgSrc: getCoinImage('AVAX'),
+ },
+ '43288': {
+ name: CHAIN_NAME.Boba_Avalanche,
+ transactionUrlPrefix: 'https://blockexplorer.avax.boba.network/tx/',
+ symbol: 'BOBA',
+ imgSrc: bobaAvax,
+ },
+ '43113': {
+ name: CHAIN_NAME.Avalanche_Testnet,
+ transactionUrlPrefix: 'https://testnet.snowtrace.io/tx/',
+ symbol: 'AVAX',
+ imgSrc: getCoinImage('AVAX'),
+ },
+ '4328': {
+ name: CHAIN_NAME.Boba_Avalanche_Testnet,
+ transactionUrlPrefix: 'https://blockexplorer.testnet.avax.boba.network/tx/',
+ symbol: 'BOBA',
+ imgSrc: bobaAvax,
+ },
+}
+
+export const ALL_NETWORKS: IDropdownItem = {
+ value: '0',
+ label: 'All Networks',
+ imgSrc: AllNetworksIcon,
+ header: false,
+ headerName: '',
+}
+export const NETWORK_L1_OPTIONS: IDropdownItem[] = [
+ ALL_NETWORKS,
+ {
+ value: '1',
+ label: 'Ethereum',
+ imgSrc: ethIcon,
+ headerName: NETWORK_TYPE.MAINNET,
+ },
+ {
+ value: '56',
+ label: 'BNB',
+ imgSrc: getCoinImage('BNB'),
+ headerName: NETWORK_TYPE.MAINNET,
+ },
+ {
+ value: '43114',
+ label: 'AVAX',
+ imgSrc: getCoinImage('AVAX'),
+ headerName: NETWORK_TYPE.MAINNET,
+ },
+ {
+ value: '5',
+ label: 'Goerli',
+ imgSrc: ethIcon,
+ headerName: NETWORK_TYPE.TESTNET,
+ },
+ {
+ value: '97',
+ label: 'tBNB',
+ imgSrc: getCoinImage('BNB'),
+ headerName: NETWORK_TYPE.TESTNET,
+ },
+ {
+ value: '43113',
+ label: 'Fuji',
+ imgSrc: getCoinImage('AVAX'),
+ headerName: NETWORK_TYPE.TESTNET,
+ },
+]
+
+export const NETWORK_L2_OPTIONS = [
+ ALL_NETWORKS,
+ {
+ value: '288',
+ label: 'Boba Ethereum',
+ imgSrc: bobaEth,
+ headerName: NETWORK_TYPE.MAINNET,
+ },
+ {
+ value: '56288',
+ label: 'Boba BNB',
+ imgSrc: bobaBnb,
+ headerName: NETWORK_TYPE.MAINNET,
+ },
+ {
+ value: '43288',
+ label: 'Boba Avax',
+ imgSrc: bobaAvax,
+ headerName: NETWORK_TYPE.MAINNET,
+ },
+ {
+ value: '2888',
+ label: 'Boba Goerli',
+ imgSrc: bobaEth,
+ headerName: NETWORK_TYPE.TESTNET,
+ },
+ {
+ value: '9728',
+ label: 'Boba tBNB',
+ imgSrc: bobaBnb,
+ headerName: NETWORK_TYPE.TESTNET,
+ },
+ {
+ value: '4328',
+ label: 'Boba Fuji',
+ imgSrc: bobaAvax,
+ headerName: NETWORK_TYPE.TESTNET,
+ },
+]
+
+export const FILTER_OPTIONS: IFilterDropdownItem[] = [
+ { value: 'All', label: 'All Status' },
+ { value: 'Completed', label: 'Completed' },
+ { value: 'Pending', label: 'Pending' },
+ { value: 'Canceled', label: 'Canceled' },
+]
+
+export const TableOptions: TableHeaderOptionType[] = [
+ {
+ name: 'Date',
+ width: 168,
+ tooltip: '',
+ },
+ {
+ name: 'From',
+ width: 142,
+ tooltip: '',
+ },
+ {
+ name: 'To',
+ width: 142,
+ tooltip: '',
+ },
+ {
+ name: 'Token',
+ width: 90,
+ tooltip: '',
+ },
+ { name: 'Amount', width: 80, tooltip: '' },
+ { name: 'Status', width: 88, tooltip: '' },
+]
diff --git a/packages/boba/gateway/src/containers/history/styles.ts b/packages/boba/gateway/src/containers/history/styles.ts
new file mode 100644
index 0000000000..2b70189198
--- /dev/null
+++ b/packages/boba/gateway/src/containers/history/styles.ts
@@ -0,0 +1,819 @@
+import styled, { css } from 'styled-components'
+import { mobile, sdesktop, tablet } from 'themes/screens'
+import { Svg, Typography } from 'components/global'
+import Switch from 'assets/images/icons/switchIcon.svg'
+
+import {
+ Arrow,
+ Header,
+ DropdownContainer,
+ IconContainer as DropdownIconContianer,
+ Option,
+ DropdownBody,
+ DropdownContent,
+ OptionsHeader,
+ Icon as DropdownIcon,
+} from 'components/global/dropdown/styles'
+
+import { Dropdown } from 'components/global/dropdown/'
+
+export const DefaultIcon = styled.div`
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ background: ${props.theme.colors.gray[600]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ background: ${props.theme.colors.gray[200]};
+ `}
+`
+
+export const HistoryPageContainer = styled.div`
+ margin: 0px auto;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-around;
+ padding: 10px;
+ padding-top: 0;
+ width: 100%;
+ max-width: 1024px;
+ min-width: 480px;
+ ${sdesktop(css`
+ max-width: 750px;
+ gap: 0px 30px;
+ `)}
+`
+
+export const TableHeader = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+ ${mobile(
+ css`
+ padding: 0px;
+ `
+ )}
+`
+
+export const TableFilters = styled.div`
+ padding: 20px;
+ border-radius: 6px 6px 0px 0px;
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ ${tablet(css`
+ margin-bottom: 5px;
+ gap: 20px;
+ padding: 10px;
+ `)}
+ ${mobile(css`
+ gap: 10px;
+ margin-bottom: 0px;
+ p {
+ font-size: 12px;
+ }
+ `)}
+`
+
+export const DatePickerWrapper = styled.div`
+ display: flex;
+ gap: 18px;
+ align-items: center;
+ justify-content: space-between;
+ white-space: nowrap;
+ text-align: center;
+ ${mobile(css`
+ display: none;
+ `)}
+`
+
+export const MobileDatePickerWrapper = styled.div`
+ display: none;
+ align-items: center;
+ justify-content: space-between;
+ white-space: nowrap;
+ text-align: center;
+ gap: 8px;
+ ${mobile(css`
+ display: flex;
+ `)}
+`
+
+export const DateInput = styled.button`
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ border: 1px solid #545454;
+ border-radius: 8px;
+ background: #262626;
+ padding: 10px 20px;
+ color: ${({ theme }) => theme.color};
+`
+
+export const NetworkDropdowns = styled.div`
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ gap: 16px;
+ font-size: 16px;
+ align-items: center;
+ ${mobile(css`
+ font-size: 12px;
+ gap: 0px 5px;
+ `)}
+`
+export const TransactionsTableWrapper = styled.div`
+ width: 100%;
+`
+
+export const TransactionsWrapper = styled.div`
+ width: 100%;
+ overflow-y: auto;
+ max-height: 512px;
+ ${sdesktop(css`
+ width: 750px;
+ gap: 0px 30px;
+ `)}
+ ::-webkit-scrollbar-corner {
+ background: none;
+ }
+ &::-webkit-scrollbar {
+ width: 24px;
+ height: 24px;
+ }
+ &::-webkit-scrollbar-track {
+ width: 24px;
+ padding: 8px;
+ margin: 0px;
+ }
+
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ color: ${props.theme.colors.gray[800]};
+ &::-webkit-scrollbar-thumb {
+ background-color: ${props.theme.colors.gray[500]};
+ background-clip: padding-box;
+ border: 8px solid transparent;
+ border-radius: 12px;
+ }
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ color: ${props.theme.colors.gray[50]};
+
+ &::-webkit-scrollbar-thumb {
+ background-color: ${props.theme.colors.gray[300]};
+ background-clip: padding-box;
+ border: 8px solid transparent;
+ border-radius: 12px;
+ }
+ `};
+`
+export const TransactionDate = styled.div`
+ font-family: Roboto;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: normal;
+ text-align: left;
+ width: 168px;
+ white-space: nowrap;
+ ${mobile(css`
+ width: 110px;
+ font-size: 10px;
+ `)}
+`
+export const TransactionDetails = styled.div`
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ width: 142px;
+ gap: 8px;
+ text-align: left;
+`
+export const TransactionChainDetails = styled.div`
+ display: flex;
+ flex-direction: column;
+ font-size: 14px;
+ gap: 2px;
+`
+export const TransactionChain = styled.div`
+ width: 102px;
+ height: 16px;
+ ${mobile(css`
+ font-size: 10px;
+ width: 72px;
+ height: 12px;
+ `)}
+`
+
+export const TransactionHash = styled.a`
+ font-size: 12px;
+ text-decoration: underline;
+ width: 102px;
+ height: 16px;
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ color: ${props.theme.colors.gray[700]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ color: ${props.theme.colors.gray[100]};
+ `}
+ ${mobile(css`
+ font-size: 8px;
+ width: 72px;
+ height: 12px;
+ `)}
+`
+
+export const IncompleteTransactionHash = styled.div`
+ font-size: 12px;
+ width: 102px;
+ height: 16px;
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ color: ${props.theme.colors.gray[700]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ color: ${props.theme.colors.gray[100]};
+ `}
+${mobile(css`
+ font-size: 8px;
+ width: 72px;
+ height: 12px;
+ `)}
+`
+
+export const TransactionToken = styled.div`
+ display: flex;
+ flex-direction: row;
+ gap: 8px;
+ align-items: center;
+ width: 90px;
+ text-align: left;
+ font-size: 14px;
+ ${mobile(css`
+ font-size: 10px;
+ `)}
+`
+
+export const TransactionAmount = styled.div`
+ font-size: 14px;
+ width: 80px;
+ text-align: left;
+ ${mobile(css`
+ font-size: 10px;
+ `)}
+`
+
+export const Status = styled.div`
+ font-size: 14px;
+ width: 88px;
+ text-align: left;
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ color: ${props.theme.colors.gray[800]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ color: ${props.theme.colors.green[300]};
+ `}
+ ${mobile(css`
+ font-size: 10px;
+ `)}
+`
+
+export const IconContainer = styled.div`
+ width: 32px;
+ height: 32px;
+ direction: flex;
+ align-items: center;
+ justify-content: center;
+ ${mobile(css`
+ width: 24px;
+ height: 26px;
+ margin: 0px;
+ `)}
+`
+
+export const Icon = styled(Svg)`
+ display: flex;
+ align-content: center;
+ width: 32px;
+ height: 32px;
+ svg {
+ width: 32px;
+ height: auto;
+ }
+ ${mobile(css`
+ svg {
+ max-width: 24px;
+ height: auto;
+ }
+ `)}
+`
+
+export const Image = styled.img`
+ display: flex;
+ align-content: center;
+ width: 32px;
+ height: 32px;
+`
+
+export const SwitchIcon = styled(Svg).attrs({
+ src: Switch,
+ fill: '#AEDB01',
+})`
+ display: flex;
+
+ div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+ ${mobile(css`
+ svg {
+ max-width: 14px;
+ height: auto;
+ }
+ `)}
+`
+
+export const SwitchChainIcon = styled.div`
+ cursor: pointer;
+ margin: -12px auto;
+ width: 40px;
+ height: 40px;
+ padding: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 20px;
+ border: 2px solid
+ ${({ theme: { colors, name } }) =>
+ name === 'light' ? colors.gray[600] : colors.gray[200]};
+ background: ${({ theme: { colors } }) => colors.box.background};
+
+ &:hover {
+ border-color: ${({ theme: { colors, name } }) =>
+ name === 'light' ? colors.gray[600] : colors.gray[100]};
+ }
+
+ > div {
+ align-self: stretch;
+ }
+ transition: transform 0.3s ease-in-out;
+ &:hover {
+ transform: rotate(180deg);
+ }
+ ${mobile(css`
+ width: 25px;
+ height: 25px;
+ `)}
+`
+
+export const Table = styled.div`
+ border-radius: 12px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: space-between;
+ text-align: center;
+ width: 100%;
+ padding-bottom: 10px;
+
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ border: 1px solid ${props.theme.colors.gray[400]};
+ background: ${props.theme.colors.box.background};
+ box-shadow: ${props.theme.boxShadow};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ border: 1px solid ${props.theme.colors.gray[300]};
+ background: ${props.theme.colors.box.background};
+ `}
+ ${mobile(css`
+ flex-direction: 'column';
+ padding-bottom: 0px;
+ gap: 10px;
+ `)}
+ ${tablet(css`
+ margin-bottom: '5px';
+ padding-bottom: 0px;
+ `)}
+`
+
+export const NoHistory = styled.div`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ margin-left: auto;
+ margin-right: auto;
+ padding: 20px;
+ font-size: 16px;
+ gap: 10px;
+
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ color: ${props.theme.colors.gray[700]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ color: ${props.theme.colors.gray[100]};
+ `}
+
+ svg {
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ fill: ${props.theme.colors.gray[700]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ fill: ${props.theme.colors.gray[100]};
+ `}
+ }
+`
+
+export const DateDescriptions = styled(Typography)`
+ ${mobile(css`
+ display: none;
+ `)}
+`
+export const MobileDateDescriptions = styled(Typography)`
+ display: none;
+ ${mobile(css`
+ font-size: 12px !important;
+ display: flex;
+ `)}
+`
+
+export const DropdownNetwork = styled(Dropdown)`
+ ${DropdownContainer} {
+ font-size: 16px;
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ color: ${props.theme.colors.gray[800]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ color: ${props.theme.colors.gray[100]};
+ `};
+ ${mobile(css`
+ div {
+ font-size: 10px;
+ }
+ `)}
+ }
+ ${Header} {
+ border-radius: 20px;
+ min-width: 0px;
+ width: 210px;
+ padding: 6px 16px;
+ gap: 8px;
+ transition: all 0.3s ease;
+ display: flex;
+ z-index: unset;
+ flex-direction: row;
+ align-content: center;
+ div {
+ justify-content: space-between;
+ width: 100%;
+ font-family: Roboto;
+ font-style: normal;
+ font-size: 16px;
+ font-weight: 500;
+ line-height: normal;
+ ${DropdownIconContianer} {
+ width: 32px;
+ }
+ ${Arrow} {
+ width: 11px;
+ ${mobile(css`
+ display: flex;
+ align-items: center;
+ `)}
+ }
+ }
+ ${mobile(css`
+ width: 148px;
+ padding: 3px 5px;
+ white-space: nowrap;
+ div {
+ font-size: 12px;
+ }
+ `)}
+ }
+
+ ${Arrow} {
+ ${mobile(css`
+ svg {
+ width: 6px;
+ height: auto;
+ }
+ `)}
+ }
+
+ ${DropdownIconContianer} {
+ width: 16px;
+ height: 22px;
+ margin: 0px;
+ ${mobile(css`
+ width: 10px;
+ height: 16px;
+ svg {
+ width: 10px;
+ height: auto;
+ }
+ `)}
+ }
+ ${DropdownIcon} {
+ height: 20px;
+ width: 20px;
+ display: flex;
+ align-items: center;
+ div {
+ height: 20px;
+ width: 20px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ margin: 0px;
+ }
+ ${OptionsHeader} {
+ display: flex;
+ align-items: center;
+ font-size: 12px;
+ font-weight: bold;
+ justify-content: flex-start;
+ box-sizing: border-box;
+ border: 1px solid rgba(0, 0, 0, 0);
+ gap: 8px;
+ border-radius: 10px;
+ text-align: left;
+ color: inherit;
+ ${mobile(css`
+ font-size: 8px;
+ `)}
+ }
+
+ ${Option} {
+ display: flex;
+ align-items: center;
+ font-size: 12px;
+ font-weight: bold;
+ justify-content: flex-start;
+ gap: 8px;
+ border-radius: 10px;
+ text-align: left;
+ color: inherit;
+ ${mobile(css`
+ font-size: 10px;
+ `)}
+ }
+
+ ${DefaultIcon} {
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ background: ${props.theme.colors.gray[600]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ background: ${props.theme.colors.gray[200]};
+ `}
+ }
+
+ ${DropdownBody} {
+ min-width: 150px;
+ width: 100%;
+ top: 45px;
+ z-index: 1;
+ padding: 10px 0px 10px 0px;
+ box-sizing: border-box;
+ border: inherit;
+ border-top: 0px;
+ border-radius: 14px;
+
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ color: ${props.theme.colors.gray[800]};
+ border: 1px solid ${props.theme.colors.gray[400]};
+ box-shadow: 2px 2px 30px rgba(0, 0, 0, 0.15);
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ color: ${props.theme.colors.gray[100]};
+ border: 1px solid ${props.theme.colors.gray[400]};
+ box-shadow: ${props.theme.backShadow};
+ `}
+ }
+ ${DropdownContent} {
+ padding: 0px 10px;
+ max-height: 200px;
+ display: flex;
+ flex-direction: column;
+ gap: 5px 0px;
+ overflow-y: auto;
+ opacity: 1;
+ & > ${Option} {
+ transition: all 0.25s ease;
+ border-radius: 8px;
+ padding: 5px;
+ box-sizing: border-box;
+ border: 1px solid rgba(0, 0, 0, 0);
+ &:hover {
+ background: ${(props) => props.theme.colors.gray[400]};
+ }
+
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ svg {
+ fill: ${props.theme.colors.gray[800]};
+ }
+ &:hover {
+ border: 1px solid ${props.theme.colors.gray[600]};
+ }
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ svg {
+ fill: ${props.theme.colors.gray[100]};
+ }
+ &:hover {
+ border: 1px solid ${props.theme.colors.gray[100]};
+ }
+ `};
+ }
+ }
+`
+
+export const TableTransactionsContainer = styled.div`
+ width: 100%;
+ ${sdesktop(css`
+ overflow-x: auto;
+ `)}
+`
+
+export const DatePickerHeader = styled.div`
+ font-size: 14px;
+ padding: 8px 20px;
+ border-radius: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ ${({ theme: { name, colors } }) =>
+ name === 'light'
+ ? css`
+ background: ${colors?.gray[50]};
+ border: 1px solid ${colors?.gray[500]};
+ `
+ : css`
+ background: ${colors?.gray[500]};
+ border: 1px solid ${colors?.gray[300]};
+ `}
+
+ ${mobile(css`
+ height: 30px;
+ font-family: roboto;
+ width: 130px;
+ font-size: 10px;
+ `)}
+`
+
+export const DatePickerHeadersContainer = styled.div`
+ box-sizing: border-box;
+ position: relative;
+ display: flex;
+ flex-direction: row;
+`
+
+export const DatePickerDropdown = styled.div<{ isRange?: boolean }>`
+ transition: 0.25s all;
+ position: absolute;
+ width: 250px;
+ right: 0px;
+ top: 40px;
+ z-index: 1;
+ border-radius: 12px;
+
+ ${({ theme: { colors, name } }) =>
+ name === 'light'
+ ? css`
+ color: ${colors.gray[800]};
+ background: ${colors.gray[50]};
+ border: 1px solid ${colors.gray[500]};
+ `
+ : css`
+ color: ${colors.gray[50]};
+ background: ${colors.gray[500]};
+ border: 1px solid ${colors.gray[300]};
+ ${(isRange) =>
+ !isRange &&
+ css`
+ .rdp-day_selected {
+ border: 1px solid ${colors.gray[100]};
+ }
+ `}
+ `}
+
+ .rdp {
+ --rdp-cell-size: 30px;
+ --rdp-caption-font-size: 14px;
+ --rdp-caption-font-weight: 400;
+ --rdp-caption-font-family: roboto;
+ --rdp-accent-color: ${(props) => props.theme.colors.gray[400]};
+ --rdp-background-color: ${(props) => props.theme.colors.gray[400]};
+ }
+ ${(props) =>
+ props.isRange &&
+ props.theme.name === 'light' &&
+ css`
+ .rdp-day_selected {
+ border: 1px solid ${props.theme.colors.gray[600]};
+ color: ${props.theme.colors.gray[800]};
+ }
+ `}
+ ${(props) =>
+ !props.isRange &&
+ props.theme.name === 'dark' &&
+ css`
+ .rdp-day_selected {
+ border: 1px solid ${props.theme.colors.gray[100]};
+ }
+ `}
+
+ ${(props) =>
+ !props.isRange &&
+ css`
+ .rdp-day {
+ border-radius: 20%;
+ }
+ `}
+ ${(props) =>
+ props.isRange &&
+ css`
+ .rdp-day {
+ border: none !important;
+ }
+ `}
+`
+
+export const DatePickerContainer = styled.div`
+ display: inline-flex;
+ flex-direction: column;
+ position: relative;
+ cursor: pointer;
+ width: 100%;
+ transition: 0.25s all;
+ box-sizing: border-box;
+ font-family: 'Roboto', sans-serif;
+ ${(props) =>
+ props.theme.name === 'light' &&
+ css`
+ color: ${props.theme.colors.gray[800]};
+ `}
+ ${(props) =>
+ props.theme.name === 'dark' &&
+ css`
+ color: ${props.theme.colors.gray[50]};
+ `};
+`
diff --git a/packages/boba/gateway/src/containers/history/tests/__snapshots__/history.test.tsx.snap b/packages/boba/gateway/src/containers/history/tests/__snapshots__/history.test.tsx.snap
new file mode 100644
index 0000000000..aef57acbe9
--- /dev/null
+++ b/packages/boba/gateway/src/containers/history/tests/__snapshots__/history.test.tsx.snap
@@ -0,0 +1,347 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Testing history page Date Picker 1`] = `
+
+
+
+ 05/10/1970 12:00 am
+
+
+
+`;
+
+exports[`Testing history page Test History Page 1`] = `
+
+
+
+
+
+
+ Date Range From
+
+
+
+ To
+
+
+
+
+
+ Date Range
+
+
+
+ 02/21/2023 - 08/21/2023
+
+
+
+
+
+
+
+
+
+ From
+
+
+
+
+ To
+
+
+
+
+
+
+
+
+
+
+
+
+ No Transactions Matching Filter.
+
+
+
+
+
+
+`;
+
+exports[`Testing history page Test transaction resolver 1`] = `
+
+
+
+
+
+ No Transactions Matching Filter.
+
+
+
+`;
diff --git a/packages/boba/gateway/src/containers/history/tests/history.test.tsx b/packages/boba/gateway/src/containers/history/tests/history.test.tsx
new file mode 100644
index 0000000000..d12d208e1f
--- /dev/null
+++ b/packages/boba/gateway/src/containers/history/tests/history.test.tsx
@@ -0,0 +1,103 @@
+import { render, screen } from '@testing-library/react'
+import React from 'react'
+import CustomThemeProvider from 'themes'
+import { Provider } from 'react-redux'
+import configureStore from 'redux-mock-store'
+import History from '../History'
+import { TransactionsResolver } from '../TransactionsResolver'
+import DatePicker, { IDatePickerProps } from '../DatePicker'
+import {
+ CHAIN_NAME,
+ ITransactionFilter,
+ ITransactionsResolverProps,
+ TRANSACTION_FILTER_STATUS,
+} from '../types'
+const sampleTransactions = require('./sampleTransactions.json')
+
+const mockStore = configureStore()
+
+const renderHistory = ({ options = null }: any) => {
+ return render(
+
+
+
+
+
+ )
+}
+
+const renderTransactionsResolver = (props: ITransactionsResolverProps) => {
+ return render(
+
+
+
+
+
+ )
+}
+
+const renderDatePicker = (props: IDatePickerProps) => {
+ return render(
+
+ )
+}
+
+describe('Testing history page', () => {
+ const filter: ITransactionFilter = {
+ fromNetworkChainId: CHAIN_NAME.Boba_Goerli,
+ toNetworkChainId: CHAIN_NAME.Goerli,
+ status: TRANSACTION_FILTER_STATUS.All,
+ targetHash: '',
+ }
+ test('Test transaction resolver', () => {
+ const { asFragment } = renderTransactionsResolver({
+ transactions: sampleTransactions,
+ transactionsFilter: filter,
+ })
+ expect(asFragment()).toMatchSnapshot()
+ })
+ test('Test History Page', () => {
+ const { asFragment } = renderHistory({})
+ expect(asFragment()).toMatchSnapshot()
+ })
+
+ test('Date Picker', () => {
+ const { asFragment } = renderDatePicker({
+ selected: new Date(1970, 4, 10),
+ onChange: (date: Date) => console.log(date),
+ })
+ expect(asFragment()).toMatchSnapshot()
+ })
+})
diff --git a/packages/boba/gateway/src/containers/history/tests/sampleTransactions.json b/packages/boba/gateway/src/containers/history/tests/sampleTransactions.json
new file mode 100644
index 0000000000..f33e45022d
--- /dev/null
+++ b/packages/boba/gateway/src/containers/history/tests/sampleTransactions.json
@@ -0,0 +1,1040 @@
+[
+ {
+ "hash": "0x54b9f38f649f85d4857aa73c278ec531b14790e6f8206326b19978b568a632fb",
+ "blockNumber": 40299,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "timeStamp": 1689006676,
+ "exitL2": true,
+ "crossDomainMessage": {
+ "crossDomainMessage": 1,
+ "crossDomainMessageFinalize": 1,
+ "crossDomainMessageSendTime": 1689007296,
+ "crossDomainMessageEstimateFinalizedTime": 1689612096,
+ "fast": null,
+ "l1Hash": "0x7237046849fedbfa5cca30eb6ce4454302a2e37531ab9af44ed6a0d587cb1124",
+ "l1BlockNumber": 9323191,
+ "l1BlockHash": "0x05c9a7d47d42f657dc05795aed1fc5248f45579082fa70b3f516fbf990d6589d",
+ "l1From": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "l1To": "0xA6fA0867F39f3A3af7433C8A43f23bf26Efd1a48"
+ },
+ "stateRoot": {
+ "stateRootHash": "0x2149e9a491530f515ba00080ffe73e64c4998a21b53d9314e72d8562aa44025b",
+ "stateRootBlockNumber": 9323164,
+ "stateRootBlockHash": "0x67032dd29c71c82252f8bf70e2fe77be92144d2e67a2935f68872959db411f68",
+ "stateRootBlockTimeStamp": 1689007296
+ },
+ "action": {
+ "sender": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "to": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "token": "0x4200000000000000000000000000000000000023",
+ "amount": "13000000000000000000",
+ "receive": "13000000000000000000",
+ "feeRate": "0",
+ "fast": null,
+ "status": "succeeded"
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5,
+ "UserFacingStatus": "Completed"
+ },
+ {
+ "hash": "0x21fa90ccb09937d5dbbeca5945c79b0a744597dd6bededfcbe98474bc7079175",
+ "blockNumber": 40298,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1689006653,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x2149e9a491530f515ba00080ffe73e64c4998a21b53d9314e72d8562aa44025b",
+ "stateRootBlockNumber": 9323164,
+ "stateRootBlockHash": "0x67032dd29c71c82252f8bf70e2fe77be92144d2e67a2935f68872959db411f68",
+ "stateRootBlockTimeStamp": 1689007296
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x2af87df315c53d553ac4b788be0575d524e9c735a858b3977edec162a8214b6b",
+ "blockNumber": 40297,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1689006638,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x2149e9a491530f515ba00080ffe73e64c4998a21b53d9314e72d8562aa44025b",
+ "stateRootBlockNumber": 9323164,
+ "stateRootBlockHash": "0x67032dd29c71c82252f8bf70e2fe77be92144d2e67a2935f68872959db411f68",
+ "stateRootBlockTimeStamp": 1689007296
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x36c3c5dd6c169abc52bff3c52b782a5ed92c910ae8dddcf7e1ef759c88dfe03b",
+ "blockNumber": 40296,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1689006582,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x2149e9a491530f515ba00080ffe73e64c4998a21b53d9314e72d8562aa44025b",
+ "stateRootBlockNumber": 9323164,
+ "stateRootBlockHash": "0x67032dd29c71c82252f8bf70e2fe77be92144d2e67a2935f68872959db411f68",
+ "stateRootBlockTimeStamp": 1689007296
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0xcf4b261400b607ad82a11d2d6cc9e337f965bd68c3f18fce13db7432be21b863",
+ "blockNumber": 40295,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1689006564,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0xf5115cf4aa78d603eb21b9c26e4eb683e90ae2d3c82486cbcac97c9abdb0dc2d",
+ "stateRootBlockNumber": 9323117,
+ "stateRootBlockHash": "0xbd706f0842a4d2a7801a558958da202df6b501a990b2c0198020bf11473de903",
+ "stateRootBlockTimeStamp": 1689006636
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x483ab732b1c870b8f3a2ab4f026db1a4f092ebe7817b93d4df2b1e95985db4e7",
+ "blockNumber": 40293,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1689004896,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x691ca2f512ebbf1afcb3334d838ecc421d86d79681ff52fb890a81f3776c790c",
+ "stateRootBlockNumber": 9323003,
+ "stateRootBlockHash": "0x3fc017dcfb9816fdb05eb6a1d755c6dc7c4ca4011b46f2aee84551fa149c5ca7",
+ "stateRootBlockTimeStamp": 1689005040
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0xa681b7ebeb778c676d375b2cd8cf9b61f61a2a5b04953d9cc1730f989f9f146e",
+ "blockNumber": 40221,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "timeStamp": 1688748466,
+ "exitL2": true,
+ "crossDomainMessage": {
+ "crossDomainMessage": 1,
+ "crossDomainMessageFinalize": 1,
+ "crossDomainMessageSendTime": 1688748876,
+ "crossDomainMessageEstimateFinalizedTime": 1689353676,
+ "fast": null,
+ "l1Hash": "0x1f21a5b056f06d645d33d268e24cd4ba6525f310c95150b51e41598a5223aba4",
+ "l1BlockNumber": 9328378,
+ "l1BlockHash": "0x4c98f776fd46781091ed481097b8a614808044327e40675f20c5c9c2975fcef3",
+ "l1From": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "l1To": "0xA6fA0867F39f3A3af7433C8A43f23bf26Efd1a48"
+ },
+ "stateRoot": {
+ "stateRootHash": "0x515f912bb0abc7d2b35bea2941a953884982d203211019ab30db583abdf070a5",
+ "stateRootBlockNumber": 9306486,
+ "stateRootBlockHash": "0x3b6356902b518f533393dad15f3043221506a5ea9592da8913f0b1499ec26920",
+ "stateRootBlockTimeStamp": 1688748876
+ },
+ "action": {
+ "sender": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "to": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "token": "0x4200000000000000000000000000000000000023",
+ "amount": "15000000000000000000",
+ "receive": "15000000000000000000",
+ "feeRate": "0",
+ "fast": null,
+ "status": "succeeded"
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5,
+ "UserFacingStatus": "Completed"
+ },
+ {
+ "hash": "0xc02413fa53c4012541193bf1df9e997108462a84d7ffd41d8b354141ddc1ad4b",
+ "blockNumber": 40220,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1688748461,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x515f912bb0abc7d2b35bea2941a953884982d203211019ab30db583abdf070a5",
+ "stateRootBlockNumber": 9306486,
+ "stateRootBlockHash": "0x3b6356902b518f533393dad15f3043221506a5ea9592da8913f0b1499ec26920",
+ "stateRootBlockTimeStamp": 1688748876
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x1931463f5d6eb9c5a4f1ff7fbfe3d9ba4fde64c78f1ab56fd42f52a3bc95f9ff",
+ "blockNumber": 40219,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1688748396,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x515f912bb0abc7d2b35bea2941a953884982d203211019ab30db583abdf070a5",
+ "stateRootBlockNumber": 9306486,
+ "stateRootBlockHash": "0x3b6356902b518f533393dad15f3043221506a5ea9592da8913f0b1499ec26920",
+ "stateRootBlockTimeStamp": 1688748876
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x61f74be0687b1b51a206d881d3ede273be90ec927b9b5c23ab6b00f7a21537da",
+ "blockNumber": 40218,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000024",
+ "timeStamp": 1688744142,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x50374214c7de50be10bb0c8c59cbdfdd24c11efb25209eca2ab17e130bea49d3",
+ "stateRootBlockNumber": 9306204,
+ "stateRootBlockHash": "0xe5ff54eac77e8db4ab49cea92a15bed501c393ae8f514070afb80856dbeaf979",
+ "stateRootBlockTimeStamp": 1688744604
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x868d172eedeccf438e912eba569ee7473d5849682d69769811573fad85667087",
+ "blockNumber": 40202,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0xDBD71249Fe60c9f9bF581b3594734E295EAfA9b2",
+ "timeStamp": 1688684802,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x66a8a8e7d58e44c4b022d1fc92c56216620c02099f86024b37a3030ddadf8657",
+ "stateRootBlockNumber": 9302406,
+ "stateRootBlockHash": "0x382cfc5ad5a6cd0078dc4847180ba6b811ddbd21ba9168e374693d71ea2aa3d9",
+ "stateRootBlockTimeStamp": 1688685252
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x1d8a6ff5906f80da7cb5c8565bfda0e96898ca9b657bda4d685e3d522aac67cd",
+ "blockNumber": 40201,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1688684796,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x66a8a8e7d58e44c4b022d1fc92c56216620c02099f86024b37a3030ddadf8657",
+ "stateRootBlockNumber": 9302406,
+ "stateRootBlockHash": "0x382cfc5ad5a6cd0078dc4847180ba6b811ddbd21ba9168e374693d71ea2aa3d9",
+ "stateRootBlockTimeStamp": 1688685252
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0xbd32053a927efbd907f2dfe0a28af9f6af487b6d79d118a83ac8fe3408f97c47",
+ "blockNumber": 40196,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "timeStamp": 1688682308,
+ "exitL2": true,
+ "crossDomainMessage": {
+ "crossDomainMessage": 1,
+ "crossDomainMessageFinalize": 1,
+ "crossDomainMessageSendTime": 1688682948,
+ "crossDomainMessageEstimateFinalizedTime": 1689287748,
+ "fast": null,
+ "l1Hash": "0xf1e7b97e267eba6e8fc8ab063e50d720a310c23598dab3d2cb09734f9435213a",
+ "l1BlockNumber": 9322440,
+ "l1BlockHash": "0x70dbad1721c06f6847d0ebba84eca9208e4f01b2997c229e086fe65ed75943b7",
+ "l1From": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "l1To": "0xA6fA0867F39f3A3af7433C8A43f23bf26Efd1a48"
+ },
+ "stateRoot": {
+ "stateRootHash": "0xdfc6f54c11268896440c654903ff36719145c265871627fe5011a3feab11dc52",
+ "stateRootBlockNumber": 9302259,
+ "stateRootBlockHash": "0xb5de92e960ee45a2d1af78ef3a6443c2d1262ab3ba5f6ccf64c05df4e21c3e58",
+ "stateRootBlockTimeStamp": 1688682948
+ },
+ "action": {
+ "sender": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "to": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "token": "0x4200000000000000000000000000000000000023",
+ "amount": "20000000000000000000",
+ "receive": "20000000000000000000",
+ "feeRate": "0",
+ "fast": null,
+ "status": "succeeded"
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5,
+ "UserFacingStatus": "Completed"
+ },
+ {
+ "hash": "0x97d1976242be4a4b0ba2680267ceecfff42036b6d5be0e7301b284ba97fc3200",
+ "blockNumber": 40195,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1688682302,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0xdfc6f54c11268896440c654903ff36719145c265871627fe5011a3feab11dc52",
+ "stateRootBlockNumber": 9302259,
+ "stateRootBlockHash": "0xb5de92e960ee45a2d1af78ef3a6443c2d1262ab3ba5f6ccf64c05df4e21c3e58",
+ "stateRootBlockTimeStamp": 1688682948
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0xedef20eecda1be0ef60c7a99ede5ad46e89ba7708e908eb652261a8aa11603df",
+ "blockNumber": 40183,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "timeStamp": 1688664589,
+ "exitL2": true,
+ "crossDomainMessage": {
+ "crossDomainMessage": 1,
+ "crossDomainMessageFinalize": 1,
+ "crossDomainMessageSendTime": 1688668836,
+ "crossDomainMessageEstimateFinalizedTime": 1689273636,
+ "fast": null,
+ "l1Hash": "0x8ff4ef323cb1b208133896369f1637a7c457d55f089a3570194371c0697ede8b",
+ "l1BlockNumber": 9302235,
+ "l1BlockHash": "0x1577eb7a0f67ae6f5c309c5c49e86f4c7ee7120760c06a6d508f5d918633af07",
+ "l1From": "0xf9B706f189E3B1A816540BF757AF16514B8bE332",
+ "l1To": "0xA6fA0867F39f3A3af7433C8A43f23bf26Efd1a48"
+ },
+ "stateRoot": {
+ "stateRootHash": "0x9af20abe12816b928a952e23818e43c631c2a0e7ca4475365ea82a0f10396024",
+ "stateRootBlockNumber": 9301365,
+ "stateRootBlockHash": "0x14e2a1b4eb0c76c9f8487070470f2bc90efd5f509d47c2df40af75e86c6e3369",
+ "stateRootBlockTimeStamp": 1688668836
+ },
+ "action": {
+ "sender": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "to": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "token": "0x4200000000000000000000000000000000000023",
+ "amount": "30000000000000000000",
+ "receive": "30000000000000000000",
+ "feeRate": "0",
+ "fast": null,
+ "status": "succeeded"
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5,
+ "UserFacingStatus": "Completed"
+ },
+ {
+ "hash": "0x31b67a9e8c7ca0a355a10c3f5ae8f311bce66ee9507efca22f22856426f441e2",
+ "blockNumber": 40182,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1688664579,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x9af20abe12816b928a952e23818e43c631c2a0e7ca4475365ea82a0f10396024",
+ "stateRootBlockNumber": 9301365,
+ "stateRootBlockHash": "0x14e2a1b4eb0c76c9f8487070470f2bc90efd5f509d47c2df40af75e86c6e3369",
+ "stateRootBlockTimeStamp": 1688668836
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x1491815da205c1d5b903afa1cd53a9f95fe460c31d3bc4503dfb59e268733de8",
+ "blockNumber": 40180,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1688664200,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x9af20abe12816b928a952e23818e43c631c2a0e7ca4475365ea82a0f10396024",
+ "stateRootBlockNumber": 9301365,
+ "stateRootBlockHash": "0x14e2a1b4eb0c76c9f8487070470f2bc90efd5f509d47c2df40af75e86c6e3369",
+ "stateRootBlockTimeStamp": 1688668836
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x6c3c97931034f330c8873d1ea20d1b26b4f430e8da8e76ef65c9a1ce69a86481",
+ "blockNumber": 40122,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "timeStamp": 1688577844,
+ "exitL2": true,
+ "crossDomainMessage": {
+ "crossDomainMessage": 1,
+ "crossDomainMessageFinalize": 1,
+ "crossDomainMessageSendTime": 1688668836,
+ "crossDomainMessageEstimateFinalizedTime": 1689273636,
+ "fast": null,
+ "l1Hash": "0xccf6ea1f7896e13897bca15616ebb821e3afdf6a5a5274624c474e98e290360c",
+ "l1BlockNumber": 9328392,
+ "l1BlockHash": "0xc533944b395a124c838d984469a9ba997e242a61e5e74136acf72af17c502691",
+ "l1From": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "l1To": "0xA6fA0867F39f3A3af7433C8A43f23bf26Efd1a48"
+ },
+ "stateRoot": {
+ "stateRootHash": "0x9af20abe12816b928a952e23818e43c631c2a0e7ca4475365ea82a0f10396024",
+ "stateRootBlockNumber": 9301365,
+ "stateRootBlockHash": "0x14e2a1b4eb0c76c9f8487070470f2bc90efd5f509d47c2df40af75e86c6e3369",
+ "stateRootBlockTimeStamp": 1688668836
+ },
+ "action": {
+ "sender": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "to": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "token": "0x4200000000000000000000000000000000000023",
+ "amount": "20000000000000000000",
+ "receive": "20000000000000000000",
+ "feeRate": "0",
+ "fast": null,
+ "status": "succeeded"
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5,
+ "UserFacingStatus": "Completed"
+ },
+ {
+ "hash": "0x6afb17e32dc1dadd9585c434cb652376a43deb5dd421ae67e568f1d1695ff917",
+ "blockNumber": 40121,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1688577839,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x9af20abe12816b928a952e23818e43c631c2a0e7ca4475365ea82a0f10396024",
+ "stateRootBlockNumber": 9301365,
+ "stateRootBlockHash": "0x14e2a1b4eb0c76c9f8487070470f2bc90efd5f509d47c2df40af75e86c6e3369",
+ "stateRootBlockTimeStamp": 1688668836
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x04c0f0c540d4f505be9504cfa31524179f8d816dd2847d61de287ecacea44837",
+ "blockNumber": 40120,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1688577727,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x9af20abe12816b928a952e23818e43c631c2a0e7ca4475365ea82a0f10396024",
+ "stateRootBlockNumber": 9301365,
+ "stateRootBlockHash": "0x14e2a1b4eb0c76c9f8487070470f2bc90efd5f509d47c2df40af75e86c6e3369",
+ "stateRootBlockTimeStamp": 1688668836
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0x560759950bea44486efa9af0e4e0e73e92bc2727031be24086422220a0810762",
+ "blockNumber": 40029,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "timeStamp": 1688429149,
+ "exitL2": true,
+ "crossDomainMessage": {
+ "crossDomainMessage": 1,
+ "crossDomainMessageFinalize": 1,
+ "crossDomainMessageSendTime": 1688668836,
+ "crossDomainMessageEstimateFinalizedTime": 1689273636,
+ "fast": null,
+ "l1Hash": "0x206b55825e96adae5f9b0593035b018b74e882e8ac94651227ee08cabf1d04ea",
+ "l1BlockNumber": 9328413,
+ "l1BlockHash": "0xd6404cd45264d605f7c6c155eff526578ed8ced44a02a9acb616681ef640c16f",
+ "l1From": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "l1To": "0xA6fA0867F39f3A3af7433C8A43f23bf26Efd1a48"
+ },
+ "stateRoot": {
+ "stateRootHash": "0x9af20abe12816b928a952e23818e43c631c2a0e7ca4475365ea82a0f10396024",
+ "stateRootBlockNumber": 9301365,
+ "stateRootBlockHash": "0x14e2a1b4eb0c76c9f8487070470f2bc90efd5f509d47c2df40af75e86c6e3369",
+ "stateRootBlockTimeStamp": 1688668836
+ },
+ "action": {
+ "sender": "0x999933FF5284038197602a80173F4f4ECb634866",
+ "to": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "token": "0x4200000000000000000000000000000000000006",
+ "amount": "100000000000000",
+ "receive": "100000000000000",
+ "feeRate": "0",
+ "fast": null,
+ "status": "succeeded"
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5,
+ "UserFacingStatus": "Completed"
+ },
+ {
+ "hash": "0x0c8288b8b620b3b0c5394ed2a12d9c1bd9a8c7e474ed46c5cca1de1cc4d66d13",
+ "blockNumber": 40028,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x4200000000000000000000000000000000000023",
+ "timeStamp": 1688429140,
+ "exitL2": false,
+ "crossDomainMessage": {
+ "crossDomainMessage": 0,
+ "crossDomainMessageFinalize": 0,
+ "crossDomainMessageSendTime": null,
+ "crossDomainMessageEstimateFinalizedTime": null,
+ "fast": null,
+ "l1Hash": null,
+ "l1BlockNumber": null,
+ "l1BlockHash": null,
+ "l1From": null,
+ "l1To": null
+ },
+ "stateRoot": {
+ "stateRootHash": "0x9af20abe12816b928a952e23818e43c631c2a0e7ca4475365ea82a0f10396024",
+ "stateRootBlockNumber": 9301365,
+ "stateRootBlockHash": "0x14e2a1b4eb0c76c9f8487070470f2bc90efd5f509d47c2df40af75e86c6e3369",
+ "stateRootBlockTimeStamp": 1688668836
+ },
+ "action": {
+ "sender": null,
+ "to": null,
+ "token": null,
+ "amount": null,
+ "receive": null,
+ "feeRate": null,
+ "fast": null,
+ "status": null
+ },
+ "layer": "L2",
+ "chainName": "BOBA Goerli L2",
+ "originChainId": 2888,
+ "destinationChainId": 5
+ },
+ {
+ "hash": "0xff7923d5f7738b491c1362165ba7c7a6eb665ce0ba142478bd1f9dfd33c81468",
+ "blockNumber": 9328236,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0xDBD71249Fe60c9f9bF581b3594734E295EAfA9b2",
+ "timeStamp": 1689085644,
+ "contractName": "L1StandardBridge",
+ "contractAddress": "0xDBD71249Fe60c9f9bF581b3594734E295EAfA9b2",
+ "activity": "ERC20DepositInitiated",
+ "depositL2": true,
+ "crossDomainMessage": {
+ "crossDomainMessage": 1,
+ "crossDomainMessageFinalize": 1,
+ "crossDomainMessageSendTime": 1689085644,
+ "crossDomainMessageEstimateFinalizedTime": 1689085764,
+ "fast": 0,
+ "l2Hash": "0xf1421f4f8cc3a5b9a36068d4d19dfe55624672066b427eec6de04d3766e977f5",
+ "l2BlockNumber": 40330,
+ "l2BlockHash": "0x67125bb99e0688aec984477bd2a43f92fe426e003c93b18443782380124d8b0f",
+ "l2From": "0x0000000000000000000000000000000000000000",
+ "l2To": "0x4200000000000000000000000000000000000007"
+ },
+ "action": {
+ "sender": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "token": "0xeCCD355862591CBB4bB7E7dD55072070ee3d0fC1",
+ "amount": "20000000000000000000",
+ "receive": "20000000000000000000",
+ "feeRate": "0",
+ "fast": 0,
+ "status": "succeeded"
+ },
+ "layer": "L1pending",
+ "chainName": "Goerli",
+ "originChainId": 5,
+ "destinationChainId": 2888,
+ "UserFacingStatus": "Completed"
+ },
+ {
+ "hash": "0x30c27ee667cd51a2ad4df0f26c707c84404ea124e6fe2dda238afbcdb9bdf98e",
+ "blockNumber": 9328024,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0xDBD71249Fe60c9f9bF581b3594734E295EAfA9b2",
+ "timeStamp": 1689082296,
+ "contractName": "L1StandardBridge",
+ "contractAddress": "0xDBD71249Fe60c9f9bF581b3594734E295EAfA9b2",
+ "activity": "ETHDepositInitiated",
+ "depositL2": true,
+ "crossDomainMessage": {
+ "crossDomainMessage": 1,
+ "crossDomainMessageFinalize": 1,
+ "crossDomainMessageSendTime": 1689082296,
+ "crossDomainMessageEstimateFinalizedTime": 1689082416,
+ "fast": 0,
+ "l2Hash": "0xc4e42fb83f4bfb876404f29527b2c9906840406fd8f669070cecbb31eb8d011c",
+ "l2BlockNumber": 40329,
+ "l2BlockHash": "0x7a3074ea5381e8a84ba025b963935f80acbe6a9eb7ee59d1e0cb5cd256f64fcc",
+ "l2From": "0x0000000000000000000000000000000000000000",
+ "l2To": "0x4200000000000000000000000000000000000007"
+ },
+ "action": {
+ "sender": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "token": "0x0000000000000000000000000000000000000000",
+ "amount": "30000000000000000",
+ "receive": "30000000000000000",
+ "feeRate": "0",
+ "fast": 0,
+ "status": "succeeded"
+ },
+ "layer": "L1pending",
+ "chainName": "Goerli",
+ "originChainId": 5,
+ "destinationChainId": 2888,
+ "UserFacingStatus": "Completed"
+ },
+ {
+ "hash": "0x6d7c3b2c833bf55a4c6fd1e4ae0611f49a8e1471fa9aa12928bf177ba0bc3172",
+ "blockNumber": 9323009,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0xDBD71249Fe60c9f9bF581b3594734E295EAfA9b2",
+ "timeStamp": 1689005124,
+ "contractName": "L1StandardBridge",
+ "contractAddress": "0xDBD71249Fe60c9f9bF581b3594734E295EAfA9b2",
+ "activity": "ERC20DepositInitiated",
+ "depositL2": true,
+ "crossDomainMessage": {
+ "crossDomainMessage": 1,
+ "crossDomainMessageFinalize": 1,
+ "crossDomainMessageSendTime": 1689005124,
+ "crossDomainMessageEstimateFinalizedTime": 1689005244,
+ "fast": 0,
+ "l2Hash": "0x96d8de3ff0a1ddde0cd4562b9906fe2b780489984c6c3cfb5127f899b4bb8ff3",
+ "l2BlockNumber": 40294,
+ "l2BlockHash": "0xf2c46f385ccf6395637539332c3863cbbb3a1c19f9aefd4826cb5f5ada3387c0",
+ "l2From": "0x0000000000000000000000000000000000000000",
+ "l2To": "0x4200000000000000000000000000000000000007"
+ },
+ "action": {
+ "sender": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "token": "0xeCCD355862591CBB4bB7E7dD55072070ee3d0fC1",
+ "amount": "20000000000000000000",
+ "receive": "20000000000000000000",
+ "feeRate": "0",
+ "fast": 0,
+ "status": "succeeded"
+ },
+ "layer": "L1pending",
+ "chainName": "Goerli",
+ "originChainId": 5,
+ "destinationChainId": 2888,
+ "UserFacingStatus": "Completed"
+ },
+ {
+ "hash": "0xc590cb9dd4b18d07f9b510b1f665ce0fc173860abe2f3d30fdbe70fb3145e333",
+ "blockNumber": 9295665,
+ "from": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0xDBD71249Fe60c9f9bF581b3594734E295EAfA9b2",
+ "timeStamp": 1688580696,
+ "contractName": "L1StandardBridge",
+ "contractAddress": "0xDBD71249Fe60c9f9bF581b3594734E295EAfA9b2",
+ "activity": "ETHDepositInitiated",
+ "depositL2": true,
+ "crossDomainMessage": {
+ "crossDomainMessage": 1,
+ "crossDomainMessageFinalize": 1,
+ "crossDomainMessageSendTime": 1688580696,
+ "crossDomainMessageEstimateFinalizedTime": 1688580816,
+ "fast": 0,
+ "l2Hash": "0xcce24215c94ff680320207d12f3beaf2c23cd5ca3260f577b24f1a8c8d581810",
+ "l2BlockNumber": 40123,
+ "l2BlockHash": "0xe92a5b8291a00f247abb5677ad8e18a08ac69eaf51b382cb39a0116c1630f3e3",
+ "l2From": "0x0000000000000000000000000000000000000000",
+ "l2To": "0x4200000000000000000000000000000000000007"
+ },
+ "action": {
+ "sender": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "to": "0x1e2855A0EA33d5f293E5Ba2018874FAB9a7F05B3",
+ "token": "0x0000000000000000000000000000000000000000",
+ "amount": "100000000000000",
+ "receive": "100000000000000",
+ "feeRate": "0",
+ "fast": 0,
+ "status": "succeeded"
+ },
+ "layer": "L1pending",
+ "chainName": "Goerli",
+ "originChainId": 5,
+ "destinationChainId": 2888,
+ "UserFacingStatus": "Completed"
+ }
+]
\ No newline at end of file
diff --git a/packages/boba/gateway/src/containers/history/tokenInfo.ts b/packages/boba/gateway/src/containers/history/tokenInfo.ts
new file mode 100644
index 0000000000..758e90f2a3
--- /dev/null
+++ b/packages/boba/gateway/src/containers/history/tokenInfo.ts
@@ -0,0 +1,583 @@
+import { TokenInfoMap } from './types'
+
+export const TokenInfo: TokenInfoMap = {
+ '1': {
+ '0x0000000000000000000000000000000000000000': {
+ name: 'Etheruem',
+ symbol: 'ETH',
+ decimals: 18,
+ },
+ '0xd26114cd6ee289accf82350c8d8487fedb8a0c07': {
+ name: 'OMGToken',
+ symbol: 'OMG',
+ decimals: 18,
+ },
+ '0xdac17f958d2ee523a2206206994597c13d831ec7': {
+ name: 'Tether USD',
+ symbol: 'USDT',
+ decimals: 6,
+ },
+ '0x6b175474e89094c44da98b954eedeac495271d0f': {
+ name: 'Dai Stablecoin',
+ symbol: 'DAI',
+ decimals: 18,
+ },
+ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': {
+ name: 'USD Coin',
+ symbol: 'USDC',
+ decimals: 6,
+ },
+ '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599': {
+ name: 'Wrapped BTC',
+ symbol: 'WBTC',
+ decimals: 8,
+ },
+ '0x221657776846890989a759ba2973e427dff5c9bb': {
+ name: 'Reputation',
+ symbol: 'REPv2',
+ decimals: 18,
+ },
+ '0x0d8775f648430679a709e98d2b0cb6250d2887ef': {
+ name: 'Basic Attention Token',
+ symbol: 'BAT',
+ decimals: 18,
+ },
+ '0xe41d2489571d322189246dafa5ebde1f4699f498': {
+ name: '0x Protocol Token',
+ symbol: 'ZRX',
+ decimals: 18,
+ },
+ '0x6b3595068778dd592e39a122f4f5a5cf09c90fe2': {
+ name: 'SushiToken',
+ symbol: 'SUSHI',
+ decimals: 18,
+ },
+ '0x514910771af9ca656af840dff83e8264ecf986ca': {
+ name: 'ChainLink Token',
+ symbol: 'LINK',
+ decimals: 18,
+ },
+ '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984': {
+ name: 'Uniswap',
+ symbol: 'UNI',
+ decimals: 18,
+ },
+ '0x43dfc4159d86f3a37a5a4b3d4580b888ad7d4ddd': {
+ name: 'DODO bird',
+ symbol: 'DODO',
+ decimals: 18,
+ },
+ '0x853d955acef822db058eb8505911ed77f175b99e': {
+ name: 'Frax',
+ symbol: 'FRAX',
+ decimals: 18,
+ },
+ '0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0': {
+ name: 'Frax Share',
+ symbol: 'FXS',
+ decimals: 18,
+ },
+ '0x42bbfa2e77757c645eeaad1655e0911a7553efbc': {
+ name: 'Boba Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0xa47c8bf37f92abed4a126bda807a7b7498661acd': {
+ name: 'Wrapped UST Token',
+ symbol: 'UST',
+ decimals: 18,
+ },
+ '0x4fabb145d64652a948d72533023f6e7a623c7c53': {
+ name: 'Binance USD',
+ symbol: 'BUSD',
+ decimals: 18,
+ },
+ '0xb8c77482e45f1f44de1745f52c74426c631bdd52': {
+ name: 'BNB',
+ symbol: 'BNB',
+ decimals: 18,
+ },
+ '0x4e15361fd6b4bb609fa63c81a2be19d873717870': {
+ name: 'Fantom Token',
+ symbol: 'FTM',
+ decimals: 18,
+ },
+ '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0': {
+ name: 'Matic Token',
+ symbol: 'MATIC',
+ decimals: 18,
+ },
+ '0x04fa0d235c4abf4bcf4787af4cf447de572ef828': {
+ name: 'UMA Voting Token v1',
+ symbol: 'UMA',
+ decimals: 18,
+ },
+ '0xef5fa9f3dede72ec306dfff1a7ea0bb0a2f7046f': {
+ name: 'Domination Finance Token',
+ symbol: 'DOM',
+ decimals: 18,
+ },
+ '0xf56b164efd3cfc02ba739b719b6526a6fa1ca32a': {
+ name: 'Curio Governance Token',
+ symbol: 'CGT',
+ decimals: 18,
+ },
+ },
+ '5': {
+ '0x0000000000000000000000000000000000000000': {
+ name: 'Etheruem',
+ symbol: 'ETH',
+ decimals: 18,
+ },
+ '0xeccd355862591cbb4bb7e7dd55072070ee3d0fc1': {
+ name: 'Boba Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0x07865c6e87b9f70255377e024ace6630c1eaa37f': {
+ name: 'USD Coin',
+ symbol: 'USDC',
+ decimals: 6,
+ },
+ '0xcb9b561c91dda1a9bac33f7716a4d5586b7f5649': {
+ name: 'OMG Token',
+ symbol: 'OMG',
+ decimals: 18,
+ },
+ },
+ '56': {
+ '0x0000000000000000000000000000000000000000': {
+ name: 'BNB',
+ symbol: 'BNB',
+ decimals: 18,
+ },
+ '0xe0db679377a0f5ae2bae485de475c9e1d8a4607d': {
+ name: 'BOBA Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d': {
+ name: 'USD Coin',
+ symbol: 'USDC',
+ decimals: 18,
+ },
+ '0xe9e7cea3dedca5984780bafc599bd69add087d56': {
+ name: 'BUSD Token',
+ symbol: 'BUSD',
+ decimals: 18,
+ },
+ '0x55d398326f99059ff775485246999027b3197955': {
+ name: 'Tether USD',
+ symbol: 'USDT',
+ decimals: 18,
+ },
+ '0x986cdf0fd180b40c4d6aeaa01ab740b996d8b782': {
+ name: 'SushiToken',
+ symbol: 'SUSHI',
+ decimals: 18,
+ },
+ '0x2170ed0880ac9a755fd29b2688956bd959f933f8': {
+ name: 'Binance-Peg Ethereum Token',
+ symbol: 'ETH',
+ decimals: 18,
+ },
+ '0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c': {
+ name: 'Binance-Peg BTCB Token',
+ symbol: 'BTCB',
+ decimals: 18,
+ },
+ },
+ '97': {
+ '0x0000000000000000000000000000000000000000': {
+ name: 'tBNB',
+ symbol: 'tBNB',
+ decimals: 18,
+ },
+ '0x875cd11fdf085e0e11b0ee6b814b6d0b38fa554c': {
+ name: 'BOBA Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0x02ed46aa41fcb4a6f06a5f2d43a958f1e8c0a4e6': {
+ name: 'Meta Token Test',
+ symbol: 'MTT',
+ decimals: 18,
+ },
+ },
+ '288': {
+ '0x4200000000000000000000000000000000000006': {
+ name: 'Ethereum',
+ symbol: 'ETH',
+ decimals: 18,
+ },
+ '0xe1e2ec9a85c607092668789581251115bcbd20de': {
+ name: 'OMGToken',
+ symbol: 'OMG',
+ decimals: 18,
+ },
+ '0x5de1677344d3cb0d7d465c10b72a8f60699c062d': {
+ name: 'Tether USD',
+ symbol: 'USDT',
+ decimals: 6,
+ },
+ '0xf74195bb8a5cf652411867c5c2c5b8c2a402be35': {
+ name: 'Dai Stablecoin',
+ symbol: 'DAI',
+ decimals: 18,
+ },
+ '0x66a2a913e447d6b4bf33efbec43aaef87890fbbc': {
+ name: 'USD Coin',
+ symbol: 'USDC',
+ decimals: 6,
+ },
+ '0xdc0486f8bf31df57a952bcd3c1d3e166e3d9ec8b': {
+ name: 'Wrapped BTC',
+ symbol: 'WBTC',
+ decimals: 8,
+ },
+ '0x8b5b1e971862015bc058234fc11ce6c4a4c536dd': {
+ name: 'Reputation',
+ symbol: 'REPv2',
+ decimals: 18,
+ },
+ '0xc0c16df1ee7dcefb88c55003c49f57aa416a3578': {
+ name: 'Basic Attention Token',
+ symbol: 'BAT',
+ decimals: 18,
+ },
+ '0xf135f13db3b114107dcb0b32b6c9e10fff5a6987': {
+ name: '0x Protocol Token',
+ symbol: 'ZRX',
+ decimals: 18,
+ },
+ '0x5ffccc55c0d2fd6d3ac32c26c020b3267e933f1b': {
+ name: 'SushiToken',
+ symbol: 'SUSHI',
+ decimals: 18,
+ },
+ '0xd5d5030831ee83e22a2c9a5cf99931a50c676433': {
+ name: 'ChainLink Token',
+ symbol: 'LINK',
+ decimals: 18,
+ },
+ '0xdbde1347fed5dc03c74059010d571a16417d307e': {
+ name: 'Uniswap',
+ symbol: 'UNI',
+ decimals: 18,
+ },
+ '0x572c5b5bf34f75fb62c39b9bfe9a75bb0bb47984': {
+ name: 'DODO bird',
+ symbol: 'DODO',
+ decimals: 18,
+ },
+ '0xab2af3a98d229b7daed7305bb88ad0ba2c42f9ca': {
+ name: 'Frax',
+ symbol: 'FRAX',
+ decimals: 18,
+ },
+ '0xdc1664458d2f0b6090bea60a8793a4e66c2f1c00': {
+ name: 'Frax Share',
+ symbol: 'FXS',
+ decimals: 18,
+ },
+ '0xa18bf3994c0cc6e3b63ac420308e5383f53120d7': {
+ name: 'Boba Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0xe5ef1407928ebce28a6f1a0759251b7187fea726': {
+ name: 'Wrapped UST Token',
+ symbol: 'UST',
+ decimals: 18,
+ },
+ '0x352f2fdf653a194b42e3311f869237c66309b69e': {
+ name: 'Binance USD',
+ symbol: 'BUSD',
+ decimals: 18,
+ },
+ '0x68ac1623acf9eb9f88b65b5f229fe3e2c0d5789e': {
+ name: 'BNB',
+ symbol: 'BNB',
+ decimals: 18,
+ },
+ '0x841979bbc06be7bfe28d9faddac1a73e1fb495c1': {
+ name: 'Fantom Token',
+ symbol: 'FTM',
+ decimals: 18,
+ },
+ '0x26b664736217407e0fa252b4578db23b1e3819f3': {
+ name: 'Matic Token',
+ symbol: 'MATIC',
+ decimals: 18,
+ },
+ '0x5747a93c87943a9567c6db00b38f1e78bf14b7c0': {
+ name: 'xBOBA Token',
+ symbol: 'xBOBA',
+ decimals: 18,
+ },
+ '0x780f33ad21314d9a1ffb6867fe53d48a76ec0d16': {
+ name: 'UMA Voting Token v1',
+ symbol: 'UMA',
+ decimals: 18,
+ },
+ '0xf56fbec7823260d7510d63b63533153b58a01921': {
+ name: 'Domination Finance Token',
+ symbol: 'DOM',
+ decimals: 18,
+ },
+ '0xf56b164efd3cfc02ba739b719b6526a6fa1ca32a': {
+ name: 'Curio Governance Token',
+ symbol: 'CGT',
+ decimals: 18,
+ },
+ '0x8493c4d9cd1a79be0523791e3331c78abb3f9672': {
+ name: 'Boba WAGMI v0 Option',
+ symbol: 'WAGMIv0',
+ decimals: 18,
+ },
+ '0xce055ea4f29ffb8bf35e852522b96ab67cbe8197': {
+ name: 'Boba WAGMI v1 Option',
+ symbol: 'WAGMIv1',
+ decimals: 18,
+ },
+ '0x76b5908ecd0ae3db23011ae96b7c1f803d63136c': {
+ name: 'Boba WAGMI v2 Option',
+ symbol: 'WAGMIv2',
+ decimals: 18,
+ },
+ '0x49a3e4a1284829160f95ee785a1a5ffe2dd5eb1d': {
+ name: 'Boba WAGMI v2 Oolong Option',
+ symbol: 'WAGMIv2-Oolong',
+ decimals: 18,
+ },
+ '0xc6158b1989f89977bcc3150fc1f2eb2260f6cabe': {
+ name: 'Boba WAGMI v3 Option',
+ symbol: 'WAGMIv3',
+ decimals: 18,
+ },
+ '0x70bf3c5b5d80c4fece8bde0fce7ef38b688463d4': {
+ name: 'Boba WAGMI v3 Oolong Option',
+ symbol: 'WAGMIv3-Oolong',
+ decimals: 18,
+ },
+ '0x5008f837883ea9a07271a1b5eb0658404f5a9610': {
+ name: 'OolongSwap Token',
+ symbol: 'OLO',
+ decimals: 18,
+ },
+ },
+ '2888': {
+ '0x4200000000000000000000000000000000000023': {
+ name: 'Boba Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0x4200000000000000000000000000000000000006': {
+ name: 'Ethereum',
+ symbol: 'ETH',
+ decimals: 18,
+ },
+ '0x429582bde1b0e011c48d883354050938f194743f': {
+ name: 'USD Coin',
+ symbol: 'USDC',
+ decimals: 6,
+ },
+ '0x080bf38b43a1441873116002d36ccb583464cf45': {
+ name: 'OMG Token',
+ symbol: 'OMG',
+ decimals: 18,
+ },
+ '0x01c9dc8b9c66d61a56db7bf3f5303cd9e9c85b1f': {
+ name: 'xBOBA Token',
+ symbol: 'xBOBA',
+ decimals: 18,
+ },
+ },
+ '9728': {
+ '0x4200000000000000000000000000000000000006': {
+ name: 'BOBA Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0x4200000000000000000000000000000000000023': {
+ name: 'tBNB',
+ symbol: 'BNB',
+ decimals: 18,
+ },
+ '0xb3be5c928e3ec6b11985753f7b3c43a8bb12bc03': {
+ name: 'Meta Token Test',
+ symbol: 'MTT',
+ decimals: 18,
+ },
+ },
+ '56288': {
+ '0x4200000000000000000000000000000000000006': {
+ name: 'BOBA Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0x9f98f9f312d23d078061962837042b8918e6aff2': {
+ name: 'USD Coin',
+ symbol: 'USDC',
+ decimals: 18,
+ },
+ '0x4a2c2838c3907d024916c3f4fe07832745ae4bec': {
+ name: 'BUSD Token',
+ symbol: 'BUSD',
+ decimals: 18,
+ },
+ '0x1e633dcd0d3d349126983d58988051f7c62c543d': {
+ name: 'Tether USD',
+ symbol: 'USDT',
+ decimals: 18,
+ },
+ '0x4200000000000000000000000000000000000023': {
+ name: 'BNB',
+ symbol: 'BNB',
+ decimals: 18,
+ },
+ '0xa84d7c48602c898ec84c4cca78651107b3625943': {
+ name: 'SushiToken',
+ symbol: 'SUSHI',
+ decimals: 18,
+ },
+ '0x38ca7a190f57d38f4dc44413508e1078cd9e0045': {
+ name: 'Binance-Peg Ethereum Token',
+ symbol: 'ETH',
+ decimals: 18,
+ },
+ '0x876df0d9582699541caa1cd57b3a82cd51c2ad5b': {
+ name: 'Binance-Peg BTCB Token',
+ symbol: 'BTCB',
+ decimals: 18,
+ },
+ },
+ '43114': {
+ '0x0000000000000000000000000000000000000000': {
+ name: 'Avalanche',
+ symbol: 'AVAX',
+ decimals: 18,
+ },
+ '0x3cD790449CF7D187a143d4Bd7F4654d4f2403e02': {
+ name: 'BOBA Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0x42006Ab57701251B580bDFc24778C43c9ff589A1': {
+ name: 'EVO',
+ symbol: 'EVO',
+ decimals: 18,
+ },
+ '0xc7198437980c041c805A1EDcbA50c1Ce5db95118': {
+ name: 'Tether USD',
+ symbol: 'USDT.e',
+ decimals: 6,
+ },
+ '0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7': {
+ name: 'TetherToken',
+ symbol: 'USDt',
+ decimals: 6,
+ },
+ '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E': {
+ name: 'USD Coin',
+ symbol: 'USDC',
+ decimals: 6,
+ },
+ '0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664': {
+ name: 'USD Coin',
+ symbol: 'USDC.e',
+ decimals: 6,
+ },
+ '0x19860CCB0A68fd4213aB9D8266F7bBf05A8dDe98': {
+ name: 'Binance USD',
+ symbol: 'BUSD.e',
+ decimals: 18,
+ },
+ '0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39': {
+ name: 'BUSD Token',
+ symbol: 'BUSD',
+ decimals: 18,
+ },
+ '0xd586E7F844cEa2F87f50152665BCbc2C279D8d70': {
+ name: 'Dai Stablecoin',
+ symbol: 'DAI.e',
+ decimals: 18,
+ },
+ },
+ '43288': {
+ '0x4200000000000000000000000000000000000006': {
+ name: 'BOBA Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0xc8849f32138de93F6097199C5721a9EfD91ceE01': {
+ name: 'EVO',
+ symbol: 'EVO',
+ decimals: 18,
+ },
+ '0x4ED96c1dc969d7E2310D9582A68c39556C005912': {
+ name: 'Tether USD',
+ symbol: 'USDT.e',
+ decimals: 6,
+ },
+ '0xfaA13D82756f1e0e4dec9416b83121db3Fc35199': {
+ name: 'TetherToken',
+ symbol: 'USDt',
+ decimals: 6,
+ },
+ '0x12bb1A120dcF8Cb7152eDAC9f04d176DD7f41F7e': {
+ name: 'USD Coin',
+ symbol: 'USDC',
+ decimals: 6,
+ },
+ '0x126969743a6d300bab08F303f104f0f7DBAfbe20': {
+ name: 'USD Coin',
+ symbol: 'USDC.e',
+ decimals: 6,
+ },
+ '0xb8B0034CFD89925944C07Ac6CcB2834d1774cfb6': {
+ name: 'Binance USD',
+ symbol: 'BUSD.e',
+ decimals: 18,
+ },
+ '0x87e062dE99Ed71aF9b22dDA63e1b6D43333798f8': {
+ name: 'BUSD Token',
+ symbol: 'BUSD',
+ decimals: 18,
+ },
+ '0x69B7d24f0E03Ff21949081C95dA7288fEa5C844D': {
+ name: 'Dai Stablecoin',
+ symbol: 'DAI.e',
+ decimals: 18,
+ },
+ '0x4200000000000000000000000000000000000023': {
+ name: 'Avalanche',
+ symbol: 'AVAX',
+ decimals: 18,
+ },
+ },
+ '43113': {
+ '0x0000000000000000000000000000000000000000': {
+ name: 'Avalanche',
+ symbol: 'AVAX',
+ decimals: 18,
+ },
+ '0xEaE78E78cC22690719361F65a50734A15aaE698C': {
+ name: 'BOBA Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ },
+ '4328': {
+ '0x4200000000000000000000000000000000000006': {
+ name: 'BOBA Token',
+ symbol: 'BOBA',
+ decimals: 18,
+ },
+ '0x4200000000000000000000000000000000000023': {
+ name: 'Avalanche',
+ symbol: 'AVAX',
+ decimals: 18,
+ },
+ },
+}
diff --git a/packages/boba/gateway/src/containers/history/types.ts b/packages/boba/gateway/src/containers/history/types.ts
new file mode 100644
index 0000000000..c2fbd5a2eb
--- /dev/null
+++ b/packages/boba/gateway/src/containers/history/types.ts
@@ -0,0 +1,138 @@
+export enum TRANSACTION_FILTER_STATUS {
+ Pending = 'Pending',
+ Completed = 'Completed',
+ Canceled = 'Canceled',
+ All = 'All',
+}
+
+export enum TRANSACTION_STATUS {
+ Succeeded = 'succeeded',
+ Pending = 'pending',
+ Failed = 'failed',
+}
+
+export interface INetworks {
+ l1: string
+ l2: string
+}
+
+export enum CHAIN_NAME {
+ All_Networks = 'All Networks',
+ BNB_Testnet = 'tBNB',
+ Boba_BNB_Testnet = 'Boba tBNB',
+ BNB = 'BNB',
+ Boba_BNB = 'Boba BNB',
+ Ethereum = 'Ethereum',
+ Boba_Ethereum = 'Boba Ethereum',
+ Goerli = 'Goerli',
+ Boba_Goerli = 'Boba Goerli',
+ Avalanche = 'Avax',
+ Boba_Avalanche = 'Boba Avax',
+ Avalanche_Testnet = 'Fuji',
+ Boba_Avalanche_Testnet = 'Boba Fuji',
+}
+
+export enum LAYER {
+ L1 = 'L1',
+ L2 = 'L2',
+}
+
+export interface ITransactionFilter {
+ fromNetworkChainId: string
+ toNetworkChainId: string
+ startDate?: Date
+ endDate?: Date
+ status?: TRANSACTION_FILTER_STATUS
+ targetHash?: string
+}
+
+// why would we need to access the parent id of a chain
+// transactionTo's id is the parentID of the transaction
+// transactionFrom's parentID is the chainID of the transaction
+export interface IAction {
+ amount: string
+ fast: number
+ feeRate: string
+ receive: string
+ sender: string
+ status: string
+ to: string
+ token: string
+}
+
+export interface ICrossDomainMessage {
+ crossDomainMessage: number
+ crossDomainMessageEstimateFinalizedTime: number
+ crossDomainMessageFinalize: number
+ crossDomainMessageSendTime: number
+ fast: number
+ l2BlockHash?: string
+ l2BlockNumber?: number
+ l2From?: string
+ l2Hash?: string
+ l2To?: string
+ l1BlockHash?: string
+ l1BlockNumber?: number
+ l1From?: string
+ l1Hash?: string
+ l1To?: string
+}
+
+export interface ITransaction {
+ action: IAction
+ activity?: string
+ blockNumber: number
+ layer: string
+ originChainId: number
+ destinationChainId: number
+ contractAddress: string
+ contractName: string
+ crossDomainMessage: ICrossDomainMessage
+ depositL2?: boolean
+ exitL2?: boolean
+ from: string
+ hash: string
+ timeStamp: number
+ to: string
+ UserFacingStatus: TRANSACTION_FILTER_STATUS
+}
+
+export interface IProcessedTransaction {
+ timeStamp: number
+ from: string
+ fromHash: string
+ toHash: string
+ to: string
+ tokenSymbol: string
+ amount: string
+ status: TRANSACTION_FILTER_STATUS // need to remove the undefined option
+ originChainId: number
+ destinationChainId: number
+}
+
+export interface ITransactionsResolverProps {
+ transactionsFilter: ITransactionFilter
+ transactions: ITransaction[]
+ loading?: boolean
+}
+
+export type ChainMap = {
+ [key: string]: ChainInfo
+}
+
+export type ChainInfo = {
+ name: string
+ symbol: string
+ transactionUrlPrefix: string
+ imgSrc: string
+}
+
+export interface Token {
+ name: string
+ symbol: string
+ decimals: number
+}
+
+export type TokenInfoMap = {
+ [key: string]: { [key: string]: Token }
+}
diff --git a/packages/boba/gateway/src/containers/home/styles.ts b/packages/boba/gateway/src/containers/home/styles.ts
index 458d7c03d0..8b9abb0dd1 100644
--- a/packages/boba/gateway/src/containers/home/styles.ts
+++ b/packages/boba/gateway/src/containers/home/styles.ts
@@ -1,10 +1,10 @@
import styled from 'styled-components'
export const HomeContainer = styled.div`
- display: 'flex',
- alignContent: 'space-between',
- flexDirection: 'column',
- width: '100%'
+ display: flex;
+ flex-direction: column;
+ align-items: space-between;
+ width: 100%;
`
export const HomeContent = styled.div`
diff --git a/packages/boba/gateway/src/containers/modals/BridgeConfirmModal/index.styles.ts b/packages/boba/gateway/src/containers/modals/BridgeConfirmModal/index.styles.ts
index c9f489d158..ed62bd6dc5 100644
--- a/packages/boba/gateway/src/containers/modals/BridgeConfirmModal/index.styles.ts
+++ b/packages/boba/gateway/src/containers/modals/BridgeConfirmModal/index.styles.ts
@@ -25,6 +25,12 @@ export const LayerNames = styled.div`
align-items: center;
justify-content: flex-start;
gap: 8px;
+
+ svg,
+ img {
+ height: 30px;
+ width: 30px;
+ }
`
export const ConfirmActionButton = styled(Button)`
diff --git a/packages/boba/gateway/src/containers/modals/TransactionSuccessModal/index.tsx b/packages/boba/gateway/src/containers/modals/TransactionSuccessModal/index.tsx
index dbb687bad8..798e4d5d5f 100644
--- a/packages/boba/gateway/src/containers/modals/TransactionSuccessModal/index.tsx
+++ b/packages/boba/gateway/src/containers/modals/TransactionSuccessModal/index.tsx
@@ -34,7 +34,11 @@ const TransactionSuccessModal: FC = ({ open }) => {
const estimateTime = () => {
if (bridgeType === BRIDGE_TYPE.CLASSIC) {
- return '7 days'
+ if (layer === LAYER.L1) {
+ return '13 ~ 14mins.'
+ } else {
+ return '7 days'
+ }
} else {
if (layer === LAYER.L1) {
return '1 ~ 5min.'
diff --git a/packages/boba/gateway/src/containers/modals/dao/CastVoteModal.js b/packages/boba/gateway/src/containers/modals/dao/CastVoteModal.js
index 861e460d0b..4487c65df8 100644
--- a/packages/boba/gateway/src/containers/modals/dao/CastVoteModal.js
+++ b/packages/boba/gateway/src/containers/modals/dao/CastVoteModal.js
@@ -26,7 +26,7 @@ import Modal from 'components/modal/Modal'
import { castProposalVote } from 'actions/daoAction'
import BobaGlassIcon from 'components/icons/BobaGlassIcon'
import { selectLockRecords,selectLoading } from 'selectors'
-import BobaNFTGlass from 'images/boba2/BobaNFTGlass.svg'
+import BobaNFTGlass from 'assets/images/boba2/BobaNFTGlass.svg'
import networkService from 'services/networkService'
import { Dropdown } from 'components/global/dropdown'
diff --git a/packages/boba/gateway/src/containers/modals/dao/NewProposalModal.js b/packages/boba/gateway/src/containers/modals/dao/NewProposalModal.js
index ab4e581623..a0441ae565 100644
--- a/packages/boba/gateway/src/containers/modals/dao/NewProposalModal.js
+++ b/packages/boba/gateway/src/containers/modals/dao/NewProposalModal.js
@@ -29,7 +29,8 @@ import Select from 'components/select/Select'
import { createDaoProposal } from 'actions/daoAction'
import { selectProposalThreshold,selectLockRecords } from 'selectors'
import BobaGlassIcon from 'components/icons/BobaGlassIcon'
-import BobaNFTGlass from 'images/boba2/BobaNFTGlass.svg'
+import BobaNFTGlass from 'assets/images/boba2/BobaNFTGlass.svg'
+import { Dropdown } from 'components/global/dropdown'
const NewProposalModal = ({ open }) => {
@@ -203,25 +204,30 @@ const NewProposalModal = ({ open }) => {
change to the bridge fee limits for the L1 and L2 bridge pools.
}
-