diff --git a/package.json b/package.json index b2cc64d..f1d7809 100755 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "license": "GPL-3.0-or-later", "dependencies": { "@jediswap/token-lists": "^1.0.0-beta.1", + "@szhsin/react-accordion": "^1.2.3", "babel-plugin-styled-components": "^2.0.7", "lodash": "^4.17.21", "react-countdown": "^2.3.5", diff --git a/src/App.js b/src/App.js index d66f860..10e9674 100755 --- a/src/App.js +++ b/src/App.js @@ -3,6 +3,9 @@ import styled from 'styled-components' import { Route, Switch, BrowserRouter, Redirect } from 'react-router-dom' import { ApolloProvider } from 'react-apollo' import { isEmpty } from 'lodash' +import VolumeContestLookup from './pages/VolumeContestLookup' +import VolumeContestAccountPage from './pages/VolumeContestPage' + import { jediSwapClient } from './apollo/client' import GlobalPage from './pages/GlobalPage' import TokenPage from './pages/TokenPage' @@ -226,6 +229,29 @@ function App() { + { + if (isStarknetAddress(match.params.accountAddress.toLowerCase())) { + return ( + + + + ) + } else { + return + } + }} + /> + + + + + + + diff --git a/src/Theme/index.js b/src/Theme/index.js index 979e1df..8c52dea 100755 --- a/src/Theme/index.js +++ b/src/Theme/index.js @@ -18,6 +18,7 @@ const theme = (darkMode, color) => ({ backgroundColor: darkMode ? '#252323' : '#F7F8FA', uniswapPink: darkMode ? '#FF00E9' : 'black', + jediGray: darkMode ? '#959595' : 'black', concreteGray: darkMode ? '#292C2F' : '#FAFAFA', inputBackground: darkMode ? '#1F1F1F' : '#FAFAFA', @@ -147,8 +148,7 @@ export const ThemedBackground = styled.div` max-width: 100vw !important; height: 200vh; mix-blend-mode: color; - background: ${({ backgroundColor }) => - `radial-gradient(50% 50% at 50% 50%, ${backgroundColor} 0%, rgba(255, 255, 255, 0) 100%)`}; + background: ${({ backgroundColor }) => `radial-gradient(50% 50% at 50% 50%, ${backgroundColor} 0%, rgba(255, 255, 255, 0) 100%)`}; position: absolute; top: 0px; left: 0px; diff --git a/src/apollo/queries.js b/src/apollo/queries.js index dc49d16..583857d 100755 --- a/src/apollo/queries.js +++ b/src/apollo/queries.js @@ -198,6 +198,7 @@ export const USER_LP_CONTEST_HISTORY = gql` } } ` + export const USER_LP_CONTEST_PERCENTILE = gql` query lpContestPercentile($user: String!) { lpContestPercentile(where: { user: $user }) { @@ -366,6 +367,30 @@ export const USER_LP_CONTEST_TRANSACTIONS = gql` } ` +export const USER_VOLUME_CONTEST_TRANSACTIONS = gql` + query transactions($user: String!) { + swaps(orderBy: "timestamp", orderByDirection: "desc", where: { to: $user }) { + id + transactionHash + timestamp + pair { + token0 { + symbol + } + token1 { + symbol + } + } + amount0In + amount0Out + amount1In + amount1Out + amountUSD + to + } + } +` + export const PAIR_CHART = gql` query pairDayDatas($pairAddress: String!, $skip: Int!) { pairDayDatas(first: 1000, skip: $skip, orderBy: "date", orderByDirection: "asc", where: { pair: $pairAddress }) { @@ -653,6 +678,27 @@ export const LP_CONTEST_DATA = gql` } ` +export const USER_VOLUME_CONTEST_DATA = (account) => { + const queryString = ` + query VolumeContest { + volumeContest(where: {user: "${account}", startDate: "2023-09-04"}) { + nftLevel + totalContestScore + totalContestVolume + weeks { + endDt + id + name + score + startDt + volume + } + } + } + ` + return gql(queryString) +} + export const LP_CONTEST_NFT_RANK = gql` query lpcontestnftrank { lpContestNftRank { @@ -802,7 +848,7 @@ export const TOKEN_DATA = (tokenAddress, block) => { } export const FILTERED_TRANSACTIONS = gql` - query ($allPairs: [String!]) { + query($allPairs: [String!]) { mints(first: 20, where: { pairIn: $allPairs }, orderBy: "timestamp", orderByDirection: "desc") { transactionHash timestamp diff --git a/src/assets/banners/cup.png b/src/assets/banners/cup.png new file mode 100644 index 0000000..fbe89ca Binary files /dev/null and b/src/assets/banners/cup.png differ diff --git a/src/assets/banners/cup@x2.png b/src/assets/banners/cup@x2.png new file mode 100644 index 0000000..14197af Binary files /dev/null and b/src/assets/banners/cup@x2.png differ diff --git a/src/assets/banners/digital_wallet.png b/src/assets/banners/digital_wallet.png new file mode 100644 index 0000000..657484d Binary files /dev/null and b/src/assets/banners/digital_wallet.png differ diff --git a/src/assets/banners/digital_wallet@x2.png b/src/assets/banners/digital_wallet@x2.png new file mode 100644 index 0000000..9b34f39 Binary files /dev/null and b/src/assets/banners/digital_wallet@x2.png differ diff --git a/src/assets/banners/nft.png b/src/assets/banners/nft.png new file mode 100644 index 0000000..791bac8 Binary files /dev/null and b/src/assets/banners/nft.png differ diff --git a/src/assets/banners/nft@x2.png b/src/assets/banners/nft@x2.png new file mode 100644 index 0000000..40fe919 Binary files /dev/null and b/src/assets/banners/nft@x2.png differ diff --git a/src/components/Banner/index.js b/src/components/Banner/index.js index 87942bd..1973c81 100644 --- a/src/components/Banner/index.js +++ b/src/components/Banner/index.js @@ -1,31 +1,32 @@ import React from 'react' import styled from 'styled-components' -import Panel from "../Panel"; +import Panel from '../Panel' const PollingDot = styled.div` width: 13px; height: 13px; border-radius: 50%; background-color: ${({ theme }) => theme.green2}; -`; +` -const Title = styled.div` +export const Title = styled.div` display: flex; align-items: center; font-size: 16px; font-weight: 500; margin-bottom: 14px; -`; +` const TitleIconWrapper = styled.div` display: flex; - margin-right: .75rem; -`; + margin-right: 0.75rem; +` const Wrapper = styled(Panel)` padding: 24px; position: relative; color: #fff; + overflow: hidden; ${PollingDot} { position: absolute; @@ -36,27 +37,45 @@ const Wrapper = styled(Panel)` @media screen and (max-width: 800px) { padding: 14px; } -`; +` const Content = styled.div` font-weight: 700; font-size: 26px; -`; +` +const MainContent = styled.div` + position: relative; + z-index: 2; +` +export const DecorationWrapper = styled.div` + position: absolute; + z-index: 1; + top: 0; + left: 0; + width: 100%; + height: 100%; -export function Banner({title, titleIcon = null, content, showPollingDot}) { - return ( - - - {titleIcon && (<TitleIconWrapper>{titleIcon}</TitleIconWrapper>)} - {title} - - - {content} - + & > * { + position: absolute; + bottom: 0; + right: 0; + } +` - {showPollingDot && ()} - - ) -} +export function Banner({ className, title, titleIcon = null, decoration = null, content, showPollingDot = false, style = {} }) { + return ( + + + + {titleIcon && <TitleIconWrapper>{titleIcon}</TitleIconWrapper>} + {title} + + {content} + {showPollingDot && } + + {decoration && {decoration}} + + ) +} diff --git a/src/components/ButtonStyled/index.js b/src/components/ButtonStyled/index.js index 1e06b23..47fae36 100755 --- a/src/components/ButtonStyled/index.js +++ b/src/components/ButtonStyled/index.js @@ -72,8 +72,29 @@ export const ButtonLight = styled(Base)` } :hover { - background-color: ${({ color, theme }) => - color ? transparentize(0.8, color) : transparentize(0.8, theme.primary1)}; + background-color: ${({ color, theme }) => (color ? transparentize(0.8, color) : transparentize(0.8, theme.primary1))}; + } +` + +export const ButtonGradient = styled(Base)` + background: linear-gradient(95deg, #29aafd 8%, #ff00e9 105%); + color: #fff; + transition: background-position 0.1s; + font-size: 16px; + font-weight: 750; + border: none; + white-space: nowrap; + + &:hover { + background-position: 100%; + } + + &[disabled] { + cursor: default; + background: rgba(196, 196, 196, 0.01); + box-shadow: inset 0px -63.1213px 52.3445px -49.2654px rgba(96, 68, 145, 0.3), inset 0px 75.4377px 76.9772px -36.9491px rgba(202, 172, 255, 0.3), + inset 0px 3.07909px 13.8559px rgba(154, 146, 210, 0.3), inset 0px 0.769772px 30.7909px rgba(227, 222, 255, 0.2); + overflow: hidden; } ` @@ -103,13 +124,17 @@ export const ButtonDark = styled(Base)` border-radius: 12px; white-space: nowrap; - ${(props) => !props.disabled && ` + ${(props) => + !props.disabled && + ` :hover { background-color: ${({ color, theme }) => (color ? darken(0.1, color) : darken(0.1, theme.primary1))}; } `} - - ${(props) => props.disabled && ` + + ${(props) => + props.disabled && + ` opacity: 0.5; cursor: default; `} diff --git a/src/components/FAQ/index.js b/src/components/FAQ/index.js new file mode 100755 index 0000000..51404c6 --- /dev/null +++ b/src/components/FAQ/index.js @@ -0,0 +1,140 @@ +import React from 'react' +import styled, { css } from 'styled-components' +import { Accordion as AccordionWrapper, AccordionItem as Item } from '@szhsin/react-accordion' +import { ChevronDown } from 'react-feather' + +import { TYPE } from '../../Theme' +import { AutoRow } from '../Row' + +const Wrapper = styled.div`` + +const ItemWithChevron = ({ header, ...rest }) => ( + + + + + {header} + + } + /> +) + +const Accordion = styled(AccordionWrapper)` + flex-grow: 1; +` + +const AccordionsLine = styled(AutoRow)` + ${Accordion} { + width: calc(100% / ${(props) => props.columnsAmount || 1}); + } + @media screen and (max-width: ${(props) => (props.columnsAmount === 3 ? '1200px' : props.columnsAmount === 2 ? '960px' : '0px')}) { + flex-direction: column; + + ${Accordion} { + width: 100%; + margin-bottom: 0 !important; + } + + ${Accordion} + ${Accordion} { + margin-top: 0 !important; + } + } +` + +const AccordionItem = styled(ItemWithChevron)` + --activeBackgroundColor: rgba(255, 255, 255, 0.05); + + & { + background: transparent; + border-radius: 8px; + transition: all 0.25s; + margin-bottom: 12px; + } + + &:hover { + background: var(--activeBackgroundColor); + } + + .szh-accordion__item-btn { + display: flex; + width: 100%; + padding: 12px; + background: transparent; + cursor: pointer; + border: none; + color: #fff; + font-size: 16px; + font-weight: 700; + align-items: center; + text-align: left; + } + + .szh-accordion__item-btn .chevron-wrapper { + margin-right: 10px; + display: flex; + } + + .szh-accordion__item-content { + transition: height 0.25s cubic-bezier(0, 0, 0, 1); + } + + .szh-accordion__item-panel { + padding: 1rem; + } + + svg { + margin-left: auto; + transition: transform 0.25s cubic-bezier(0, 0, 0, 1); + } + + &.szh-accordion__item--expanded { + background: var(--activeBackgroundColor); + + svg { + transform: rotate(180deg); + } + } +` + +const MAX_COLUMNS = 3 +const DEFAULT_ACCORDION_PROPS = { + transition: true, + transitionTimeout: 250, + allowMultiple: true, +} + +const FAQ = ({ items = [], columns = 1, accordionProps = {} }) => { + const columnsAmount = Math.min(Math.abs(columns), MAX_COLUMNS) || 1 + const columnSize = Math.ceil(items.length / columnsAmount) + + const mergedAccordionProps = { + ...DEFAULT_ACCORDION_PROPS, + ...accordionProps, + } + + if (!items?.length) { + return null + } + return ( + + + {Array.from({ length: columnsAmount }).map((n, i) => { + return ( + + {items.slice(i * columnSize, (i + 1) * columnSize).map(({ header, content }, i) => ( + + {content} + + ))} + + ) + })} + + + ) +} + +export default FAQ diff --git a/src/components/Panel/index.js b/src/components/Panel/index.js index af41ecb..eb32855 100755 --- a/src/components/Panel/index.js +++ b/src/components/Panel/index.js @@ -27,10 +27,8 @@ const Panel = styled(RebassBox)` flex-direction: column; justify-content: flex-start; border-radius: 8px; - box-shadow: rgb(255 255 255 / 50%) 0px 30.0211px 43.1072px -27.7118px inset, - rgb(255 255 255) 0px 5.38841px 8.46749px -3.07909px inset, - rgb(96 68 145 / 30%) 0px -63.1213px 52.3445px -49.2654px inset, - rgb(202 172 255 / 30%) 0px 75.4377px 76.9772px -36.9491px inset, + box-shadow: rgb(255 255 255 / 50%) 0px 30.0211px 43.1072px -27.7118px inset, rgb(255 255 255) 0px 5.38841px 8.46749px -3.07909px inset, + rgb(96 68 145 / 30%) 0px -63.1213px 52.3445px -49.2654px inset, rgb(202 172 255 / 30%) 0px 75.4377px 76.9772px -36.9491px inset, rgb(154 146 210 / 30%) 0px 3.07909px 13.8559px inset, rgb(227 222 255 / 20%) 0px 0.769772px 30.7909px inset; border: 1px solid ${({ theme }) => theme.bg3}; @@ -68,19 +66,11 @@ const Panel = styled(RebassBox)` ${(props) => !props.last && panelPseudo} ` -export default Panel +export const VolumeContestPanel = styled(Panel)` + box-shadow: none; + border-radius: 8px; + border: 1px solid rgba(160, 160, 160, 0.4); + background: rgba(255, 255, 255, 0.05); +` -// const Panel = styled.div` -// width: 100%; -// height: 100%; -// display: flex; -// flex-direction: column; -// justify-content: flex-start; -// border-radius: 12px; -// background-color: ${({ theme }) => theme.advancedBG}; -// padding: 1.25rem; -// box-sizing: border-box; -// box-shadow: 0 1.1px 2.8px -9px rgba(0, 0, 0, 0.008), 0 2.7px 6.7px -9px rgba(0, 0, 0, 0.012), -// 0 5px 12.6px -9px rgba(0, 0, 0, 0.015), 0 8.9px 22.6px -9px rgba(0, 0, 0, 0.018), -// 0 16.7px 42.2px -9px rgba(0, 0, 0, 0.022), 0 40px 101px -9px rgba(0, 0, 0, 0.03); -// ` +export default Panel diff --git a/src/components/SideNav/index.js b/src/components/SideNav/index.js index d1737b6..8defdf1 100755 --- a/src/components/SideNav/index.js +++ b/src/components/SideNav/index.js @@ -136,6 +136,18 @@ function SideNav({ history }) { + + + +