diff --git a/packages/boba/gateway/src/actions/networkAction.js b/packages/boba/gateway/src/actions/networkAction.js index 24ee5743a5..f637ca961f 100644 --- a/packages/boba/gateway/src/actions/networkAction.js +++ b/packages/boba/gateway/src/actions/networkAction.js @@ -202,11 +202,11 @@ export function settle_v1() { ) } -export function monsterMint() { - return createAction('MONSTER/CREATE', () => - networkService.monsterMint() - ) -} +// export function monsterMint() { +// return createAction('MONSTER/CREATE', () => +// networkService.monsterMint() +// ) +// } export function fetchLookUpPrice(params) { return createAction('PRICE/GET', () => diff --git a/packages/boba/gateway/src/actions/nftAction.js b/packages/boba/gateway/src/actions/nftAction.js index 184daaead4..a4fbb1d6ed 100644 --- a/packages/boba/gateway/src/actions/nftAction.js +++ b/packages/boba/gateway/src/actions/nftAction.js @@ -14,11 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ import { createAction } from './createAction' +import networkService from 'services/networkService' + import store from 'store' export function getNFTs () { const state = store.getState() - return state.nft.list; + return state.nft.list } export async function addNFT ( NFT ) { @@ -50,6 +52,19 @@ export async function addNFT ( NFT ) { } +export async function addMonster ( monster ) { + store.dispatch({ + type: 'MONSTER/INFO/SUCCESS', + payload: monster + }) +} + +export function getMonsterInfo() { + return createAction('MONSTER/NUMBER', () => + networkService.checkMonster() + ) +} + export function removeNFT( UUID ) { return createAction('NFT/REMOVE', ()=>{ return UUID diff --git a/packages/boba/gateway/src/components/listNFT/listNFT.js b/packages/boba/gateway/src/components/listNFT/listNFT.js index 1cf9c40575..619b29d546 100644 --- a/packages/boba/gateway/src/components/listNFT/listNFT.js +++ b/packages/boba/gateway/src/components/listNFT/listNFT.js @@ -123,16 +123,11 @@ class listNFT extends React.Component { tokenID } = this.state - //console.log("meta:", meta) - //console.log("URL:", URL) - let rarity = '' if(meta && meta.hasOwnProperty("attributes")) { if(meta.attributes.length === 5){ if(meta.attributes[3].trait_type === 'Top') { rarity = 'Basic' - console.log(meta.attributes[3].value) - console.log(meta.attributes[4].value) if(meta.attributes[3].value === 'crown' && meta.attributes[4].value === 'wizzard') { rarity = 'Rarest (2/1000)' // 1000 * 5/256 * 20/256 } else if (meta.attributes[3].value === 'crown') { diff --git a/packages/boba/gateway/src/components/listNFT/listNFT.styles.js b/packages/boba/gateway/src/components/listNFT/listNFT.styles.js index 0a263f7851..0b52599b97 100644 --- a/packages/boba/gateway/src/components/listNFT/listNFT.styles.js +++ b/packages/boba/gateway/src/components/listNFT/listNFT.styles.js @@ -1,6 +1,5 @@ -import { Divider, Grid } from "@mui/material"; -import { styled } from '@mui/material/styles'; - +import { Divider, Grid } from "@mui/material" +import { styled } from '@mui/material/styles' export const ListNFTItem = styled(Grid)(({ theme, active }) => ({ borderRadius: '10px', @@ -12,7 +11,6 @@ export const ListNFTItem = styled(Grid)(({ theme, active }) => ({ flexDirection: 'column', justifyContent: 'space-around', alignItems: 'flex-start', - //gap: '30px', border: '1px solid transparent', padding: active ? '10px' : '0px', minHeight: '250px', diff --git a/packages/boba/gateway/src/components/mainMenu/menuItems/MenuItems.js b/packages/boba/gateway/src/components/mainMenu/menuItems/MenuItems.js index 32e221ba21..eb6fb47a8f 100644 --- a/packages/boba/gateway/src/components/mainMenu/menuItems/MenuItems.js +++ b/packages/boba/gateway/src/components/mainMenu/menuItems/MenuItems.js @@ -5,9 +5,22 @@ import * as S from './MenuItems.styles' import { useDispatch, useSelector } from 'react-redux' import { selectModalState } from 'selectors/uiSelector' import { setPage } from 'actions/uiAction' +import { selectMonster } from 'selectors/setupSelector' function MenuItems ({ setOpen }) { + const monsterNumber = useSelector(selectMonster()) + const monstersAdded = menuItems.some(item => item.key === 'Monster') + + if(monsterNumber > 0 && !monstersAdded) { + menuItems.push({ + key: 'Monster', + icon: "MonsterIcon", + title: "MonsterVerse", + url: "/" + }) + } + const pageDisplay = useSelector(selectModalState('page')) const dispatch = useDispatch() diff --git a/packages/boba/gateway/src/components/pageHeader/PageHeader.js b/packages/boba/gateway/src/components/pageHeader/PageHeader.js index 40a2222109..0da82d32ed 100644 --- a/packages/boba/gateway/src/components/pageHeader/PageHeader.js +++ b/packages/boba/gateway/src/components/pageHeader/PageHeader.js @@ -1,6 +1,7 @@ import React from 'react' import * as S from './PageHeader.styles' import { ReactComponent as BobaLogo } from '../../images/boba2/logo-boba2.svg' +import { ReactComponent as BobaLogoM } from '../../images/boba2/logo-boba2-m.svg' import MenuItems from 'components/mainMenu/menuItems/MenuItems' import LayerSwitcher from 'components/mainMenu/layerSwitcher/LayerSwitcher' import ThemeSwitcher from 'components/mainMenu/themeSwitcher/ThemeSwitcher' @@ -14,7 +15,7 @@ import networkService from 'services/networkService'; import { makeStyles } from '@mui/styles' import Copy from 'components/copy/Copy' import { useSelector } from 'react-redux' -import { selectAccountEnabled } from 'selectors/setupSelector' +import { selectAccountEnabled, selectMonster } from 'selectors/setupSelector' const useStyles = makeStyles({ root: { @@ -31,12 +32,16 @@ const PageHeader = ({ maintenance }) => { const [ walletOpen, setWalletOpen ] = useState(); const theme = useTheme() const accountEnabled = useSelector(selectAccountEnabled()) + const monsterNumber = useSelector(selectMonster()) const isMobile = useMediaQuery(theme.breakpoints.down('md')) + let Logo = BobaLogo + if(monsterNumber>0) Logo = BobaLogoM + if (maintenance) { return ( - + ) @@ -48,7 +53,7 @@ const PageHeader = ({ maintenance }) => { isMobile ? ( - + setWalletOpen(!walletOpen)} sx={{ cursor: 'pointer' }}> @@ -88,7 +93,7 @@ const PageHeader = ({ maintenance }) => { ) : ( - + diff --git a/packages/boba/gateway/src/containers/home/Home.js b/packages/boba/gateway/src/containers/home/Home.js index a7a8038e20..7ff535c735 100644 --- a/packages/boba/gateway/src/containers/home/Home.js +++ b/packages/boba/gateway/src/containers/home/Home.js @@ -33,10 +33,20 @@ import { fetchExits } from 'actions/networkAction' +import { + getMonsterInfo +} from 'actions/nftAction' + import networkService from 'services/networkService' import { setBaseState } from 'actions/setupAction' -import { selectBaseEnabled, selectAccountEnabled, selectNetwork, selectLayer } from 'selectors/setupSelector' +import { + selectBaseEnabled, + selectAccountEnabled, + selectNetwork, + selectLayer, + selectMonster +} from 'selectors/setupSelector' /**** ACTIONS and SELECTORS *****/ @@ -72,7 +82,11 @@ import { getProposalThreshold } from 'actions/daoAction' -import { fetchAirdropStatusL1, fetchAirdropStatusL2 } from 'actions/airdropAction' +import { + fetchAirdropStatusL1, + fetchAirdropStatusL2 +} from 'actions/airdropAction' + import { getFS_Saves, getFS_Info } from 'actions/fixedAction' import { fetchVerifierStatus } from 'actions/verifierAction' @@ -83,6 +97,7 @@ import BobaScope from 'containers/bobaScope/BobaScope' import Help from 'containers/help/Help' import Ecosystem from 'containers/ecosystem/Ecosystem' import Wallet from 'containers/wallet/Wallet' +import Monster from 'containers/monster/Monster' import { Box, Container } from '@mui/material' @@ -127,6 +142,7 @@ function Home() { const layer = useSelector(selectLayer()) const baseEnabled = useSelector(selectBaseEnabled()) const accountEnabled = useSelector(selectAccountEnabled()) + const monsterNumber = useSelector(selectMonster()) const handleErrorClose = () => dispatch(closeError()) const handleAlertClose = () => dispatch(closeAlert()) @@ -179,8 +195,9 @@ function Home() { dispatch(fetchExits()) // account specific dispatch(getFS_Saves()) // account specific dispatch(getFS_Info()) // account specific + dispatch(getMonsterInfo()) // account specific } - if(baseEnabled /*== we have Base L1 and L2 providers*/) { + if(baseEnabled /*== we only have have Base L1 and L2 providers*/) { dispatch(fetchGas()) dispatch(fetchVerifierStatus()) dispatch(getProposalThreshold()) @@ -195,12 +212,13 @@ function Home() { dispatch(fetchGas()) dispatch(fetchVerifierStatus()) dispatch(getProposalThreshold()) - }, [dispatch, maintenance]) + }, [ dispatch, maintenance ]) useEffect(() => { if (maintenance) return if (accountEnabled) { dispatch(addTokenList()) + dispatch(getMonsterInfo()) } }, [ dispatch, accountEnabled, maintenance ]) @@ -334,6 +352,9 @@ function Home() { {pageDisplay === "Ecosystem" && } + {pageDisplay === "Monster" && + + } diff --git a/packages/boba/gateway/src/containers/monster/Monster.js b/packages/boba/gateway/src/containers/monster/Monster.js new file mode 100644 index 0000000000..7d43c62943 --- /dev/null +++ b/packages/boba/gateway/src/containers/monster/Monster.js @@ -0,0 +1,269 @@ +import React from 'react' +import { connect } from 'react-redux' +import { isEqual } from 'lodash' + +import ListNFT from 'components/listNFT/listNFT' +import * as S from './Monster.styles' + +import { Box, Grid, Typography } from '@mui/material' + +import Input from 'components/input/Input' +import Button from 'components/button/Button' + +import networkService from 'services/networkService' +import LayerSwitcher from 'components/mainMenu/layerSwitcher/LayerSwitcher' +import AlertIcon from 'components/icons/AlertIcon' +import BobaGlassIcon from 'components/icons/BobaGlassIcon' +import Copy from 'components/copy/Copy' +import WalletPicker from 'components/walletpicker/WalletPicker' + +import truncate from 'truncate-middle' + +class Monster extends React.Component { + + constructor(props) { + + super(props) + + const { + list, + monsterNumber, + monsterInfo + } = this.props.nft + + const { + accountEnabled, + netLayer + } = this.props.setup + + this.state = { + list, + contractAddress: '', + tokenID: '', + loading: this.props.loading[ 'NFT/ADD' ], + accountEnabled, + netLayer, + monsterNumber, + monsterInfo + } + + } + + componentDidUpdate(prevState) { + + const { + list, + monsterNumber, + monsterInfo + } = this.props.nft + + const { + accountEnabled, + netLayer + } = this.props.setup + + if (!isEqual(prevState.nft.list, list)) { + this.setState({ list }) + } + + if (!isEqual(prevState.nft.monsterNumber, monsterNumber)) { + this.setState({ monsterNumber }) + } + + if (!isEqual(prevState.nft.monsterInfo, monsterInfo)) { + this.setState({ monsterInfo }) + } + + if (!isEqual(prevState.loading[ 'NFT/ADD' ], this.props.loading[ 'NFT/ADD' ])) { + this.setState({ loading: this.props.loading[ 'NFT/ADD' ] }) + if (this.props.loading[ 'NFT/ADD' ]) { + this.setState({ contractAddress: '' }) + } + } + + if (!isEqual(prevState.setup.accountEnabled, accountEnabled)) { + this.setState({ accountEnabled }) + } + + if (!isEqual(prevState.setup.netLayer, netLayer)) { + this.setState({ netLayer }) + } + + } + + handleInputAddress = event => { + this.setState({ contractAddress: event.target.value }) + } + + handleInputID = event => { + this.setState({ tokenID: event.target.value }) + } + + async addNFT() { + networkService.addNFT(this.state.contractAddress, this.state.tokenID) + } + + + render() { + + const { + list, + contractAddress, + tokenID, + loading, + netLayer, + monsterInfo, + monsterNumber + } = this.state + + let tokenIDverified = null + + //figure out which monster type we are dealing with + let monsterType = 'Monster' + if(monsterInfo.length > 0) { + tokenIDverified = monsterInfo.find(e => e.tokenID) + if(typeof(tokenIDverified) !== 'undefined') { + tokenIDverified = Number(monsterInfo.find(e => e.tokenID).tokenID) + } else { + tokenIDverified = null + } + + const type = monsterInfo.find(e => e.monsterType).monsterType + + if(type === 'crowned') { + monsterType = 'Crowned Monster' + } + else if (type === 'wizard') { + monsterType = 'Wizard Monster' + } + else if (type === 'crowned wizard') { + monsterType = 'Crowned Wizard' + } + } + + if (!netLayer) { + + return ( + + + + + + + Not connected. To access the MonsterVerse, CONNECT to Boba + + + + + + + ) + + } else if (netLayer === 'L1') { + + return ( + + + + + + + You are on Ethereum. To access the MonsterVerse, SWITCH to Boba + + + + + + + ) + } + + else { + + return ( + + + + + + + + MonsterVerse + + + + +
Welcome, esteemed {monsterType} {tokenIDverified} +
+ {tokenIDverified === null && + +
You have one or more Turing Monsters, but you have not added them to your NFT page (Wallet>NFT>Add NFT). Please add them to join the MonsterVerse. +
+ } +
+ {Object.keys(list).map((v, i) => { + const key_UUID = `nft_` + i + if(tokenIDverified === Number(list[v].tokenID)) { + return ( + ) + } + }) + } +
+
+ + + + Meetups + + + + Turing monster holders will be invited to meetups in different regions, such as Amsterdam, Dubai, and Hong Kong. + If you would like to host a meetup, or would like to propose one in your city, let us know - a signup system will + go live later in April. + + + + First look: Experimental Features + + + + Here is where we will showcase new features and projects, for you to see first. + + + + +
+ )} + } +} + +const mapStateToProps = state => ({ + nft: state.nft, + loading: state.loading, + setup: state.setup, +}) + +export default connect(mapStateToProps)(Monster) diff --git a/packages/boba/gateway/src/containers/monster/Monster.styles.js b/packages/boba/gateway/src/containers/monster/Monster.styles.js new file mode 100644 index 0000000000..c2d0e0a1fb --- /dev/null +++ b/packages/boba/gateway/src/containers/monster/Monster.styles.js @@ -0,0 +1,260 @@ +import { styled } from '@mui/material/styles' +import { Box, Typography, Grid, Divider } from "@mui/material" + +export const NFTPageContainer = styled(Box)(({ theme }) => ({ + margin: '20px auto', + display: 'flex', + justifyContent: 'space-around', + width: '100%', + 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', + flexDirection: 'column', + }, +})); + +export const NFTActionContent = styled(Box)(({ theme }) => ({ + width: '35%', + display: 'flex', + flexDirection: 'column', + justifyContent: 'flex-start', + gap: '10px', + [ theme.breakpoints.down('sm') ]: { + width: '100%', + }, +})); + +export const NFTFormContent = styled(Box)(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'flex-start', + padding: '10px', + borderRadius: '20px', + gap: '10px', + height: 'fit-content', + background: theme.palette.background.secondary, + [ theme.breakpoints.down('sm') ]: { + width: '100%', + }, +})); + +export const NFTListContainer = styled(Grid)((props) => ({ + width: '63%', + background: !props['data-empty'] ? props.theme.palette.background.secondary : 'none', + padding: !props['data-empty'] ? '10px' : 0, + borderRadius: !props['data-empty'] ? '20px' : 0, + [ props.theme.breakpoints.down('sm') ]: { + width: '100%', + }, +})) + +export const NFTPageContent = styled(Grid)(({ theme }) => ({ + marginTop: '20px', + padding: '10px', + borderRadius: '20px', + background: theme.palette.background.secondary, +})) + +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: "50%", + margin: '20px auto', + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-between', + alignItems: 'center', + gap: '30px', + borderRadius: '12px', + padding: '25px', + background: theme.palette.background.secondary, + [ theme.breakpoints.up('md') ]: { + width: '100%', + }, + [ theme.breakpoints.down('md') ]: { + width: '100%', + }, + +})); + +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; +`; + +export const DropdownWrapper = styled(Box)` + display: flex; + align-items: center; + justify-content: space-between; + gap: 5px; + width: 100%; + padding: 16px; + margin-top: 16px; + background-color: ${props => props.theme.palette.background.secondary}; + border-radius: 12px; + text-align: left; +`; + +export const DropdownContent = styled(Box)(({ theme }) => ({ + display: 'flex', + justifyContent: 'space-between', + [ theme.breakpoints.down('md') ]: { + flexDirection: 'column', + gap: '0', + }, + [ theme.breakpoints.up('md') ]: { + flexDirection: 'row', + gap: '16px', + }, +})); + +export const FarmActionContainer = styled(Box)(({ theme }) => ({ + display: 'flex', + justifyContent: 'space-around', + alignItems: 'center', + [ theme.breakpoints.down('md') ]: { + width: '100%' + } +})) + +export const FarmListContainer = 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 DividerLine = 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 TokenPageContentEmpty = styled(Box)(({ theme }) => ({ + width: '100%', + minHeight: '400px', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + padding: '10px', + borderRadius: '20px', + gap: '10px', + height: 'fit-content', + background: theme.palette.background.secondary, +})) + +export const TokenPageContent = styled(Box)(({ theme }) => ({ + width: '100%', + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + padding: '10px', + borderRadius: '20px', + gap: '10px', + height: 'fit-content', + background: theme.palette.background.secondary, + [ theme.breakpoints.down('sm') ]: { + width: 'fit-content', + minWidth: '100%' + }, +})) + +export const TokenPageContainer = styled(Box)(({ theme }) => ({ + display: 'flex', + justifyContent: 'space-around', + margin: '20px auto', + width: '100%', + gap: '10px', + [ theme.breakpoints.down('sm') ]: { + width: '100%', + padding: '0px', + overflowX: 'scroll', + display: 'block' + }, +})) diff --git a/packages/boba/gateway/src/containers/wallet/Wallet.js b/packages/boba/gateway/src/containers/wallet/Wallet.js index 286bce6830..25cdabc623 100644 --- a/packages/boba/gateway/src/containers/wallet/Wallet.js +++ b/packages/boba/gateway/src/containers/wallet/Wallet.js @@ -99,10 +99,12 @@ function Wallet() { console.log("l2Balances",l2Balances) const l2BalanceETH = l2Balances.find((i) => i.symbol === 'ETH') const l2BalanceBOBA = l2Balances.find((i) => i.symbol === 'BOBA') - if (l2BalanceETH[0]) { + + if (l2BalanceETH && l2BalanceETH[0]) { setTooSmallETH(new BN(logAmount(l2BalanceETH[0].balance, 18)).lt(new BN(0.003))) } - if (l2BalanceBOBA[0]) { + + if (l2BalanceBOBA && l2BalanceBOBA[0]) { setTooSmallBOBA(new BN(logAmount(l2BalanceBOBA[0].balance, 18)).lt(new BN(4.0))) } } @@ -225,22 +227,6 @@ function Wallet() { Disconnected : Connected } - {layer === 'L2' && - - - Need ETH or BOBA{'? '} - You can swap one for the other at - - Oologswap - - - - } - - 0xce458FC7cfC322cDd65eC77Cf7B6410002E2D793 + + 0xce45...D793 diff --git a/packages/boba/gateway/src/containers/wallet/token/Token.js b/packages/boba/gateway/src/containers/wallet/token/Token.js index a7ac4eaaf5..b6a616ce24 100644 --- a/packages/boba/gateway/src/containers/wallet/token/Token.js +++ b/packages/boba/gateway/src/containers/wallet/token/Token.js @@ -13,6 +13,7 @@ import ListToken from 'components/listToken/listToken' import lightLoader from 'images/boba2/loading_light.gif' import darkLoader from 'images/boba2/loading_dark.gif' +import Link from 'components/icons/LinkIcon' function TokenPage() { @@ -24,6 +25,7 @@ function TokenPage() { const networkLayer = useSelector(selectLayer()) const childBalance = useSelector(selectlayer2Balance, isEqual) const rootBalance = useSelector(selectlayer1Balance, isEqual) + const layer = useSelector(selectLayer()) const depositLoading = useSelector(selectLoading([ 'DEPOSIT/CREATE' ])) const exitLoading = useSelector(selectLoading([ 'EXIT/CREATE' ])) @@ -84,6 +86,24 @@ function TokenPage() { } else { return ( + <> + {layer === 'L2' && + + + Need ETH or BOBA{'? '} + You can swap one for the other at + + Oologswap + + + + } + @@ -127,7 +147,7 @@ function TokenPage() { : null} - ) + ) } } diff --git a/packages/boba/gateway/src/containers/wallet/token/Token.styles.js b/packages/boba/gateway/src/containers/wallet/token/Token.styles.js index b534c84ed5..6cf23ce72e 100644 --- a/packages/boba/gateway/src/containers/wallet/token/Token.styles.js +++ b/packages/boba/gateway/src/containers/wallet/token/Token.styles.js @@ -1,5 +1,5 @@ -import { Box, Typography } from "@mui/material"; -import { styled } from '@mui/material/styles'; +import { Box, Typography, IconButton } from '@mui/material' +import { styled } from '@mui/material/styles' export const TokenPageContainer = styled(Box)(({ theme }) => ({ display: 'flex', @@ -117,3 +117,14 @@ export const AlertInfo = styled(Box)` align-items: center; flex: 1; `; + +export const footerLink = styled(IconButton)(({ theme }) => ({ + '&:hover ': { + svg: { + path: { + fill: theme.palette.primary.main, + fillOpacity: 1, + } + } + } +})) diff --git a/packages/boba/gateway/src/images/boba2/logo-boba2-m.svg b/packages/boba/gateway/src/images/boba2/logo-boba2-m.svg new file mode 100644 index 0000000000..329660c7e7 --- /dev/null +++ b/packages/boba/gateway/src/images/boba2/logo-boba2-m.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/boba/gateway/src/layout/index.js b/packages/boba/gateway/src/layout/index.js index 2295152ce4..6783dcee31 100644 --- a/packages/boba/gateway/src/layout/index.js +++ b/packages/boba/gateway/src/layout/index.js @@ -85,9 +85,11 @@ function App () { body2: { fontSize: 16, fontWeight: 400, + lineHeight: '1.0em' }, body3: { - fontSize: '0.8em' + fontSize: '0.8em', + lineHeight: '1.0em' }, body4: { fontSize: 12 diff --git a/packages/boba/gateway/src/reducers/nftReducer.js b/packages/boba/gateway/src/reducers/nftReducer.js index 5fd7921996..ae586adef3 100644 --- a/packages/boba/gateway/src/reducers/nftReducer.js +++ b/packages/boba/gateway/src/reducers/nftReducer.js @@ -27,7 +27,9 @@ if (nftList) { } const initialState = { - list: nftList ? nftList : {} + list: nftList ? nftList : {}, + monsterNumber: 0, + monsterInfo: {} } function nftReducer (state = initialState, action) { @@ -49,6 +51,18 @@ function nftReducer (state = initialState, action) { } } + case 'MONSTER/INFO/SUCCESS': + return { + ...state, + monsterInfo: action.payload + } + + case 'MONSTER/NUMBER/SUCCESS': + return { + ...state, + monsterNumber: action.payload + } + case 'NFT/REMOVE/SUCCESS': let listN = state.list @@ -60,7 +74,7 @@ function nftReducer (state = initialState, action) { ...state, list: listN } - + default: return state } diff --git a/packages/boba/gateway/src/selectors/setupSelector.js b/packages/boba/gateway/src/selectors/setupSelector.js index 4d1aeb6ee0..4f660521f4 100644 --- a/packages/boba/gateway/src/selectors/setupSelector.js +++ b/packages/boba/gateway/src/selectors/setupSelector.js @@ -57,3 +57,15 @@ export function selectBobaPriceRatio () { return state.setup['bobaFeePriceRatio'] } } + +export function selectMonster () { + return function (state) { + return state.nft['monsterNumber'] + } +} + +export function selectMonsterInfo () { + return function (state) { + return state.nft['monsterInfo'] + } +} diff --git a/packages/boba/gateway/src/services/networkService.js b/packages/boba/gateway/src/services/networkService.js index 73f6ac4653..fd8e41cf57 100644 --- a/packages/boba/gateway/src/services/networkService.js +++ b/packages/boba/gateway/src/services/networkService.js @@ -31,6 +31,8 @@ import { getToken } from 'actions/tokenAction' import { addNFT, + addMonster, + getNFTs } from 'actions/nftAction' import { @@ -904,7 +906,7 @@ class NetworkService { return 'enabled' } catch (error) { - console.log(`NS: ERROR :InitializeBase `,error) + console.log(`NS: ERROR: InitializeBase `,error) return false } } @@ -1205,6 +1207,68 @@ class NetworkService { } } + async checkMonster() { + + const NFTs = getNFTs() + //console.log("NFTs:",NFTs) + let validMonsters = [] + + try { + + const contract = new ethers.Contract( + allAddresses.BobaMonsters, + TuringMonsterJson.abi, + this.L2Provider + ) + + const monsterBalance = await contract.balanceOf(this.account) + + let monsterType = 0 + let topMagic = 0 + let topTop = 0 + + if(NFTs && Number(monsterBalance) > 0) { + for (const [key, value] of Object.entries(NFTs)) { + //console.log(`${key}: ${value.name}`) + if(value.name === 'TuringMonster') { + const owner = await contract.ownerOf(value.tokenID) + //console.log("owner:", owner) + if(owner.toLowerCase() === this.account.toLowerCase()) { + const attributes = { + top: value.meta.attributes[3].value, + magic: value.meta.attributes[4].value, + } + if(value.meta.attributes[3].value === 'crown') topTop = 1 + if(value.meta.attributes[4].value === 'wizzard') topMagic = 1 + validMonsters.push({tokenID: value.tokenID, attributes}) + } + } + } + + if(topMagic === 0 && topTop === 0) { + validMonsters.push({monsterType: 'basic'}) + } else if (topMagic === 0 && topTop === 1) { + validMonsters.push({monsterType: 'crowned'}) + } else if (topMagic === 1 && topTop === 0) { + validMonsters.push({monsterType: 'wizard'}) + } else if (topMagic === 1 && topTop === 1) { + validMonsters.push({monsterType: 'crowned wizard'}) + } + + //console.log("adding monster info:",validMonsters) + await addMonster( validMonsters ) + + } + + return Number(monsterBalance.toString()) + + } catch (error) { + console.log("NS: checkMonster error:",error) + return error + } + + } + async addNFT( address, tokenID ) { try { diff --git a/packages/boba/gateway/src/util/nftImage.js b/packages/boba/gateway/src/util/nftImage.js index 8102f7c229..e7cdff5b97 100644 --- a/packages/boba/gateway/src/util/nftImage.js +++ b/packages/boba/gateway/src/util/nftImage.js @@ -26,8 +26,6 @@ const getIpfsUrl = (url) => { export const getNftImageUrl = async (url) => { - console.log("URL1:", url) - try { if(url.substring(0,29) === 'data:application/json;base64,') { // we have an svg