diff --git a/apps/next/pages/account/rewards/lock-and-earn.tsx b/apps/next/pages/account/rewards/lock-and-earn.tsx new file mode 100644 index 000000000..71474a30d --- /dev/null +++ b/apps/next/pages/account/rewards/lock-and-earn.tsx @@ -0,0 +1,29 @@ +import { LockAndEarnScreen } from 'app/features/account/rewards/lock-and-earn/screen' +import Head from 'next/head' +import { userProtectedGetSSP } from 'utils/userProtected' +import type { NextPageWithLayout } from 'next-app/pages/_app' +import { HomeLayout } from 'app/features/home/layout.web' +import { ButtonOption, TopNav } from 'app/components/TopNav' +import { MobileButtonRowLayout } from 'app/components/MobileButtonRowLayout' + +export const Page: NextPageWithLayout = () => { + return ( + <> + + Send | Lock and Earn + + + + ) +} + +export const getServerSideProps = userProtectedGetSSP() +Page.getLayout = (children) => ( + + }> + {children} + + +) + +export default Page diff --git a/packages/app/components/MobileButtonRowLayout.tsx b/packages/app/components/MobileButtonRowLayout.tsx index 6b3940642..20054c5e8 100644 --- a/packages/app/components/MobileButtonRowLayout.tsx +++ b/packages/app/components/MobileButtonRowLayout.tsx @@ -23,6 +23,7 @@ import { useProfileScreenParams, useRewardsScreenParams } from 'app/routers/para import { useMonthlyDistributions } from 'app/utils/distributions' import { DistributionClaimButton } from 'app/features/account/rewards/components/DistributionClaimButton' import formatAmount from 'app/utils/formatAmount' +import { LockAndEarnButtons } from 'app/features/account/rewards/lock-and-earn/LockAndEarnButtons' const Row = styled(XStack, { w: '100%', @@ -243,8 +244,60 @@ export const ActivityRewards = ({ children, ...props }: XStackProps) => { ) } +export const LockAndEarn = ({ children, ...props }: XStackProps) => { + const isPwa = usePwa() + const { isLoading } = useUser() + + const { direction } = useScrollDirection() + + return ( + <> + {children} + + {!isLoading && direction !== 'down' && ( + + + + + + + + + )} + + + ) +} + export const MobileButtonRowLayout = { Home: Home, Profile: Profile, ActivityRewards: ActivityRewards, + LockAndEarn: LockAndEarn, } diff --git a/packages/app/components/icons/IconCoin.tsx b/packages/app/components/icons/IconCoin.tsx index 0f11c4572..1eff46e58 100644 --- a/packages/app/components/icons/IconCoin.tsx +++ b/packages/app/components/icons/IconCoin.tsx @@ -3,14 +3,15 @@ import { IconEthereum } from './IconEthereum' import { IconSend } from './IconSend' import { IconUSDC } from './IconUSDC' import { IconSPX6900 } from './IconSPX6900' +import type { SizeTokens } from 'tamagui' -const coinSymbolToIcons: Record = { - USDC: , - ETH: , - SEND: , - SPX: , +const coinSymbolToIcons: Record JSX.Element> = { + USDC: (size) => , + ETH: (size) => , + SEND: (size) => , + SPX: (size) => , } -export const IconCoin = ({ coin }: { coin: coin }) => { - return coinSymbolToIcons[coin.symbol] +export const IconCoin = ({ coin, size }: { coin: coin; size?: SizeTokens }) => { + return coinSymbolToIcons[coin.symbol]?.(size || '$2.5') } diff --git a/packages/app/components/icons/IconExclamationCircle.tsx b/packages/app/components/icons/IconExclamationCircle.tsx new file mode 100644 index 000000000..93249a6d2 --- /dev/null +++ b/packages/app/components/icons/IconExclamationCircle.tsx @@ -0,0 +1,25 @@ +import type { ColorTokens } from '@my/ui/types' +import { type IconProps, themed } from '@tamagui/helpers-icon' +import { memo } from 'react' +import { Path, Svg } from 'react-native-svg' + +const ExclamationCircle = (props) => { + const { size, color, ...rest } = props + return ( + + + + ) +} +const IconExclamationCircle = memo(themed(ExclamationCircle)) +export { IconExclamationCircle } diff --git a/packages/app/components/icons/IconPlusCircle.tsx b/packages/app/components/icons/IconPlusCircle.tsx new file mode 100644 index 000000000..1ef485b66 --- /dev/null +++ b/packages/app/components/icons/IconPlusCircle.tsx @@ -0,0 +1,25 @@ +import type { ColorTokens } from '@my/ui/types' +import { type IconProps, themed } from '@tamagui/helpers-icon' +import { memo } from 'react' +import { Path, Svg } from 'react-native-svg' + +const PlusCircle = (props) => { + const { size, color, ...rest } = props + return ( + + + + ) +} +const IconPlusCircle = memo(themed(PlusCircle)) +export { IconPlusCircle } diff --git a/packages/app/components/icons/index.tsx b/packages/app/components/icons/index.tsx index 2eefa125b..7b111abdc 100644 --- a/packages/app/components/icons/index.tsx +++ b/packages/app/components/icons/index.tsx @@ -57,3 +57,5 @@ export { IconInfoCircle } from './IconInfoCircle' export { IconLeaderboard } from './IconLeaderboard' export { IconStarOutline } from './IconStarOutline' export { IconQuestionCircle } from './IconQuestionCircle' +export { IconPlusCircle } from './IconPlusCircle' +export { IconExclamationCircle } from './IconExclamationCircle' diff --git a/packages/app/features/account/rewards/lock-and-earn/LockAndEarnButtons.tsx b/packages/app/features/account/rewards/lock-and-earn/LockAndEarnButtons.tsx new file mode 100644 index 000000000..c7012a293 --- /dev/null +++ b/packages/app/features/account/rewards/lock-and-earn/LockAndEarnButtons.tsx @@ -0,0 +1,13 @@ +import { Button } from '@my/ui' + +export const OpenButton = () => ( + +) + +export const LockAndEarnButtons = { + OpenButton: OpenButton, +} diff --git a/packages/app/features/account/rewards/lock-and-earn/screen.tsx b/packages/app/features/account/rewards/lock-and-earn/screen.tsx new file mode 100644 index 000000000..607460461 --- /dev/null +++ b/packages/app/features/account/rewards/lock-and-earn/screen.tsx @@ -0,0 +1,400 @@ +import { + YStack, + Card, + Paragraph, + H2, + XStack, + Spinner, + Tooltip, + type TooltipProps, + LinkableButton, + Button, + isWeb, + Stack, + AnimatePresence, + useMedia, +} from '@my/ui' +import { + IconDollar, + IconError, + IconExclamationCircle, + IconPlus, + IconTriangleDown, +} from 'app/components/icons' +import { coins, type coin } from 'app/data/coins' +import { useSendAccount } from 'app/utils/send-accounts' +import { useBalance, type UseBalanceReturnType } from 'wagmi' +import { baseMainnet } from '@my/wagmi' +import formatAmount from 'app/utils/formatAmount' +import { IconCoin } from 'app/components/icons/IconCoin' +import { useState } from 'react' +import { useThemeSetting } from 'app/provider/theme' + +export function LockAndEarnScreen() { + return ( + + + + + + + + + ) +} + +const BalancesSection = () => { + return ( + +

