diff --git a/packages/frontend/pages/lp.tsx b/packages/frontend/pages/lp.tsx index a54ef9ac8..824e21576 100644 --- a/packages/frontend/pages/lp.tsx +++ b/packages/frontend/pages/lp.tsx @@ -1,109 +1,209 @@ import { createStyles, makeStyles } from '@material-ui/core' -import Typography from '@material-ui/core/Typography' -import Image from 'next/image' +import { Box, Typography } from '@material-ui/core' import React, { useState } from 'react' -import squeethTokenSymbol from '../public/images/Squeeth.svg' import ObtainSqueeth from '@components/Lp/ObtainSqueeth' import SqueethInfo from '@components/Lp/SqueethInfo' +import LPPosition from '@components/Lp/LPPosition' import LPBuyChart from '@components/Charts/LPBuyChart' import LPMintChart from '@components/Charts/LPMintChart' import Nav from '@components/Nav' import { LPProvider } from '@context/lp' -import { useRestrictUser } from '@context/restrict-user' import { SqueethTabNew, SqueethTabsNew } from '@components/Tabs' import { useETHPrice } from '@hooks/useETHPrice' -import { supportedNetworkAtom } from 'src/state/wallet/atoms' -import { useAtomValue } from 'jotai' const useStyles = makeStyles((theme) => createStyles({ container: { - padding: theme.spacing(4, 10), - marginLeft: 'auto', - marginRight: 'auto', - maxWidth: '1500px', + maxWidth: '1280px', + width: '80%', display: 'flex', - justifyContent: 'space-between', - }, - logoContainer: { - display: 'flex', - alignItems: 'center', - width: '100%', - }, - logoTitle: { - marginLeft: theme.spacing(1), + justifyContent: 'center', + gridGap: '96px', + flexWrap: 'wrap', + padding: theme.spacing(6, 5), + margin: '0 auto', + [theme.breakpoints.down('lg')]: { + maxWidth: 'none', + width: '90%', + }, + [theme.breakpoints.down('md')]: { + width: '100%', + gridGap: '40px', + }, [theme.breakpoints.down('sm')]: { - fontSize: 18, + padding: theme.spacing(3, 4), + }, + [theme.breakpoints.down('xs')]: { + padding: theme.spacing(3, 3), }, }, - logoSubTitle: { - marginLeft: theme.spacing(1), - [theme.breakpoints.down('sm')]: { - fontSize: 16, + leftColumn: { + flex: 1, + minWidth: '480px', + [theme.breakpoints.down('xs')]: { + minWidth: '320px', + }, + }, + rightColumn: { + flexBasis: '452px', + [theme.breakpoints.down('xs')]: { + flex: '1', }, }, - logo: { - marginTop: theme.spacing(0.5), - alignSelf: 'flex-start', + title: { + fontSize: '28px', + fontWeight: 700, + letterSpacing: '-0.02em', }, - comparison: { - marginTop: theme.spacing(4), - //paddingBottom: theme.spacing(2), + description: { + fontSize: '18px', + fontWeight: 400, + color: theme.palette.grey[400], }, - comparisonItem: { - width: '400px', + subtitle: { + fontSize: '22px', + fontWeight: 700, + letterSpacing: '-0.01em', }, - comparisonPoint: { - marginTop: theme.spacing(2), - padding: theme.spacing(0, 2), + sectionTitle: { + marginTop: theme.spacing(3), + color: 'rgb(255, 255, 255)', + fontWeight: 500, + fontSize: '18px', + letterSpacing: '-0.01em', }, + details: { marginTop: theme.spacing(4), - // paddingLeft: theme.spacing(4), - // display: 'flex', }, - heading: { - marginTop: theme.spacing(3), - }, - tradeForm: { + tradeSection: { position: 'sticky', top: '100px', + border: '1px solid #242728', + boxShadow: '0px 4px 40px rgba(0, 0, 0, 0.25)', + borderRadius: theme.spacing(0.7), + padding: '32px 24px', }, chartNav: { border: `1px solid ${theme.palette.primary.main}30`, }, + content: { + color: '#bdbdbd', + marginTop: '4px', + }, }), ) -export function LPCalculator() { +const LPInfo: React.FC<{ lpType: number }> = ({ lpType }) => { const classes = useStyles() - const { isRestricted } = useRestrictUser() const ethPrice = useETHPrice() + + if (lpType === 0) { + return ( + <> + + Buy squeeth and LP + + + Earn a payoff similar to ETH1.5 + + + Strategy Overview + + + Buying and LPing gives you a leverage position with a payoff similar to ETH1.5. You give up some of + your squeeth upside in exchange for trading fees. You are paying daily premiums for being long squeeth, but + earning fees from LPing on Uniswap. + + + Payoff + + + + This payoff diagram does not include premiums or trading fees and assumes implied volatility stays constant.{' '} + + + Risks + + + You are exposed to squeeth premiums, so if you hold the position for a long period of time without upward + price movements in ETH, you can lose considerable funds to premium payments. + +
+ + {' '} + Squeeth smart contracts have been audited by Trail of Bits, Akira, and Sherlock. However, smart contracts are + experimental technology and we encourage caution only risking funds you can afford to lose. + + + ) + } + + return ( + <> + + Mint squeeth and LP + + + Earn yield from trading fees while being long ETH + + + Strategy Overview + + + Minting and LPing is similar to a covered call. You start off with a position similar to 1x long ETH that gets + less long ETH as the price moves up and longer ETH as the price moves down. + + + Payoff + + + + This payoff diagram does not included premiums or trading fees and assumes implied volatility stays constant.{' '} + + + Risks + + + You enter this position neutral to squeeth exposure, but could end up long squeeth exposed to premiums or short + squeeth depending on ETH price movements. If you fall below the minimum collateralization threshold (150%), you + are at risk of liquidation. + +
+ + Squeeth smart contracts have been audited by Trail of Bits, Akira, and Sherlock. However, smart contracts are + experimental technology and we encourage caution only risking funds you can afford to lose. + + + ) +} + +export function LPCalculator() { + const classes = useStyles() const [lpType, setLpType] = useState(0) - const supportedNetwork = useAtomValue(supportedNetworkAtom) return ( -
+ <>
) : ( - - + <> + Buy back oSQTH & close position - + = ({ open }) => { <> - Collateralization ratio + Collateral ratio - + = ({ open }) => { )} - + )} ) diff --git a/packages/frontend/src/components/Trade/SqueethMetrics.tsx b/packages/frontend/src/components/Trade/SqueethMetrics.tsx index 7417c8e2f..ffc641f0f 100644 --- a/packages/frontend/src/components/Trade/SqueethMetrics.tsx +++ b/packages/frontend/src/components/Trade/SqueethMetrics.tsx @@ -1,8 +1,6 @@ import React from 'react' -import { Box, BoxProps, Typography, Tooltip } from '@material-ui/core' -import { makeStyles, createStyles } from '@material-ui/core/styles' +import { Box, BoxProps } from '@material-ui/core' import { useAtomValue } from 'jotai' -import InfoIcon from '@material-ui/icons/InfoOutlined' import { normFactorAtom, @@ -14,42 +12,10 @@ import { } from '@state/controller/atoms' import { toTokenAmount } from '@utils/calculations' import { formatCurrency, formatNumber } from '@utils/formatter' -import Metric from '@components/Metric' +import Metric, { MetricLabel } from '@components/Metric' import { Tooltips } from '@constants/enums' import { useOnChainETHPrice } from '@hooks/useETHPrice' -const useStyles = makeStyles((theme) => - createStyles({ - labelContainer: { - display: 'flex', - alignItems: 'center', - color: 'rgba(255, 255, 255, 0.5)', - }, - label: { - fontSize: '15px', - fontWeight: 500, - width: 'max-content', - }, - infoIcon: { - fontSize: '15px', - marginLeft: theme.spacing(0.5), - }, - }), -) - -const Label: React.FC<{ label: string; tooltipTitle: string }> = ({ label, tooltipTitle }) => { - const classes = useStyles() - - return ( -
- {label} - - - -
- ) -} - const SqueethMetrics: React.FC = (props) => { const mark = useAtomValue(markAtom) const impliedVol = useAtomValue(impliedVolAtom) @@ -70,43 +36,43 @@ const SqueethMetrics: React.FC = (props) => { return ( } + label={} value={formatCurrency(ethPrice.toNumber())} /> } + label={} value={formatCurrency(eth2Price.toNumber())} /> } + label={} value={formatCurrency(markPrice.toNumber())} /> } + label={} value={`${formatNumber(impliedVolPercent)}%`} /> } + label={} value={`${formatNumber(osqthRefVol)}%`} /> } + label={} value={formatNumber(normFactor.toNumber(), 4)} /> } + label={} value={currentImpliedPremium} /> diff --git a/packages/frontend/src/components/Trade/index.tsx b/packages/frontend/src/components/Trade/index.tsx index 5e2a5b807..25e33546e 100644 --- a/packages/frontend/src/components/Trade/index.tsx +++ b/packages/frontend/src/components/Trade/index.tsx @@ -40,9 +40,9 @@ const Trade: React.FC = (props) => { -
+ {tradeType === TradeType.LONG ? : } -
+
) } diff --git a/packages/frontend/src/constants/index.ts b/packages/frontend/src/constants/index.ts index 65ef72d70..c1b18f830 100644 --- a/packages/frontend/src/constants/index.ts +++ b/packages/frontend/src/constants/index.ts @@ -17,6 +17,8 @@ export const MIN_COLLATERAL_AMOUNT = 6.9 export const MIN_COLLATERAL_RATIO = 150 +export const DEFAULT_COLLATERAL_RATIO = 225 + export const YEAR = 365 export const VOL_PERCENT_FIXED = 0.1 diff --git a/packages/frontend/styles/globals.css b/packages/frontend/styles/globals.css index 7ec190882..f8cf7a9a5 100644 --- a/packages/frontend/styles/globals.css +++ b/packages/frontend/styles/globals.css @@ -20,6 +20,11 @@ html { background: 'none'; } +sup { + vertical-align: top; + font-size: 0.6em; +} + input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { -webkit-appearance: none; @@ -54,47 +59,46 @@ a { @-webkit-keyframes AnimationName { 0% { - background-position: 0% 46% + background-position: 0% 46%; } 50% { - background-position: 100% 55% + background-position: 100% 55%; } 100% { - background-position: 0% 46% + background-position: 0% 46%; } } @-moz-keyframes AnimationName { 0% { - background-position: 0% 46% + background-position: 0% 46%; } 50% { - background-position: 100% 55% + background-position: 100% 55%; } 100% { - background-position: 0% 46% + background-position: 0% 46%; } } @keyframes AnimationName { 0% { - background-position: 0% 46% + background-position: 0% 46%; } 50% { - background-position: 100% 55% + background-position: 100% 55%; } 100% { - background-position: 0% 46% + background-position: 0% 46%; } } - #rain-front { position: absolute; left: 0; @@ -156,4 +160,4 @@ a { 100% { opacity: 0; } -} \ No newline at end of file +}