Mp 2591 add terms of service (#300)
This commit is contained in:
parent
d949cc84b7
commit
48d07173fb
@ -19,7 +19,7 @@ NEXT_PUBLIC_CANDLES_ENDPOINT="https://api.thegraph.com/subgraphs/name/{NAME}/{GR
|
|||||||
CHARTING_LIBRARY_USERNAME="username_with_access_to_charting_library"
|
CHARTING_LIBRARY_USERNAME="username_with_access_to_charting_library"
|
||||||
CHARTING_LIBRARY_ACCESS_TOKEN="access_token_with_access_to_charting_library"
|
CHARTING_LIBRARY_ACCESS_TOKEN="access_token_with_access_to_charting_library"
|
||||||
CHARTING_LIBRARY_REPOSITORY="github.com/username/charting_library/"
|
CHARTING_LIBRARY_REPOSITORY="github.com/username/charting_library/"
|
||||||
NEXT_PUBLIC_PYTH_ENDPOINT=https://xc-mainnet.pyth.network/api/
|
NEXT_PUBLIC_PYTH_ENDPOINT=https://xc-mainnet.pyth.network/api
|
||||||
NEXT_PUBLIC_MAINNET_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-lcd-front/
|
NEXT_PUBLIC_MAINNET_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-lcd-front/
|
||||||
|
|
||||||
# MAINNET #
|
# MAINNET #
|
||||||
|
@ -3,7 +3,7 @@ import { BN } from 'utils/helpers'
|
|||||||
|
|
||||||
export default async function fetchPythPrices(...priceFeedIds: string[]) {
|
export default async function fetchPythPrices(...priceFeedIds: string[]) {
|
||||||
try {
|
try {
|
||||||
const pricesUrl = new URL(`${ENV.PYTH_API}/latest_price_feeds`)
|
const pricesUrl = new URL(`${ENV.PYTH_ENDPOINT}/latest_price_feeds`)
|
||||||
priceFeedIds.forEach((id) => pricesUrl.searchParams.append('ids[]', id))
|
priceFeedIds.forEach((id) => pricesUrl.searchParams.append('ids[]', id))
|
||||||
|
|
||||||
const pythResponse: PythPriceData[] = await fetch(pricesUrl).then((res) => res.json())
|
const pythResponse: PythPriceData[] = await fetch(pricesUrl).then((res) => res.json())
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
|
||||||
import AccountMenu from 'components/Account/AccountMenu'
|
import AccountMenu from 'components/Account/AccountMenu'
|
||||||
|
import EscButton from 'components/Button/EscButton'
|
||||||
import DesktopNavigation from 'components/Navigation/DesktopNavigation'
|
import DesktopNavigation from 'components/Navigation/DesktopNavigation'
|
||||||
import Settings from 'components/Settings'
|
import Settings from 'components/Settings'
|
||||||
import Wallet from 'components/Wallet'
|
import Wallet from 'components/Wallet'
|
||||||
@ -16,6 +17,12 @@ export const menuTree: { page: Page; label: string }[] = [
|
|||||||
|
|
||||||
export default function DesktopHeader() {
|
export default function DesktopHeader() {
|
||||||
const address = useStore((s) => s.address)
|
const address = useStore((s) => s.address)
|
||||||
|
const isFocusMode = useStore((s) => s.isFocusMode)
|
||||||
|
|
||||||
|
function handleCloseFocusMode() {
|
||||||
|
useStore.setState({ isFocusMode: false, showTermsOfService: false })
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@ -24,13 +31,22 @@ export default function DesktopHeader() {
|
|||||||
'lg:block',
|
'lg:block',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className='flex items-center justify-between border-b border-white/20 py-3 pl-6 pr-4'>
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'flex items-center justify-between py-3 pl-6 pr-4',
|
||||||
|
!isFocusMode && ' border-b border-white/20',
|
||||||
|
)}
|
||||||
|
>
|
||||||
<DesktopNavigation />
|
<DesktopNavigation />
|
||||||
<div className='flex gap-4'>
|
{isFocusMode ? (
|
||||||
{address && <AccountMenu />}
|
<EscButton onClick={handleCloseFocusMode} />
|
||||||
<Wallet />
|
) : (
|
||||||
<Settings />
|
<div className='flex gap-4'>
|
||||||
</div>
|
{address && <AccountMenu />}
|
||||||
|
<Wallet />
|
||||||
|
<Settings />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
|
@ -218,7 +218,7 @@ export default function SettingsModal() {
|
|||||||
<SettingsSwitch
|
<SettingsSwitch
|
||||||
onChange={handleReduceMotion}
|
onChange={handleReduceMotion}
|
||||||
name='reduceMotion'
|
name='reduceMotion'
|
||||||
value={!reduceMotion}
|
value={reduceMotion}
|
||||||
label='Reduce Motion'
|
label='Reduce Motion'
|
||||||
decsription='Turns off all animations inside the dApp. Turning animations off can increase the
|
decsription='Turns off all animations inside the dApp. Turning animations off can increase the
|
||||||
overall performance on lower-end hardware.'
|
overall performance on lower-end hardware.'
|
||||||
|
@ -3,10 +3,12 @@ import { useParams } from 'react-router-dom'
|
|||||||
import { menuTree } from 'components/Header/DesktopHeader'
|
import { menuTree } from 'components/Header/DesktopHeader'
|
||||||
import { Logo } from 'components/Icons'
|
import { Logo } from 'components/Icons'
|
||||||
import { NavLink } from 'components/Navigation/NavLink'
|
import { NavLink } from 'components/Navigation/NavLink'
|
||||||
|
import useStore from 'store'
|
||||||
import { getRoute } from 'utils/route'
|
import { getRoute } from 'utils/route'
|
||||||
|
|
||||||
export default function DesktopNavigation() {
|
export default function DesktopNavigation() {
|
||||||
const { address, accountId } = useParams()
|
const { address, accountId } = useParams()
|
||||||
|
const isFocusMode = useStore((s) => s.isFocusMode)
|
||||||
|
|
||||||
function getIsActive(href: string) {
|
function getIsActive(href: string) {
|
||||||
return location.pathname.includes(href)
|
return location.pathname.includes(href)
|
||||||
@ -14,22 +16,24 @@ export default function DesktopNavigation() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-1 items-center'>
|
<div className='flex flex-1 items-center'>
|
||||||
<NavLink href={getRoute('trade', address, accountId)} isActive={false}>
|
<NavLink href={getRoute('trade', address, accountId)}>
|
||||||
<span className='block h-10 w-10'>
|
<span className='block h-10 w-10'>
|
||||||
<Logo />
|
<Logo className='text-white' />
|
||||||
</span>
|
</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<div className='flex gap-8 px-6'>
|
{!isFocusMode && (
|
||||||
{menuTree.map((item, index) => (
|
<div className='flex gap-8 px-6'>
|
||||||
<NavLink
|
{menuTree.map((item, index) => (
|
||||||
key={index}
|
<NavLink
|
||||||
href={getRoute(item.page, address, accountId)}
|
key={index}
|
||||||
isActive={getIsActive(item.page)}
|
href={getRoute(item.page, address, accountId)}
|
||||||
>
|
isActive={getIsActive(item.page)}
|
||||||
{item.label}
|
>
|
||||||
</NavLink>
|
{item.label}
|
||||||
))}
|
</NavLink>
|
||||||
</div>
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
86
src/components/TermsOfService.tsx
Normal file
86
src/components/TermsOfService.tsx
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import { useWalletManager } from '@marsprotocol/wallet-connector'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import { useCallback } from 'react'
|
||||||
|
|
||||||
|
import Text from 'components/Text'
|
||||||
|
import { TERMS_OF_SERVICE_KEY } from 'constants/localStore'
|
||||||
|
import useLocalStorage from 'hooks/useLocalStorage'
|
||||||
|
import useStore from 'store'
|
||||||
|
import Button from 'components/Button'
|
||||||
|
import { Check, ExternalLink } from 'components/Icons'
|
||||||
|
|
||||||
|
interface BenefitsProps {
|
||||||
|
benefits: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
function Benefits({ benefits }: BenefitsProps) {
|
||||||
|
return (
|
||||||
|
<ul className='w-full list-none px-0 py-3'>
|
||||||
|
{benefits.map((benefit, index) => (
|
||||||
|
<li className='relative my-6 flex h-6 w-full items-center px-0 pl-8' key={index}>
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'absolute left-0 top-0 isolate h-6 w-6 rounded-full bg-white/10',
|
||||||
|
'before:content-[" "] before:absolute before:inset-0 before:-z-1 before:rounded-full before:p-[1px] before:border-glas',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Check className='p-1.5' />
|
||||||
|
</div>
|
||||||
|
<Text size='sm' className=' text-white/60'>
|
||||||
|
{benefit}
|
||||||
|
</Text>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function TermsOfService() {
|
||||||
|
const { connect } = useWalletManager()
|
||||||
|
const [hasAgreedToTerms, setHasAgreedToTerms] = useLocalStorage(TERMS_OF_SERVICE_KEY, false)
|
||||||
|
|
||||||
|
const handleAgreeTermsOfService = useCallback(() => {
|
||||||
|
useStore.setState({ showTermsOfService: false, isFocusMode: false })
|
||||||
|
setHasAgreedToTerms(true)
|
||||||
|
connect()
|
||||||
|
}, [connect, hasAgreedToTerms, setHasAgreedToTerms])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='relative flex h-full w-full items-center justify-center'>
|
||||||
|
<div className='w-100'>
|
||||||
|
<Text size='4xl' className='w-full pb-2'>
|
||||||
|
Master the Red Planet
|
||||||
|
</Text>
|
||||||
|
<Text size='sm' className='w-full text-white/60'>
|
||||||
|
Mars offers the easiest way to margin trade, lend & borrow and yield farm with leverage
|
||||||
|
any whitelisted token
|
||||||
|
</Text>
|
||||||
|
<Benefits
|
||||||
|
benefits={[
|
||||||
|
'Swap tokens with margin acress any whitelisted pair',
|
||||||
|
'Amplify your LP rewards with leveraged yield farming',
|
||||||
|
'Earn interest on deposited tokens',
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
className='w-full'
|
||||||
|
text='Agree & continue'
|
||||||
|
color='tertiary'
|
||||||
|
onClick={handleAgreeTermsOfService}
|
||||||
|
size='lg'
|
||||||
|
/>
|
||||||
|
<Text size='sm' className='w-full pt-5 text-center text-white/60'>
|
||||||
|
By continuing you accept our{' '}
|
||||||
|
<a
|
||||||
|
href='https://docs.marsprotocol.io/docs/overview/legal/terms-of-service'
|
||||||
|
target='_blank'
|
||||||
|
className='leading-4 text-white hover:underline'
|
||||||
|
>
|
||||||
|
terms of service
|
||||||
|
<ExternalLink className='-mt-1 ml-1 inline w-3.5' />
|
||||||
|
</a>
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -5,7 +5,7 @@ interface Props {
|
|||||||
children: ReactNode | string
|
children: ReactNode | string
|
||||||
className?: string
|
className?: string
|
||||||
monospace?: boolean
|
monospace?: boolean
|
||||||
size?: '3xs' | '2xs' | 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl' | '6xl'
|
size?: '3xs' | '2xs' | 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl'
|
||||||
tag?: 'p' | 'span' | 'h1' | 'h2' | 'h3' | 'h4'
|
tag?: 'p' | 'span' | 'h1' | 'h2' | 'h3' | 'h4'
|
||||||
uppercase?: boolean
|
uppercase?: boolean
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import { useWalletManager, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
import { useWalletManager, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||||
import { ReactNode } from 'react'
|
import { ReactNode, useCallback } from 'react'
|
||||||
|
|
||||||
import Button from 'components/Button'
|
import Button from 'components/Button'
|
||||||
import { CircularProgress } from 'components/CircularProgress'
|
import { CircularProgress } from 'components/CircularProgress'
|
||||||
import { Wallet } from 'components/Icons'
|
import { Wallet } from 'components/Icons'
|
||||||
|
import { TERMS_OF_SERVICE_KEY } from 'constants/localStore'
|
||||||
|
import useLocalStorage from 'hooks/useLocalStorage'
|
||||||
|
import useStore from 'store'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
textOverride?: string | ReactNode
|
textOverride?: string | ReactNode
|
||||||
@ -13,6 +16,15 @@ interface Props {
|
|||||||
|
|
||||||
export default function ConnectButton(props: Props) {
|
export default function ConnectButton(props: Props) {
|
||||||
const { connect } = useWalletManager()
|
const { connect } = useWalletManager()
|
||||||
|
const [hasAgreedToTerms] = useLocalStorage(TERMS_OF_SERVICE_KEY, false)
|
||||||
|
|
||||||
|
const handleConnect = useCallback(() => {
|
||||||
|
if (!hasAgreedToTerms) {
|
||||||
|
useStore.setState({ showTermsOfService: true, isFocusMode: true })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
connect()
|
||||||
|
}, [connect, hasAgreedToTerms])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative'>
|
<div className='relative'>
|
||||||
@ -20,7 +32,7 @@ export default function ConnectButton(props: Props) {
|
|||||||
variant='solid'
|
variant='solid'
|
||||||
color='tertiary'
|
color='tertiary'
|
||||||
disabled={props.disabled}
|
disabled={props.disabled}
|
||||||
onClick={connect}
|
onClick={handleConnect}
|
||||||
leftIcon={<Wallet />}
|
leftIcon={<Wallet />}
|
||||||
>
|
>
|
||||||
{props.status === WalletConnectionStatus.Connecting ? (
|
{props.status === WalletConnectionStatus.Connecting ? (
|
||||||
|
@ -16,7 +16,7 @@ interface EnvironmentVariables {
|
|||||||
URL_API: string
|
URL_API: string
|
||||||
URL_APOLLO_APR: string
|
URL_APOLLO_APR: string
|
||||||
WALLETS: string[]
|
WALLETS: string[]
|
||||||
PYTH_API: string
|
PYTH_ENDPOINT: string
|
||||||
MAINNET_REST_API: string
|
MAINNET_REST_API: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ export const ENV: EnvironmentVariables = {
|
|||||||
: process.env.NEXT_PUBLIC_API || '',
|
: process.env.NEXT_PUBLIC_API || '',
|
||||||
URL_APOLLO_APR: process.env.NEXT_PUBLIC_APOLLO_APR || '',
|
URL_APOLLO_APR: process.env.NEXT_PUBLIC_APOLLO_APR || '',
|
||||||
WALLETS: process.env.NEXT_PUBLIC_WALLETS?.split(',') || [],
|
WALLETS: process.env.NEXT_PUBLIC_WALLETS?.split(',') || [],
|
||||||
PYTH_API: process.env.NEXT_PUBLIC_PYTH_API || '',
|
PYTH_ENDPOINT: process.env.NEXT_PUBLIC_PYTH_ENDPOINT || '',
|
||||||
MAINNET_REST_API: process.env.NEXT_PUBLIC_MAINNET_REST || '',
|
MAINNET_REST_API: process.env.NEXT_PUBLIC_MAINNET_REST || '',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,3 +5,4 @@ export const FAVORITE_ASSETS_KEY = 'favoriteAssets'
|
|||||||
export const LEND_ASSETS_KEY = 'lendAssets'
|
export const LEND_ASSETS_KEY = 'lendAssets'
|
||||||
export const AUTO_LEND_ENABLED_ACCOUNT_IDS_KEY = 'autoLendEnabledAccountIds'
|
export const AUTO_LEND_ENABLED_ACCOUNT_IDS_KEY = 'autoLendEnabledAccountIds'
|
||||||
export const SLIPPAGE_KEY = 'slippage'
|
export const SLIPPAGE_KEY = 'slippage'
|
||||||
|
export const TERMS_OF_SERVICE_KEY = 'termsOfService'
|
||||||
|
@ -7,10 +7,13 @@ import Footer from 'components/Footer'
|
|||||||
import DesktopHeader from 'components/Header/DesktopHeader'
|
import DesktopHeader from 'components/Header/DesktopHeader'
|
||||||
import ModalsContainer from 'components/Modals/ModalsContainer'
|
import ModalsContainer from 'components/Modals/ModalsContainer'
|
||||||
import PageMetadata from 'components/PageMetadata'
|
import PageMetadata from 'components/PageMetadata'
|
||||||
|
import TermsOfService from 'components/TermsOfService'
|
||||||
import Toaster from 'components/Toaster'
|
import Toaster from 'components/Toaster'
|
||||||
|
import useStore from 'store'
|
||||||
|
|
||||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
const showTermsOfService = useStore((s) => s.showTermsOfService)
|
||||||
const isFullWidth = location.pathname.includes('trade') || location.pathname === '/'
|
const isFullWidth = location.pathname.includes('trade') || location.pathname === '/'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -25,7 +28,9 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
|||||||
'align-items-center grid h-full min-h-[900px] grid-cols-[auto_min-content] place-items-start gap-6 p-6',
|
'align-items-center grid h-full min-h-[900px] grid-cols-[auto_min-content] place-items-start gap-6 p-6',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{isFullWidth ? children : <div className='mx-auto w-full max-w-content'>{children}</div>}
|
<div className={classNames('mx-auto h-full w-full', !isFullWidth && 'max-w-content')}>
|
||||||
|
{showTermsOfService ? <TermsOfService /> : children}
|
||||||
|
</div>
|
||||||
<AccountDetails />
|
<AccountDetails />
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
@ -9,5 +9,7 @@ export default function createCommonSlice(set: SetState<CommonSlice>, get: GetSt
|
|||||||
isOpen: true,
|
isOpen: true,
|
||||||
selectedAccount: null,
|
selectedAccount: null,
|
||||||
status: WalletConnectionStatus.Unconnected,
|
status: WalletConnectionStatus.Unconnected,
|
||||||
|
isFocusMode: false,
|
||||||
|
showTermsOfService: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
src/types/interfaces/store/common.d.ts
vendored
2
src/types/interfaces/store/common.d.ts
vendored
@ -6,4 +6,6 @@ interface CommonSlice {
|
|||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
selectedAccount: string | null
|
selectedAccount: string | null
|
||||||
status: import('@marsprotocol/wallet-connector').WalletConnectionStatus
|
status: import('@marsprotocol/wallet-connector').WalletConnectionStatus
|
||||||
|
isFocusMode: boolean
|
||||||
|
showTermsOfService: boolean
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user