+ Your Balances +

+ + {coins.map((coin) => { + return + })} + +
+ ) +} + +const TokenBalanceCard = ({ + coin, +}: { + coin: coin +}) => { + const { data: sendAccount } = useSendAccount() + const { gtMd } = useMedia() + const balance = useBalance({ + address: sendAccount?.address, + token: coin.token === 'eth' ? undefined : coin.token, + query: { enabled: !!sendAccount }, + chainId: baseMainnet.id, + }) + const iconSize = gtMd ? '$size.3.5' : '$size.1.5' + + return ( + + + + + + {coin.label} + + + + + + ) +} + +const TokenBalance = ({ balance }: { balance: UseBalanceReturnType }) => { + if (balance.isError) { + return ( + + + -- + + }> + Error occurred while fetching balance. {balance?.error?.message} + + + ) + } + + if (balance.isFetching && balance.isPending) { + return + } + if (balance?.data?.value === undefined) { + return <> + } + return ( + + {formatAmount( + (Number(balance.data?.value) / 10 ** (balance.data?.decimals ?? 0)).toString(), + 10, + 5 + )} + + ) +} + +// @TODO: This is duplicated from TokenBalanceList +const ErrorTooltip = ({ Icon, children, ...props }: TooltipProps & { Icon?: JSX.Element }) => { + return ( + + {Icon} + + + {children} + + + + ) +} + +const PositionsSection = () => { + const [positionsCount, setPositionsCount] = useState(0) + + return ( + + +

+ Your Positions [{positionsCount}] +

+ +
+ + + {positionsCount > 0 ? ( + [...Array(positionsCount)].map((n) => { + return + }) + ) : ( + + You don't have any open positions. + + )} + + + +
+ ) +} + +const PositionCard = () => { + const [isOpen, setIsOpen] = useState(false) + const [isClaimed, setIsClaimed] = useState(false) + const { resolvedTheme } = useThemeSetting() + + return ( + + + + + USDC/SEND + + + + + + + + + + {isOpen && ( + <> + + + + )} + + + + + + + {isOpen && ( + <> + + + + )} + + + + + ) +} + +const AddLiquidityButton = () => { + return ( + + ) +} + +const ClosePositionButton = () => { + return ( + + ) +} + +const PositionCardLineText = ({ left, right }: { left: string; right: string }) => { + return ( + + + {left} + + {right} + + ) +} + +const OpenPosition = () => { + return ( + + + + + + + + + + Open a New Position + + + + ) +} diff --git a/packages/app/features/account/rewards/screen.tsx b/packages/app/features/account/rewards/screen.tsx index a574be879..4ff57ae8e 100644 --- a/packages/app/features/account/rewards/screen.tsx +++ b/packages/app/features/account/rewards/screen.tsx @@ -46,7 +46,7 @@ export function RewardsScreen() { - {/* @TODO: href, reward */} + {/* @TODO: reward */}