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..6931f9522
--- /dev/null
+++ b/apps/next/pages/account/rewards/lock-and-earn.tsx
@@ -0,0 +1,26 @@
+import { LockAndEarnScreen } from 'app/features/account/rewards/lock/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'
+
+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/icons/IconCoin.tsx b/packages/app/components/icons/IconCoin.tsx
index a253f1931..4cafa2833 100644
--- a/packages/app/components/icons/IconCoin.tsx
+++ b/packages/app/components/icons/IconCoin.tsx
@@ -2,13 +2,14 @@ import type { coin } from 'app/data/coins'
import { IconEthereum } from './IconEthereum'
import { IconSend } from './IconSend'
import { IconUSDC } from './IconUSDC'
+import type { SizeTokens } from 'tamagui'
-const coinSymbolToIcons: Record = {
- USDC: ,
- ETH: ,
- SEND: ,
+const coinSymbolToIcons: Record JSX.Element> = {
+ USDC: (size) => ,
+ ETH: (size) => ,
+ SEND: (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/screen.tsx b/packages/app/features/account/rewards/lock/screen.tsx
new file mode 100644
index 000000000..d38534577
--- /dev/null
+++ b/packages/app/features/account/rewards/lock/screen.tsx
@@ -0,0 +1,439 @@
+import {
+ YStack,
+ Card,
+ Paragraph,
+ H2,
+ XStack,
+ Spinner,
+ Tooltip,
+ type TooltipProps,
+ LinkableButton,
+ Button,
+ isWeb,
+ Stack,
+ AnimatePresence,
+ useMedia,
+ ScrollView,
+ LinearGradient,
+ usePwa,
+} 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'
+
+const ScrollLayout = ({ children }) => {
+ const isPwa = usePwa()
+ const media = useMedia()
+
+ return (
+
+ {media.gtMd ? (
+ children
+ ) : (
+ <>
+ {/* @NOTE: This only works if passed a fixed height */}
+
+ {children}
+
+
+
+
+
+
+
+ >
+ )}
+
+ )
+}
+
+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(4)
+
+ 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)
+
+ 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
+
+
+
+ )
+}