diff --git a/app/space/[domain]/[slug]/PostTradeDialog/AvatarList.tsx b/app/space/[domain]/[slug]/PostTradeDialog/AvatarList.tsx deleted file mode 100644 index f262e43e..00000000 --- a/app/space/[domain]/[slug]/PostTradeDialog/AvatarList.tsx +++ /dev/null @@ -1,38 +0,0 @@ -'use client' - -import { Badge } from '@/components/ui/badge' -import { UserAvatar } from '@/components/UserAvatar' -import { useHolders } from '@/hooks/useHolders' -import { PostWithSpace } from '@/hooks/usePost' -import { cn } from '@/lib/utils' - -interface Props { - post: PostWithSpace -} - -export function AvatarList({ post }: Props) { - const { holders, isLoading } = useHolders(post.id) - - if (isLoading) return null - - return ( -
-
- {holders.slice(0, 4).map((item) => ( - - ))} -
- - {holders.length} holders - -
- ) -} diff --git a/app/space/[domain]/[slug]/PostTradeDialog/HolderList.tsx b/app/space/[domain]/[slug]/PostTradeDialog/HolderList.tsx deleted file mode 100644 index adcef806..00000000 --- a/app/space/[domain]/[slug]/PostTradeDialog/HolderList.tsx +++ /dev/null @@ -1,54 +0,0 @@ -'use client' - -import { Skeleton } from '@/components/ui/skeleton' -import { UserAvatar } from '@/components/UserAvatar' -import { useHolders } from '@/hooks/useHolders' -import { PostWithSpace } from '@/hooks/usePost' -import { precision } from '@/lib/math' -import { getEnsAvatar, shortenAddress } from '@/lib/utils' -import { Space } from '@prisma/client' - -interface Props { - space: Space - post: PostWithSpace -} - -export function HolderList({ space, post }: Props) { - const { holders, isLoading } = useHolders(post.id) - - if (isLoading) { - return ( -
- {Array(10) - .fill('') - .map((_, index) => ( - - ))} -
- ) - } - - if (holders.length === 0) { - return ( -
- No holders yet -
- ) - } - - return ( -
- {holders.map((item) => ( -
-
- -
{item.user.ensName || shortenAddress(item.user.address)}
-
-
- {item.amount} Keys -
-
- ))} -
- ) -} diff --git a/app/space/[domain]/[slug]/PostTradeDialog/PostTradeDialog.tsx b/app/space/[domain]/[slug]/PostTradeDialog/PostTradeDialog.tsx deleted file mode 100644 index 2ee96e81..00000000 --- a/app/space/[domain]/[slug]/PostTradeDialog/PostTradeDialog.tsx +++ /dev/null @@ -1,48 +0,0 @@ -'use client' - -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, - DialogTrigger, -} from '@/components/ui/dialog' -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' -import { PostWithSpace } from '@/hooks/usePost' -import { Space } from '@prisma/client' -import { AvatarList } from './AvatarList' -import { HolderList } from './HolderList' -import { PostTradeList } from './PostTradeList' - -interface Props { - space: Space - post: PostWithSpace -} -export function PostTradeModal({ space, post }: Props) { - return ( - - - - - - - {/* # */} - - - Key Holders - Trade History - -
- - - - - - -
-
-
-
-
- ) -} diff --git a/app/space/[domain]/[slug]/PostTradeDialog/PostTradeList.tsx b/app/space/[domain]/[slug]/PostTradeDialog/PostTradeList.tsx deleted file mode 100644 index a4d45743..00000000 --- a/app/space/[domain]/[slug]/PostTradeDialog/PostTradeList.tsx +++ /dev/null @@ -1,16 +0,0 @@ -'use client' - -import { Badge } from '@/components/ui/badge' -import { UserAvatar } from '@/components/UserAvatar' -import { PostWithSpace } from '@/hooks/usePost' -import { usePostTrades } from '@/hooks/usePostTrades' -import { precision } from '@/lib/math' -import { cn, shortenAddress } from '@/lib/utils' - -interface Props { - post: PostWithSpace -} - -export function PostTradeList({ post }: Props) { - return
-} diff --git a/app/space/[domain]/[slug]/PostTradeDialog/useTradeDialog.ts b/app/space/[domain]/[slug]/PostTradeDialog/useTradeDialog.ts deleted file mode 100644 index db53a3ae..00000000 --- a/app/space/[domain]/[slug]/PostTradeDialog/useTradeDialog.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { atom, useAtom } from 'jotai' - -const tradeDialogAtom = atom(false) - -export function useTradeDialog() { - const [isOpen, setIsOpen] = useAtom(tradeDialogAtom) - return { isOpen, setIsOpen } -} diff --git a/app/space/[domain]/[slug]/page.tsx b/app/space/[domain]/[slug]/page.tsx index 016aaebe..5c77308c 100644 --- a/app/space/[domain]/[slug]/page.tsx +++ b/app/space/[domain]/[slug]/page.tsx @@ -13,7 +13,6 @@ import { handlers } from './handlers' import { ImageCreation } from './ImageCreation' import { PostActionBar } from './PostActionBar' import { PostCreation } from './PostCreation' -import { PostTradeModal } from './PostTradeDialog/PostTradeDialog' import { PromotionCard } from './PromotionCard' export const dynamic = 'force-dynamic' diff --git a/app/~/space/[id]/(home)/layout.tsx b/app/~/space/[id]/(home)/layout.tsx index 952f84d5..2f81c3e6 100644 --- a/app/~/space/[id]/(home)/layout.tsx +++ b/app/~/space/[id]/(home)/layout.tsx @@ -4,10 +4,10 @@ import { ReactNode } from 'react' import { NavbarWrapper } from '@/components/Navbar/NavbarWrapper' import { useChainSpace, useQueryChainSpace } from '@/hooks/useChainSpace' import { SpaceInfo } from '../Space/SpaceInfo' +import { TradeList } from '../Space/TradeList' import { Transaction } from '../Transaction' export default function Layout({ children }: { children: ReactNode }) { - const { isLoading, data } = useQueryChainSpace() const { space } = useChainSpace() if (!space) return null @@ -21,7 +21,11 @@ export default function Layout({ children }: { children: ReactNode }) { {children} - +
+ +
Trades
+ +
) diff --git a/app/~/space/[id]/(home)/trades/page.tsx b/app/~/space/[id]/(home)/trades/page.tsx index de88d1db..7336679a 100644 --- a/app/~/space/[id]/(home)/trades/page.tsx +++ b/app/~/space/[id]/(home)/trades/page.tsx @@ -1,10 +1,10 @@ 'use client' import { useSpace } from '@/hooks/useSpace' -import { SpaceTradeList } from '../../Space/SpaceTradeList' +import { SubscriptionRecordList } from '../../Space/SubscriptionRecordList' export default function Page() { const { space } = useSpace() if (!space) return - return + return } diff --git a/app/~/space/[id]/Space/SpaceInfo.tsx b/app/~/space/[id]/Space/SpaceInfo.tsx index fcf9f620..76589d21 100644 --- a/app/~/space/[id]/Space/SpaceInfo.tsx +++ b/app/~/space/[id]/Space/SpaceInfo.tsx @@ -3,6 +3,7 @@ import { MemberDialog } from '@/components/MemberDialog/MemberDialog' import { Badge } from '@/components/ui/badge' import { Skeleton } from '@/components/ui/skeleton' +import { UpdatePriceDialog } from '@/components/UpdatePriceDialog/UpdatePriceDialog' import { useSpace } from '@/hooks/useSpace' import { cn } from '@/lib/utils' import { useSession } from 'next-auth/react' @@ -11,7 +12,6 @@ import Link from 'next/link' import { usePathname } from 'next/navigation' import { ClaimShareRewards } from './ClaimShareRewards' import { MemberButton } from './MemberButton' -import { UpdatePriceDialog } from '@/components/UpdatePriceDialog/UpdatePriceDialog' interface Props {} @@ -97,7 +97,7 @@ export function SpaceInfo({}: Props) {
- +
@@ -118,7 +118,7 @@ export function SpaceInfo({}: Props) { */} - Trades + Activities diff --git a/app/~/space/[id]/Space/SpaceTradeList.tsx b/app/~/space/[id]/Space/SubscriptionRecordList.tsx similarity index 66% rename from app/~/space/[id]/Space/SpaceTradeList.tsx rename to app/~/space/[id]/Space/SubscriptionRecordList.tsx index caf557e0..3cfbe544 100644 --- a/app/~/space/[id]/Space/SpaceTradeList.tsx +++ b/app/~/space/[id]/Space/SubscriptionRecordList.tsx @@ -3,7 +3,8 @@ import { Badge } from '@/components/ui/badge' import { UserAvatar } from '@/components/UserAvatar' import { SECONDS_PER_DAY } from '@/domains/Space' -import { useSpaceTrades } from '@/hooks/useSpaceTrades' +import { useSubscriptionRecords } from '@/hooks/useSpaceTrades' +import { SubscriptionType } from '@/lib/constants' import { precision } from '@/lib/math' import { cn, getEnsAvatar, shortenAddress } from '@/lib/utils' import { Space } from '@prisma/client' @@ -12,12 +13,12 @@ interface Props { space: Space } -export function SpaceTradeList({ space }: Props) { - const { trades } = useSpaceTrades(space.id) +export function SubscriptionRecordList({ space }: Props) { + const { records } = useSubscriptionRecords(space.id) return (
- {trades.map((item) => ( + {records.map((item) => (
@@ -30,11 +31,13 @@ export function SpaceTradeList({ space }: Props) {
- {item.type === 'BUY' ? 'Subscribe' : 'Unsubscribe'} + {item.type === SubscriptionType.SUBSCRIBE + ? 'Subscribe' + : 'Unsubscribe'}
diff --git a/app/~/space/[id]/Space/TradeList.tsx b/app/~/space/[id]/Space/TradeList.tsx new file mode 100644 index 00000000..47827c8c --- /dev/null +++ b/app/~/space/[id]/Space/TradeList.tsx @@ -0,0 +1,52 @@ +'use client' + +import { UserAvatar } from '@/components/UserAvatar' +import { useSpace } from '@/hooks/useSpace' +import { useTrades } from '@/hooks/useTrades' +import { TradeType } from '@/lib/constants' +import { precision } from '@/lib/math' +import { cn } from '@/lib/utils' + +interface Props {} + +export function TradeList({}: Props) { + const { space } = useSpace() + const { records: trades } = useTrades() + + return ( +
+ {trades.map((item) => ( +
+
+ +
+ {item.user.ensName + ? item.user.ensName + : item.user.address.slice(0, 5)} +
+
+
+
+ {item.type === TradeType.BUY ? 'Bought' : 'sold'} +
+
+
+ + {precision + .toDecimal( + item.type === TradeType.BUY ? item.amountOut : item.amountIn, + ) + .toFixed(2)}{' '} + + {space.symbolName} +
+
+ ))} +
+ ) +} diff --git a/app/~/space/[id]/Transaction.tsx b/app/~/space/[id]/Transaction.tsx index 728f7ddb..d61e823b 100644 --- a/app/~/space/[id]/Transaction.tsx +++ b/app/~/space/[id]/Transaction.tsx @@ -1,88 +1,65 @@ 'use client' -import { useEffect, useMemo, useState } from 'react'; -import { useAddress } from '@/hooks/useAddress'; -import { useTokenKxy } from '@/hooks/useTokenKxy'; -import { precision } from '@/lib/math'; -import { Address } from 'viem'; -import { useAccount, useBalance } from 'wagmi'; -import { useSpace } from "@/hooks/useSpace" -import { useSpaceTokenBalance } from '@/components/spaceToken/hooks/useSpaceTokenBalance'; -import { Buy } from '@/components/spaceToken/Buy'; -import { Sell } from '@/components/spaceToken/Sell'; +import { useEffect, useMemo, useState } from 'react' +import { BuyPanel } from '@/components/spaceToken/BuyPanel' +import { SellPanel } from '@/components/spaceToken/SellPanel' +import { useAddress } from '@/hooks/useAddress' +import { useSpace } from '@/hooks/useSpace' +import { precision } from '@/lib/math' +import { Address } from 'viem' +import { useAccount, useBalance } from 'wagmi' enum Direction { buy = 1, - sell = 2 + sell = 2, } export function Transaction() { const { space } = useSpace() const address = useAddress() const { isConnected } = useAccount() - const { data: balanceData } = useBalance({ address }) - const { isLoading, data: tokenBalance } = useSpaceTokenBalance() const [direction, setDirection] = useState(Direction.buy) - const { updateTokenKxy } = useTokenKxy() - - const ethBalance = useMemo(() => { - if (balanceData?.value) { - // Numerical precision issues: precision.toDecimal(tokenBalance).toString() - return precision.toExactDecimalString(balanceData?.value) - } - - return '0.00' - }, [balanceData]) const onSwitch = (direction: Direction) => { setDirection(direction) } - useEffect(() => { - if (space) { - updateTokenKxy(space.spaceAddress as Address) - } - }, [space]) - return ( -
+
-
+
-
- +
+
-
- +
+
diff --git a/components/DashboardLayout/DashboardLayout.tsx b/components/DashboardLayout/DashboardLayout.tsx index 0e685be0..db14f4d9 100644 --- a/components/DashboardLayout/DashboardLayout.tsx +++ b/components/DashboardLayout/DashboardLayout.tsx @@ -2,6 +2,7 @@ import { PropsWithChildren } from 'react' import { useAddress } from '@/hooks/useAddress' +import { useQueryChainSpace } from '@/hooks/useChainSpace' import { useQueryEthBalance } from '@/hooks/useEthBalance' import { useQueryEthPrice } from '@/hooks/useEthPrice' import { CreateSpaceDialog } from '../CreateSpaceDialog/CreateSpaceDialog' @@ -11,6 +12,7 @@ import { Sidebar } from './Sidebar/Sidebar' export function DashboardLayout({ children }: PropsWithChildren) { useQueryEthPrice() useQueryEthBalance() + useQueryChainSpace() return (
diff --git a/components/DashboardLayout/Sidebar/SpaceMenu.tsx b/components/DashboardLayout/Sidebar/SpaceMenu.tsx index 07b824f6..bb8df95c 100644 --- a/components/DashboardLayout/Sidebar/SpaceMenu.tsx +++ b/components/DashboardLayout/Sidebar/SpaceMenu.tsx @@ -24,47 +24,66 @@ export function SpaceMenu() { pathname === '/~/create-space' if (!space || isNotSpace) return null - return ( -
- - -
-
- +
+
+ -
{space.name}
- -
-
- - - { - push(`/~/space/${space.id}/settings`) - }} - > - -
Space settings
-
-
- +
{space.name}
+ {/* */} +
) + + // return ( + //
+ // + // + //
+ //
+ // + + //
{space.name}
+ // + //
+ //
+ //
+ // + // { + // push(`/~/space/${space.id}/settings`) + // }} + // > + // + //
Space settings
+ //
+ //
+ //
+ //
+ // ) } diff --git a/components/MemberDialog/MemberDialog.tsx b/components/MemberDialog/MemberDialog.tsx index 94545be3..aede8a15 100644 --- a/components/MemberDialog/MemberDialog.tsx +++ b/components/MemberDialog/MemberDialog.tsx @@ -3,17 +3,14 @@ import { Dialog, DialogContent, + DialogDescription, DialogHeader, DialogTitle, } from '@/components/ui/dialog' import { useQueryEthBalance } from '@/hooks/useEthBalance' import { RouterOutputs } from '@/server/_app' -import { useMutation } from '@tanstack/react-query' -import { ProfileAvatar } from '../Profile/ProfileAvatar' -import { AmountInput } from './AmountInput' import { MemberForm } from './MemberForm' import { useMemberDialog } from './useMemberDialog' -import { useSubscribe } from './useSubscribe' interface Props { space: RouterOutputs['space']['byId'] @@ -26,6 +23,7 @@ export function MemberDialog({ space }: Props) { return ( setIsOpen(v)}> + Subscription
diff --git a/components/MemberDialog/MemberForm.tsx b/components/MemberDialog/MemberForm.tsx index 9dca0c8e..7537d450 100644 --- a/components/MemberDialog/MemberForm.tsx +++ b/components/MemberDialog/MemberForm.tsx @@ -19,7 +19,7 @@ import { useChainSpace } from '@/hooks/useChainSpace' import { useQueryEthBalance } from '@/hooks/useEthBalance' import { useSubscription } from '@/hooks/useSubscription' import { useTokenBalance } from '@/hooks/useTokenBalance' -import { TradeType } from '@/lib/constants' +import { SubscriptionType, TradeType } from '@/lib/constants' import { precision } from '@/lib/math' import { RouterOutputs } from '@/server/_app' import { zodResolver } from '@hookform/resolvers/zod' @@ -45,7 +45,7 @@ const FormSchema = z.object({ }) export function MemberForm({ space }: Props) { - const { isOpen, setIsOpen } = useMemberDialog() + const { setIsOpen } = useMemberDialog() const [loading, setLoading] = useState(false) useQueryEthBalance() const trade = useSubscribe(space) @@ -56,13 +56,13 @@ export function MemberForm({ space }: Props) { const form = useForm>({ resolver: zodResolver(FormSchema), defaultValues: { - type: TradeType.BUY, + type: SubscriptionType.SUBSCRIBE, token: 'ETH', - times: '180', + times: '180', // 180 days by default }, }) - const isSubscribe = form.watch('type') === 'BUY' + const isSubscribe = form.watch('type') === SubscriptionType.SUBSCRIBE const token = form.watch('token') const times = form.watch('times') @@ -86,7 +86,7 @@ export function MemberForm({ space }: Props) { }, [isSubscribe, token, space.symbolName]) async function onSubmit(data: z.infer) { - const isSubscribe = data.type === 'BUY' + const isSubscribe = data.type === SubscriptionType.SUBSCRIBE setLoading(true) const amount = getAmount(data.token, data.times, isSubscribe) @@ -128,13 +128,13 @@ export function MemberForm({ space }: Props) { > Subscribe Unsubscribe diff --git a/components/MemberDialog/useSubscribe.ts b/components/MemberDialog/useSubscribe.ts index 32a432db..8a74a263 100644 --- a/components/MemberDialog/useSubscribe.ts +++ b/components/MemberDialog/useSubscribe.ts @@ -3,21 +3,18 @@ import { useMembers } from '@/hooks/useMembers' import { refetchSpaces } from '@/hooks/useSpaces' import { useSubscription } from '@/hooks/useSubscription' import { spaceAbi } from '@/lib/abi' -import { TradeType } from '@/lib/constants' +import { SubscriptionType } from '@/lib/constants' import { extractErrorMessage } from '@/lib/extractErrorMessage' -import { precision } from '@/lib/math' import { api } from '@/lib/trpc' import { wagmiConfig } from '@/lib/wagmi' import { RouterOutputs } from '@/server/_app' -import { Post } from '@prisma/client' import { readContract, waitForTransactionReceipt, writeContract, } from '@wagmi/core' -import { useSearchParams } from 'next/navigation' import { toast } from 'sonner' -import { Address, isAddress, zeroAddress } from 'viem' +import { Address } from 'viem' import { useWriteContract } from 'wagmi' export function useSubscribe(space: RouterOutputs['space']['byId']) { @@ -32,9 +29,18 @@ export function useSubscribe(space: RouterOutputs['space']['byId']) { isSubscribe: boolean, duration: number, ) => { - const tradeType = isSubscribe ? TradeType.BUY : TradeType.SELL + const subscriptionType = isSubscribe + ? SubscriptionType.SUBSCRIBE + : SubscriptionType.UNSUBSCRIBE try { if (isSubscribe) { + console.log( + '=====amount:', + amount, + 'space.spaceAddress:', + space.spaceAddress, + ) + const hash = await writeContractAsync({ address: space.spaceAddress as Address, abi: spaceAbi, @@ -62,9 +68,8 @@ export function useSubscribe(space: RouterOutputs['space']['byId']) { functionName: 'getSubscription', args: [address], }) - console.log('========subscription.info:', info) - await api.trade.tradeSpaceKey.mutate({ + await api.subscriptionRecord.upsertSubscription.mutate({ spaceId: space.id, tradeDuration: duration, start: Number(info.start), @@ -73,7 +78,7 @@ export function useSubscribe(space: RouterOutputs['space']['byId']) { amount: String(info.amount), consumed: String(info.consumed), - type: tradeType, + type: subscriptionType, }) await Promise.all([ @@ -82,9 +87,9 @@ export function useSubscribe(space: RouterOutputs['space']['byId']) { refetchSpaces(), ]) - toast.success('Buy Key successful!') + toast.success('Subscribe successful!') } catch (error) { - console.log('=======>>>>error:', error) + console.log('=======>>>>error:', JSON.stringify(error)) const msg = extractErrorMessage(error) toast.error(msg) } finally { diff --git a/components/spaceToken/AmountInput.tsx b/components/spaceToken/AmountInput.tsx new file mode 100644 index 00000000..0c313bfc --- /dev/null +++ b/components/spaceToken/AmountInput.tsx @@ -0,0 +1,47 @@ +import { ReactNode } from 'react' +import { matchNumber } from '@/lib/utils' + +interface Props { + symbolName: string + icon: ReactNode + disabled?: boolean + value: string + onChange: (value: string) => void +} + +export const AmountInput = ({ + symbolName, + icon, + value, + onChange, + disabled = false, +}: Props) => { + return ( +
+ { + let value = e.target.value + if ((e.nativeEvent as any)?.data === '。') { + value = value.replace('。', '.') + } + + if (!matchNumber(value, 8) && value.length) { + if (/^\.\d+$/.test(value)) { + onChange?.('0' + value) + e.preventDefault() + } + return + } + onChange(e.target.value) + }} + placeholder="0.0" + className="font-bold text-2xl text-black pl-0 w-full border-none focus:border-none outline-none bg-transparent h-full" + /> + {icon} + {symbolName} +
+ ) +} diff --git a/components/spaceToken/Buy.tsx b/components/spaceToken/Buy.tsx deleted file mode 100644 index b79524af..00000000 --- a/components/spaceToken/Buy.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { ChangeEvent, useMemo, useState } from 'react' -import { useTokenKxy } from '@/hooks/useTokenKxy' -import { precision } from '@/lib/math' -import { Space } from '@prisma/client' -import { Address } from 'viem' -import { Button } from '../ui/button' -import { BuyBtn } from './BuyBtn' -import { formatAmount } from './hooks/useSpaceTokenBalance' - -interface Props { - ethBalance: string - tokenBalance: bigint | undefined - isConnected: boolean - space: Space -} - -export const Buy = ({ - space, - ethBalance, - tokenBalance, - isConnected, -}: Props) => { - const [ethAmount, setEthAmount] = useState('0') - const [purchasedAmount, setPurchasedAmount] = useState('0') - const { updateTokenKxy, getBuyTokenAmount } = useTokenKxy() - - const isAmountValid = - parseFloat(ethAmount) > 0 && parseFloat(purchasedAmount) > 0 - - const isInsufficientBalance = parseFloat(ethBalance) < parseFloat(ethAmount) - - const validateAndSetEthAmount = (value: string) => { - // Validate and format input - if (/^\d*\.?\d*$/.test(value) && !value.startsWith('.')) { - const formattedValue = formatAmount(value) - setEthAmount(formattedValue) - const decimalAmount = getBuyTokenAmount( - precision.toExactDecimalBigint(value), - ) - if (!Number(value) || !decimalAmount) { - setPurchasedAmount('') - } else { - setPurchasedAmount(precision.toExactDecimalString(decimalAmount)) - } - } - } - - const validateAndsetPurchasedAmount = (value: string) => { - // Validate and format input - // if (/^\d*\.?\d*$/.test(value) && !value.startsWith('.')) { } - } - - const handleMax = () => { - setEthAmount(ethBalance) - const decimalAmount = getBuyTokenAmount( - precision.toExactDecimalBigint(ethBalance), - ) - if (!ethAmount || !decimalAmount) { - setPurchasedAmount('') - } else { - setPurchasedAmount(precision.toExactDecimalString(decimalAmount)) - } - } - - const displayBalance = useMemo(() => { - if (tokenBalance) { - return Number(precision.toExactDecimalString(tokenBalance)).toFixed(4) - } - - return '0.0000' - }, [tokenBalance]) - - return ( - <> -
-
Sell
-
- ) => - validateAndSetEthAmount(e.target.value) - } - placeholder="Amount in ETH" - className="p-2 font-[600] text-[24px] text-[#222222] pl-0 bg-gray-100 rounded w-full border-none focus:border-none outline-none" - /> - ETH - ETH -
-
- Balance: {ethBalance} - -
-
- -
-
Buy
-
- ) => - validateAndsetPurchasedAmount(e.target.value) - } - placeholder="Amount in PenX" - className="p-2 font-[500] text-[24px] text-[#222222] pl-0 bg-gray-100 rounded w-full border-none focus:border-none outline-none" - /> - PenX - {space?.name} -
-
- Balance: {displayBalance} -
-
- { - setEthAmount('') - setPurchasedAmount('') - updateTokenKxy(space.spaceAddress as Address) - }} - isInsufficientBalance={isInsufficientBalance} - isAmountValid={isAmountValid} - space={space} - /> - - ) -} diff --git a/components/spaceToken/BuyBtn.tsx b/components/spaceToken/BuyBtn.tsx index ad4928fa..1815cd42 100644 --- a/components/spaceToken/BuyBtn.tsx +++ b/components/spaceToken/BuyBtn.tsx @@ -1,6 +1,10 @@ +import { useQueryEthBalance } from '@/hooks/useEthBalance' +import { useTrades } from '@/hooks/useTrades' import { spaceAbi } from '@/lib/abi' +import { TradeType } from '@/lib/constants' import { extractErrorMessage } from '@/lib/extractErrorMessage' import { precision } from '@/lib/math' +import { api } from '@/lib/trpc' import { wagmiConfig } from '@/lib/wagmi' import { Space } from '@prisma/client' import { waitForTransactionReceipt } from '@wagmi/core' @@ -14,6 +18,7 @@ import { useSpaceTokenBalance } from './hooks/useSpaceTokenBalance' interface Props { ethAmount: string + purchasedAmount: string handleSwap: () => void isInsufficientBalance: boolean isAmountValid: boolean @@ -23,6 +28,7 @@ interface Props { export const BuyBtn = ({ ethAmount, + purchasedAmount, isInsufficientBalance, isAmountValid, handleSwap, @@ -31,10 +37,12 @@ export const BuyBtn = ({ }: Props) => { const { writeContractAsync, isPending } = useWriteContract() const balance = useSpaceTokenBalance() + const { refetch: refetchEth } = useQueryEthBalance() + const trade = useTrades() const onBuy = async () => { try { - const value = precision.token(parseFloat(ethAmount), 18) + const value = precision.token(ethAmount, 18) const hash = await writeContractAsync({ address: space.spaceAddress as Address, abi: spaceAbi, @@ -43,7 +51,18 @@ export const BuyBtn = ({ }) await waitForTransactionReceipt(wagmiConfig, { hash }) - await balance.refetch() + await Promise.all([ + api.trade.create.mutate({ + spaceId: space.id, + type: TradeType.BUY, + amountIn: String(value), + amountOut: precision.token(purchasedAmount).toString(), + }), + balance.refetch(), + refetchEth(), + ]) + + trade.refetch() handleSwap() toast.success(`${space?.name} bought successfully!`) } catch (error) { @@ -56,7 +75,7 @@ export const BuyBtn = ({ <> {isConnected ? ( +
+
+ +
+
Buy
+ + } + value={purchasedAmount} + onChange={(value) => validateAndSetPurchasedAmount(value)} + /> + +
+ +
+
+ { + setEthAmount('') + setPurchasedAmount('') + refetch() + }} + isInsufficientBalance={isInsufficientBalance} + isAmountValid={isAmountValid} + space={space} + /> + + ) +} diff --git a/components/spaceToken/EthBalance.tsx b/components/spaceToken/EthBalance.tsx new file mode 100644 index 00000000..2951ad4b --- /dev/null +++ b/components/spaceToken/EthBalance.tsx @@ -0,0 +1,17 @@ +'use client' + +import { useEthBalance } from '@/hooks/useEthBalance' +import { Skeleton } from '../ui/skeleton' + +export const EthBalance = () => { + const { ethBalance } = useEthBalance() + if (!ethBalance.valueDecimal) return + return ( +
+ +
+ {ethBalance.valueFormatted} +
+
+ ) +} diff --git a/components/spaceToken/Sell.tsx b/components/spaceToken/Sell.tsx deleted file mode 100644 index 9988ddc9..00000000 --- a/components/spaceToken/Sell.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import { ChangeEvent, useMemo, useState } from 'react' -import { Button } from '../ui/button' -import { SellBtn } from './SellBtn' -import { precision } from '@/lib/math' -import { useTokenKxy } from '@/hooks/useTokenKxy' -import { Address } from 'viem' -import { Space } from '@prisma/client' -import { formatAmount } from './hooks/useSpaceTokenBalance' - -interface Props { - ethBalance: string - tokenBalance: bigint | undefined - isConnected: boolean - space: Space -} - -export const Sell = ({ space, ethBalance, tokenBalance, isConnected }: Props) => { - const [ethAmount, setEthAmount] = useState('0') - const [purchasedAmount, setPurchasedAmount] = useState('0') - - // const isAmountValid = parseFloat(ethAmount) > 0 && parseFloat(purchasedAmount) > 0 - // TODO: please add eth judgment logic - const isAmountValid = parseFloat(purchasedAmount) > 0 - - const { updateTokenKxy, getSellEthAmount } = useTokenKxy() - - const validateAndSetEthAmount = (value: string) => { - // Validate and format input - // if (/^\d*\.?\d*$/.test(value) && !value.startsWith('.')) { } - } - - const validateAndsetPurchasedAmount = (value: string) => { - // Validate and format input - if (/^\d*\.?\d*$/.test(value) && !value.startsWith('.')) { - const formattedValue = formatAmount(value) - setPurchasedAmount(formattedValue) - const decimalAmount = getSellEthAmount(precision.toExactDecimalBigint(value)) - if (!Number(value) || !decimalAmount) { - setEthAmount('') - } else { - setEthAmount(precision.toExactDecimalString(decimalAmount)) - } - } - } - - const handleMax = () => { - if (tokenBalance) { - setPurchasedAmount(precision.toExactDecimalString(tokenBalance)) - const decimalAmount = getSellEthAmount(tokenBalance) - if (!ethAmount || !decimalAmount) { - setEthAmount('') - } else { - setEthAmount(precision.toExactDecimalString(decimalAmount)) - } - } - } - - const { decimalBalance, displayBalance } = useMemo(() => { - if (tokenBalance) { - const decimal = precision.toExactDecimalString(tokenBalance); - return { - decimalBalance: Number(decimal), - displayBalance: Number(decimal).toFixed(4), - }; - } - return { - decimalBalance: 0, - displayBalance: '0.0000', - }; - }, [tokenBalance]); - - const isInsufficientBalance = decimalBalance < parseFloat(purchasedAmount) - - return <> -
-
Sell
-
- ) => - validateAndsetPurchasedAmount(e.target.value) - } - placeholder="Amount in PenX" - className="p-2 font-[500] text-[24px] text-[#222222] pl-0 bg-gray-100 rounded w-full border-none focus:border-none outline-none" - /> - PenX - {space?.name} -
-
- Balance: {displayBalance} - -
-
- -
-
Buy
-
- ) => - validateAndSetEthAmount(e.target.value) - } - placeholder="Amount in ETH" - className="p-2 font-[600] text-[24px] text-[#222222] pl-0 bg-gray-100 rounded w-full border-none focus:border-none outline-none" - /> - ETH - ETH -
-
- Balance: {ethBalance} -
-
- - { - setEthAmount('') - setPurchasedAmount('') - updateTokenKxy(space.spaceAddress as Address) - }} - isInsufficientBalance={isInsufficientBalance} - isAmountValid={isAmountValid} - space={space} - /> - -} \ No newline at end of file diff --git a/components/spaceToken/SellBtn.tsx b/components/spaceToken/SellBtn.tsx index 24ddcd89..ba14fdbd 100644 --- a/components/spaceToken/SellBtn.tsx +++ b/components/spaceToken/SellBtn.tsx @@ -1,6 +1,10 @@ +import { useEthBalance, useQueryEthBalance } from '@/hooks/useEthBalance' +import { useTrades } from '@/hooks/useTrades' import { erc20Abi, spaceAbi } from '@/lib/abi' +import { TradeType } from '@/lib/constants' import { extractErrorMessage } from '@/lib/extractErrorMessage' import { precision } from '@/lib/math' +import { api } from '@/lib/trpc' import { wagmiConfig } from '@/lib/wagmi' import { Space } from '@prisma/client' import { waitForTransactionReceipt } from '@wagmi/core' @@ -23,6 +27,7 @@ interface Props { } export const SellBtn = ({ + ethAmount, purchasedAmount, isInsufficientBalance, isAmountValid, @@ -32,6 +37,8 @@ export const SellBtn = ({ }: Props) => { const { writeContractAsync, isPending } = useWriteContract() const balance = useSpaceTokenBalance() + const { refetch: refetchEth } = useQueryEthBalance() + const trade = useTrades() const onSell = async () => { try { @@ -54,7 +61,18 @@ export const SellBtn = ({ }) await waitForTransactionReceipt(wagmiConfig, { hash }) - await balance.refetch() + + await Promise.all([ + api.trade.create.mutate({ + spaceId: space.id, + type: TradeType.SELL, + amountIn: String(value), + amountOut: precision.token(ethAmount).toString(), + }), + balance.refetch(), + refetchEth(), + ]) + trade.refetch() handleSwap() toast.success(`${space?.name} sell successfully!`) } catch (error) { @@ -68,14 +86,14 @@ export const SellBtn = ({ <> {isConnected ? ( +
+
+ +
+
Buy
+ + } + value={ethAmount} + onChange={(value) => validateAndSetEthAmount(value)} + /> +
+ +
+
+ + { + setEthAmount('') + setPurchasedAmount('') + refetchChainSpace() + }} + isInsufficientBalance={isInsufficientBalance} + isAmountValid={isAmountValid} + space={space} + /> + + ) +} diff --git a/components/spaceToken/SpaceTokenBalance.tsx b/components/spaceToken/SpaceTokenBalance.tsx new file mode 100644 index 00000000..96dc220f --- /dev/null +++ b/components/spaceToken/SpaceTokenBalance.tsx @@ -0,0 +1,18 @@ +'use client' + +import { precision } from '@/lib/math' +import { Skeleton } from '../ui/skeleton' +import { useSpaceTokenBalance } from './hooks/useSpaceTokenBalance' + +export const SpaceTokenBalance = () => { + const { isLoading, data } = useSpaceTokenBalance() + if (isLoading) return + return ( +
+ +
+ {precision.toDecimal(data!).toFixed(4)} +
+
+ ) +} diff --git a/domains/Space.ts b/domains/Space.ts index 5a91ce7d..e1890a41 100644 --- a/domains/Space.ts +++ b/domains/Space.ts @@ -83,7 +83,7 @@ export class Space { getTokenPricePerSecond() { const ethPricePerSecond = this.getEthPricePerSecond() - const { tokenAmount } = this.getTokenAmount(ethPricePerSecond) + const tokenAmount = this.getTokenAmount(ethPricePerSecond) return tokenAmount } @@ -93,10 +93,7 @@ export class Space { const newX = this.x + ethAmountAfterFee const newY = this.k / newX const tokenAmount = this.y - newY - return { - tokenAmount, - tokenAmountFormatted: toFloorFixed(Number(tokenAmount), 2), - } + return tokenAmount } getEthAmount(tokenAmount: bigint) { @@ -105,9 +102,6 @@ export class Space { const newY = this.y + tokenAmountAfterFee const newX = this.k / newY const ethAmount = this.x - newX - return { - ethAmount, - ethAmountFormatted: toFloorFixed(Number(ethAmount), 2), - } + return ethAmount } } diff --git a/hooks/useSpaceTrades.ts b/hooks/useSpaceTrades.ts index b3069030..a3758951 100644 --- a/hooks/useSpaceTrades.ts +++ b/hooks/useSpaceTrades.ts @@ -1,7 +1,7 @@ import { trpc } from '@/lib/trpc' -export function useSpaceTrades(spaceId: string) { - const { data: trades = [], ...rest } = - trpc.trade.listBySpaceId.useQuery(spaceId) - return { trades, ...rest } +export function useSubscriptionRecords(spaceId: string) { + const { data: records = [], ...rest } = + trpc.subscriptionRecord.listBySpaceId.useQuery(spaceId) + return { records, ...rest } } diff --git a/hooks/useTokenKxy.ts b/hooks/useTokenKxy.ts deleted file mode 100644 index 412a9916..00000000 --- a/hooks/useTokenKxy.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { spaceAbi } from '@/lib/abi' -import { wagmiConfig } from '@/lib/wagmi' -import { readContract, readContracts } from '@wagmi/core' -import { atom, useAtom } from 'jotai' -import { Address } from 'viem' - -interface IKxy { - k: bigint - x: bigint - y: bigint -} - -const tokenKxyAtom = atom({ - k: BigInt(0), - x: BigInt(0), - y: BigInt(0), -}) - -const FEE_RATE = BigInt(1) - -export function useTokenKxy() { - const [tokenKxy, setTokenKxy] = useAtom(tokenKxyAtom) - - const updateTokenKxy = async (spaceAddress: Address) => { - try { - const { x, y, k } = await readContract(wagmiConfig, { - address: spaceAddress, - abi: spaceAbi, - functionName: 'getSpaceInfo', - }) - - setTokenKxy({ k, x, y }) - } catch (error) { - console.error('Failed to update kxy values:', error) - } - } - - function getBuyTokenAmount(ethAmount: bigint): bigint { - const fee = (ethAmount * FEE_RATE) / BigInt(100) - const ethAmountAfterFee = ethAmount - fee - const newX = tokenKxy.x + ethAmountAfterFee - const newY = tokenKxy.k / newX - const tokenAmount = tokenKxy.y - newY - - return tokenAmount - } - - function getSellEthAmount(tokenAmount: bigint): bigint { - const fee = (tokenAmount * FEE_RATE) / BigInt(100) - const tokenAmountAfterFee = tokenAmount - fee - const newY = tokenKxy.y + tokenAmountAfterFee - const newX = tokenKxy.k / newY - const ethAmount = tokenKxy.x - newX - - return ethAmount - } - - const getTokenKxy = (): IKxy => { - return tokenKxy - } - - return { getBuyTokenAmount, getTokenKxy, updateTokenKxy, getSellEthAmount } -} diff --git a/hooks/useTrades.ts b/hooks/useTrades.ts new file mode 100644 index 00000000..097ef700 --- /dev/null +++ b/hooks/useTrades.ts @@ -0,0 +1,13 @@ +import { trpc } from '@/lib/trpc' +import { useSpace } from './useSpace' + +export function useTrades() { + const { space } = useSpace() + const { data: trades = [], ...rest } = trpc.trade.listBySpaceId.useQuery( + space.id, + { + enabled: !!space?.id, + }, + ) + return { records: trades, ...rest } +} diff --git a/lib/constants.ts b/lib/constants.ts index 510732ec..ceb8b1aa 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -3,6 +3,11 @@ export enum TradeType { SELL = 'SELL', } +export enum SubscriptionType { + SUBSCRIBE = 'SUBSCRIBE', + UNSUBSCRIBE = 'UNSUBSCRIBE', +} + export enum TradeSource { MEMBER = 'MEMBER', SPONSOR = 'SPONSOR', diff --git a/lib/math/precision.ts b/lib/math/precision.ts index 3412970e..c5cdbdfd 100644 --- a/lib/math/precision.ts +++ b/lib/math/precision.ts @@ -34,7 +34,10 @@ export const precision = { return BigInt(parseInt(times(Math.pow(10, decimal), value) as any, 10)) }, - toDecimal(value: bigint | number, decimals: number = Decimals.TOKEN) { + toDecimal( + value: bigint | number | string = '', + decimals: number = Decimals.TOKEN, + ) { if (!value) return 0 return div(value.toString(), Math.pow(10, decimals)) }, @@ -43,8 +46,11 @@ export const precision = { }, // Maintaining Numeric Precision - toExactDecimalString(value: bigint, decimals: number = Decimals.TOKEN): string { - if (!value) return "0" + toExactDecimalString( + value: bigint, + decimals: number = Decimals.TOKEN, + ): string { + if (!value) return '0' const factor = BigInt(Math.pow(10, decimals)) const integerPart = value / factor const fractionalPart = value % factor @@ -52,10 +58,13 @@ export const precision = { }, // Maintaining Numeric Precision - toExactDecimalBigint(decimalValue: string, decimals: number = Decimals.TOKEN): bigint { - const [integerPart, fractionalPart = ""] = decimalValue.split(".") + toExactDecimalBigint( + decimalValue: string, + decimals: number = Decimals.TOKEN, + ): bigint { + const [integerPart, fractionalPart = ''] = decimalValue.split('.') const integerBigInt = BigInt(integerPart) * BigInt(Math.pow(10, decimals)) - const fractionalBigInt = BigInt(fractionalPart.padEnd(decimals, "0")) + const fractionalBigInt = BigInt(fractionalPart.padEnd(decimals, '0')) return integerBigInt + fractionalBigInt - } + }, } diff --git a/lib/wagmi/siweConfig.ts b/lib/wagmi/siweConfig.ts index 9c1e1160..9e9713f4 100644 --- a/lib/wagmi/siweConfig.ts +++ b/lib/wagmi/siweConfig.ts @@ -49,10 +49,10 @@ export const siweConfig = createSIWEConfig({ } }, - // onSignIn: (session?: SIWESession) => { - // location.href = '/' - // location.reload() - // }, + onSignIn: (session?: SIWESession) => { + // location.href = '/' + location.reload() + }, signOut: async () => { try { await signOut({ diff --git a/lib/wagmi/wagmiConfig.ts b/lib/wagmi/wagmiConfig.ts index cc21edc6..c8809c8c 100644 --- a/lib/wagmi/wagmiConfig.ts +++ b/lib/wagmi/wagmiConfig.ts @@ -24,7 +24,16 @@ const metadata = { // Create wagmiConfig const chains = [ - arbitrumSepolia, + { + ...arbitrumSepolia, + rpcUrls: { + default: { + http: [ + 'https://arb-sepolia.g.alchemy.com/v2/HI5irVjoVHajk9VrB7FAkpt2Inz1iymo', + ], + }, + }, + }, // baseSepolia, // mainnet, // optimism, diff --git a/next.config.js b/next.config.js index 670cd838..5414b47a 100644 --- a/next.config.js +++ b/next.config.js @@ -6,7 +6,7 @@ const { env } = require('./server/env') module.exports = { experimental: { serverActions: { - allowedOrigins: ['app.localhost:3000'], + // allowedOrigins: ['app.localhost:3000'], }, }, diff --git a/package.json b/package.json index 08a68cc6..98276a9c 100644 --- a/package.json +++ b/package.json @@ -42,10 +42,10 @@ "@vercel/analytics": "^1.3.1", "@vercel/blob": "^0.15.0", "@vercel/kv": "^1.0.1", - "@vercel/postgres": "^0.5.1", + "@vercel/postgres": "^0.9.0", "@wagmi/core": "^2.13.4", - "@web3modal/siwe": "^5.1.0", - "@web3modal/wagmi": "^5.1.0", + "@web3modal/siwe": "^5.1.1", + "@web3modal/wagmi": "^5.1.1", "ai": "^2.2.22", "big.js": "^6.2.1", "c": "^1.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8bb28025..f0bb4c3c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -96,17 +96,17 @@ dependencies: specifier: ^1.0.1 version: 1.0.1 '@vercel/postgres': - specifier: ^0.5.1 - version: 0.5.1 + specifier: ^0.9.0 + version: 0.9.0 '@wagmi/core': specifier: ^2.13.4 version: 2.13.4(@types/react@18.2.37)(react@18.2.0)(typescript@5.2.2)(viem@2.18.2) '@web3modal/siwe': - specifier: ^5.1.0 - version: 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) + specifier: ^5.1.1 + version: 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) '@web3modal/wagmi': - specifier: ^5.1.0 - version: 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(@wagmi/connectors@5.1.1)(@wagmi/core@2.13.4)(ioredis@5.4.1)(react-dom@18.2.0)(react@18.2.0)(viem@2.18.2)(vue@3.3.8)(wagmi@2.12.1) + specifier: ^5.1.1 + version: 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(@wagmi/connectors@5.1.1)(@wagmi/core@2.13.4)(ioredis@5.4.1)(react-dom@18.2.0)(react@18.2.0)(viem@2.18.2)(vue@3.3.8)(wagmi@2.12.1) ai: specifier: ^2.2.22 version: 2.2.22(react@18.2.0)(solid-js@1.8.5)(svelte@4.2.3)(vue@3.3.8) @@ -2685,10 +2685,10 @@ packages: tslib: 2.6.2 dev: false - /@neondatabase/serverless@0.6.0: - resolution: {integrity: sha512-qXxBRYN0m2v8kVQBfMxbzNGn2xFAhTXFibzQlE++NfJ56Shz3m7+MyBBtXDlEH+3Wfa6lToDXf1MElocY4sJ3w==} + /@neondatabase/serverless@0.9.4: + resolution: {integrity: sha512-D0AXgJh6xkf+XTlsO7iwE2Q1w8981E1cLCPAALMU2YKtkF/1SF6BiAzYARZFYo175ON+b1RNIy9TdSFHm5nteg==} dependencies: - '@types/pg': 8.6.6 + '@types/pg': 8.11.6 dev: false /@next/env@14.0.2: @@ -5399,12 +5399,12 @@ packages: resolution: {integrity: sha512-5PjwB0uP2XDp3nt5u5NJAG2DORHIRClPzWT/TTZhJ2Ekwe8M5bA9tvPdi9NO/n2uvu2/ictat8kgqvLfcIE1SA==} dev: false - /@types/pg@8.6.6: - resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==} + /@types/pg@8.11.6: + resolution: {integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==} dependencies: '@types/node': 20.9.0 pg-protocol: 1.6.0 - pg-types: 2.2.0 + pg-types: 4.0.2 dev: false /@types/prop-types@15.7.10: @@ -5593,14 +5593,14 @@ packages: '@upstash/redis': 1.25.1 dev: false - /@vercel/postgres@0.5.1: - resolution: {integrity: sha512-JKl8QOBIDnifhkxAhIKtY0A5Tb8oWBf2nzZhm0OH7Ffjsl0hGVnDL2w1/FCfpX8xna3JAWM034NGuhZfTFdmiw==} + /@vercel/postgres@0.9.0: + resolution: {integrity: sha512-WiI2g3+ce2g1u1gP41MoDj2DsMuQQ+us7vHobysRixKECGaLHpfTI7DuVZmHU087ozRAGr3GocSyqmWLLo+fig==} engines: {node: '>=14.6'} dependencies: - '@neondatabase/serverless': 0.6.0 + '@neondatabase/serverless': 0.9.4 bufferutil: 4.0.8 - utf-8-validate: 6.0.3 - ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3) + utf-8-validate: 6.0.4 + ws: 8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.4) dev: false /@vue/compiler-core@3.3.8: @@ -5866,8 +5866,8 @@ packages: - utf-8-validate dev: false - /@walletconnect/core@2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1): - resolution: {integrity: sha512-QekYQlpxyn2bcQXMkMxo0+v7nUOQKyu3j5ZKzTg/HGU1eSgTRLIvYIEkC8VVflIgOw7meOAb5pFChX51wShksQ==} + /@walletconnect/core@2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1): + resolution: {integrity: sha512-9MWVt33MFrLiAeK9nqY/B30/y0M4uiq8v9EXenIBQdlgkmXM++RTcOnn7u7EAbthGgzx3WLPRm4ViwIb+rI/Cg==} engines: {node: '>=18'} dependencies: '@walletconnect/heartbeat': 1.2.2 @@ -5881,8 +5881,8 @@ packages: '@walletconnect/relay-auth': 1.0.4 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) - '@walletconnect/utils': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/types': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/utils': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) events: 3.3.0 lodash.isequal: 4.5.0 uint8arrays: 3.1.0 @@ -5946,18 +5946,18 @@ packages: - utf-8-validate dev: false - /@walletconnect/ethereum-provider@2.15.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0): - resolution: {integrity: sha512-qQyHVwJtPo7RZJIIn7KAp20t2pthhr9P2Nnhv196+49dTMJ5Es962cgouA410XA7DSQkom+4esiXR2AR5SsrAA==} + /@walletconnect/ethereum-provider@2.15.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0): + resolution: {integrity: sha512-3ssEAKc/rLYshwyE2ZIaoTxzi/p9Ws+kj/FIsd1Ed/CC37Rl5l/KYHaRJtevWeni9s4dGqyqKsYkJ0VwwUcnfQ==} dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/modal': 2.6.2(@types/react@18.2.37)(react@18.2.0) - '@walletconnect/sign-client': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) - '@walletconnect/types': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) - '@walletconnect/universal-provider': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) - '@walletconnect/utils': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/sign-client': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/types': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/universal-provider': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/utils': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -6168,17 +6168,17 @@ packages: - utf-8-validate dev: false - /@walletconnect/sign-client@2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1): - resolution: {integrity: sha512-efwrPfIwKWKeku44TGBCnQqPZGCILI1wBKK9bTF0F0/qrLR/zRe6RWpM3/L4+jOMr/BktxPZ5lRozBh+c2U7Pg==} + /@walletconnect/sign-client@2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1): + resolution: {integrity: sha512-YnLNEmCHgZ8yBpE3hwZnHD/bVznVMguSAlwLBNOoWUH2f4d9mR8bqa6KeVXqZ3e8mVHcxKTJTjTJ3oQMLyKIjw==} dependencies: - '@walletconnect/core': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/core': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.1.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) - '@walletconnect/utils': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/types': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/utils': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -6231,8 +6231,8 @@ packages: - uWebSockets.js dev: false - /@walletconnect/types@2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1): - resolution: {integrity: sha512-hLffDKKe70jIrK+YcLkAnzi6vqNki1SDBWjV+M/72mKcU2KzXxk0G2STFsWsQDx8DoqxMiuGehd0DlD1jwQmBg==} + /@walletconnect/types@2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1): + resolution: {integrity: sha512-4WkMsHD8ioZI5GmxNT0qMlz6msI7ZajBcTyDxfRncaNZVau0C+Btw1U4jWO+gxwJVDJY+Ue/cb1QKJ5BanZsyw==} dependencies: '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 @@ -6289,17 +6289,17 @@ packages: - utf-8-validate dev: false - /@walletconnect/universal-provider@2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1): - resolution: {integrity: sha512-+jIuYyLfud1XRYPWt/3wYiD7DYUOSZk26qbtvZFMj1m947NRnZGzp+0gt1ORi7NInEtX3R0fUhMOYKnPwadp6g==} + /@walletconnect/universal-provider@2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1): + resolution: {integrity: sha512-JvKwHoE/ugWSKOmrEr03go1V79N0bbYV6w24Lqlzz4VAoReZZo8TDKsya7UkJ1L5HUCgKVP+AVktuJv8khzJ6w==} dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) - '@walletconnect/types': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) - '@walletconnect/utils': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/sign-client': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/types': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/utils': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -6355,8 +6355,8 @@ packages: - uWebSockets.js dev: false - /@walletconnect/utils@2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1): - resolution: {integrity: sha512-xaazgCMyr5fUPm2QuZ76G+W8beDfKMILqJ3INL6wyuaLil2YQNdsCSvWMNhSP+EZeKD3SUqqBmQaM/maP0YHTg==} + /@walletconnect/utils@2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1): + resolution: {integrity: sha512-i5AR8XpZdcX8ghaCjYV13Er/KAGe56c1mLaG9c2cv9kmnZMZijeMdInjX/flnSM1RFDUiZXvKPMUNwlCL4NsWw==} dependencies: '@stablelib/chacha20poly1305': 1.0.1 '@stablelib/hkdf': 1.0.1 @@ -6366,11 +6366,10 @@ packages: '@walletconnect/relay-api': 1.0.11 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@walletconnect/types': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) '@walletconnect/window-getters': 1.0.1 '@walletconnect/window-metadata': 1.0.1 detect-browser: 5.3.0 - elliptic: 6.5.7 query-string: 7.1.3 uint8arrays: 3.1.0 transitivePeerDependencies: @@ -6403,32 +6402,32 @@ packages: tslib: 1.14.1 dev: false - /@web3modal/common@5.1.0: - resolution: {integrity: sha512-TIYncrKDnFKE+q0mudzVCvGOZdNWa0kzkp+iL0zpbHm9sL+ceV4eOCip09Xcvrb5HeaBv1ROgAMPGLmpVCO3AA==} + /@web3modal/common@5.1.1: + resolution: {integrity: sha512-3rXsfFhaGPdr0F1iQ0andnZ4o9Dtq23m4ZC+IkEZ9nYjQ3U8i1KkI7jlSL3Ziq5jSTy1/uBcr154Db4frb6+jQ==} dependencies: bignumber.js: 9.1.2 dayjs: 1.11.10 dev: false - /@web3modal/core@5.1.0(@types/react@18.2.37)(react@18.2.0): - resolution: {integrity: sha512-dasGgDnhAFKvdm4OwC4iiWsCwx+kPjrZBEqnz1vxY1Z27aQx19eke4xN+2IYjN/TCRG+m+5BoeCqyNomHEjaug==} + /@web3modal/core@5.1.1(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-76ywvsayfj7LcdrxfQBMOj62HRULnH3tIvIO9khQm/8EAjqTo23kKMPxNxd5kctw8EN6C0qonTFAzxY46v6QHA==} dependencies: - '@web3modal/common': 5.1.0 - '@web3modal/wallet': 5.1.0 + '@web3modal/common': 5.1.1 + '@web3modal/wallet': 5.1.1 valtio: 1.11.2(@types/react@18.2.37)(react@18.2.0) transitivePeerDependencies: - '@types/react' - react dev: false - /@web3modal/polyfills@5.1.0: - resolution: {integrity: sha512-Vj0+htFFi053oU4n10vfkNDCDv0VladWW7WdpbneiYs8nVThIP1+aGil5DG1iL0JsModgwaWgJwKwDKbwlCFtA==} + /@web3modal/polyfills@5.1.1: + resolution: {integrity: sha512-Y91SBc12r2x1V3Y3OsNZM5zmNLBUEd3mIzJ9fGrBu38q6Fe6XzxVr6VEWCPiK7g/y1eA++1AdbiVZq587zeuRg==} dependencies: buffer: 6.0.3 dev: false - /@web3modal/scaffold-react@5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-XfgRiIVCvhAPBBjXJIKMQIdQXSqfLza8XtylakqiFtgh9B8taFJOCH4vomi+WucAvGAtxGju4IyEub7afSIvog==} + /@web3modal/scaffold-react@5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-u88KVr/7qKmCGaIVEJvUQhGf3VaqPKzyqWDaymLgo6IvsTCnnsoVZdejpkxh1FY28vOehsBD2QMh/ruPPzpnRw==} peerDependencies: react: '>=17' react-dom: '>=17' @@ -6438,7 +6437,7 @@ packages: react-dom: optional: true dependencies: - '@web3modal/scaffold': 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) + '@web3modal/scaffold': 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) transitivePeerDependencies: @@ -6459,15 +6458,15 @@ packages: - uWebSockets.js dev: false - /@web3modal/scaffold-ui@5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0): - resolution: {integrity: sha512-X2WjL6TtuCFw2qeVClVjmYDWbBQDK7JV0CiO57FUBo8xLMhYcj1pSQ1G+zOvikkWaGWwiOyKxJWzVsfrDeihOQ==} + /@web3modal/scaffold-ui@5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0): + resolution: {integrity: sha512-Pi1TAPPtw3Xxb3BD8EDsRVhtKh9UPNa6ACTrDrKnAeXBPSWMRI2GBZOTrfrqfJzixsjoFfH+79J/D2JDvvXCEA==} dependencies: - '@web3modal/common': 5.1.0 - '@web3modal/core': 5.1.0(@types/react@18.2.37)(react@18.2.0) - '@web3modal/scaffold-utils': 5.1.0(@types/react@18.2.37)(react@18.2.0) - '@web3modal/siwe': 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) - '@web3modal/ui': 5.1.0 - '@web3modal/wallet': 5.1.0 + '@web3modal/common': 5.1.1 + '@web3modal/core': 5.1.1(@types/react@18.2.37)(react@18.2.0) + '@web3modal/scaffold-utils': 5.1.1(@types/react@18.2.37)(react@18.2.0) + '@web3modal/siwe': 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) + '@web3modal/ui': 5.1.1 + '@web3modal/wallet': 5.1.1 lit: 3.1.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -6488,29 +6487,29 @@ packages: - uWebSockets.js dev: false - /@web3modal/scaffold-utils@5.1.0(@types/react@18.2.37)(react@18.2.0): - resolution: {integrity: sha512-q4SwEWgUT03VJEMvOuegm+k89eWU/BYq/2bJYIyO5bf0hpVCTLDk2MG9nNJ1wafJdYv8iCAe5xWhfdv8OKPC3Q==} + /@web3modal/scaffold-utils@5.1.1(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-oHZ9LKidN36sFDFaTcBgkfhKRxSx+wYPpLtL7hdN782w5MI6M/rhnefmUogKblWfXSmZ3GvDVbpG3QLvKEPIZg==} dependencies: '@coinbase/wallet-sdk': 4.0.3 - '@web3modal/core': 5.1.0(@types/react@18.2.37)(react@18.2.0) - '@web3modal/polyfills': 5.1.0 - '@web3modal/wallet': 5.1.0 + '@web3modal/core': 5.1.1(@types/react@18.2.37)(react@18.2.0) + '@web3modal/polyfills': 5.1.1 + '@web3modal/wallet': 5.1.1 valtio: 1.11.2(@types/react@18.2.37)(react@18.2.0) transitivePeerDependencies: - '@types/react' - react dev: false - /@web3modal/scaffold-vue@5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0)(vue@3.3.8): - resolution: {integrity: sha512-d0Ar9b+lXVVlhzFVAACFrYbzCEen5hdzgmevRibKvhkvYnKZjYweTSldTNt8z0qnn1JNZMOA23/9Q4gGMJHACA==} + /@web3modal/scaffold-vue@5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0)(vue@3.3.8): + resolution: {integrity: sha512-NiwLGZpPEgHHf22KD2Xvd7mK70RKK0kfQOB8sm3W0LSfxh5wfrY1WrhwXR0XDs9mSFN2fD4bxEDbUwvcTXD/XQ==} peerDependencies: vue: '>=3' peerDependenciesMeta: vue: optional: true dependencies: - '@web3modal/core': 5.1.0(@types/react@18.2.37)(react@18.2.0) - '@web3modal/scaffold': 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) + '@web3modal/core': 5.1.1(@types/react@18.2.37)(react@18.2.0) + '@web3modal/scaffold': 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) vue: 3.3.8(typescript@5.2.2) transitivePeerDependencies: - '@azure/app-configuration' @@ -6531,16 +6530,16 @@ packages: - uWebSockets.js dev: false - /@web3modal/scaffold@5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0): - resolution: {integrity: sha512-92SO2gQF1N3TWJBIor1ju2RoBvubCbhm/zdVG1nGYvyIf3k9ulX2crZAmg0P8CE8Cc3rrLPty2wW10hncbdv7g==} + /@web3modal/scaffold@5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0): + resolution: {integrity: sha512-E51ksfT0EWyttUmIjnkKDzTo5WafrzcrScXVeuMySYGk0ldN4yh70A8Y82qWcCtPRQ8hzb8MrMB4F26P67BGlA==} dependencies: - '@web3modal/common': 5.1.0 - '@web3modal/core': 5.1.0(@types/react@18.2.37)(react@18.2.0) - '@web3modal/scaffold-ui': 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) - '@web3modal/scaffold-utils': 5.1.0(@types/react@18.2.37)(react@18.2.0) - '@web3modal/siwe': 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) - '@web3modal/ui': 5.1.0 - '@web3modal/wallet': 5.1.0 + '@web3modal/common': 5.1.1 + '@web3modal/core': 5.1.1(@types/react@18.2.37)(react@18.2.0) + '@web3modal/scaffold-ui': 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) + '@web3modal/scaffold-utils': 5.1.1(@types/react@18.2.37)(react@18.2.0) + '@web3modal/siwe': 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) + '@web3modal/ui': 5.1.1 + '@web3modal/wallet': 5.1.1 lit: 3.1.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -6561,15 +6560,15 @@ packages: - uWebSockets.js dev: false - /@web3modal/siwe@5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0): - resolution: {integrity: sha512-HUS/lBswY+AUiYvDbUaJX1RFoDH4HLFouUDv+Q4DhpY8qOT2vT8IdxkVyKezDAtXRcak7L/qSzLdgSv5ijDcDw==} + /@web3modal/siwe@5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0): + resolution: {integrity: sha512-tuWIKuXP0cRL+7DI3pkK0UqMWPwxptfI+ojinndQfwc972sFNGGZZLxeYWCShWqbUnMw0eVQOjoJCXDF9zXTtA==} dependencies: - '@walletconnect/utils': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) - '@web3modal/common': 5.1.0 - '@web3modal/core': 5.1.0(@types/react@18.2.37)(react@18.2.0) - '@web3modal/scaffold-utils': 5.1.0(@types/react@18.2.37)(react@18.2.0) - '@web3modal/ui': 5.1.0 - '@web3modal/wallet': 5.1.0 + '@walletconnect/utils': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@web3modal/common': 5.1.1 + '@web3modal/core': 5.1.1(@types/react@18.2.37)(react@18.2.0) + '@web3modal/scaffold-utils': 5.1.1(@types/react@18.2.37)(react@18.2.0) + '@web3modal/ui': 5.1.1 + '@web3modal/wallet': 5.1.1 lit: 3.1.0 valtio: 1.11.2(@types/react@18.2.37)(react@18.2.0) transitivePeerDependencies: @@ -6591,15 +6590,15 @@ packages: - uWebSockets.js dev: false - /@web3modal/ui@5.1.0: - resolution: {integrity: sha512-msjkOm/PLkfAVglQ8ZsuCLNuaf4IbkWkjZneO1uU+F2+7sCaGZHskFVmJQBbhwN347m0DTU8KgDP0BvFppW4Aw==} + /@web3modal/ui@5.1.1: + resolution: {integrity: sha512-OSAWbltEBc54dVE2WDdqYFMd6Fg1ivh46BHAn1D5bCjGEgGHdm7j8ZHukcKzP9e+raNz8Ih7ShuPKC+NtMc9Dw==} dependencies: lit: 3.1.0 qrcode: 1.5.3 dev: false - /@web3modal/wagmi@5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(@wagmi/connectors@5.1.1)(@wagmi/core@2.13.4)(ioredis@5.4.1)(react-dom@18.2.0)(react@18.2.0)(viem@2.18.2)(vue@3.3.8)(wagmi@2.12.1): - resolution: {integrity: sha512-3SrBSSriv8sDgnBNpK1eo8ykbvIAw9Zmv2rfQ3KMkltW/rTTFTLX9mSbALnV+Tj6ZjhQLnVArtH8FX3FztffQA==} + /@web3modal/wagmi@5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(@wagmi/connectors@5.1.1)(@wagmi/core@2.13.4)(ioredis@5.4.1)(react-dom@18.2.0)(react@18.2.0)(viem@2.18.2)(vue@3.3.8)(wagmi@2.12.1): + resolution: {integrity: sha512-BxQHx1En8+FPSrh+h9P++ixd+LvihCsxZwG0SvlgORTrvGCq/CaO4EgoMUsXek9r5apatwXiJHiqWyIhWDnJsQ==} peerDependencies: '@wagmi/connectors': '>=4' '@wagmi/core': '>=2.0.0' @@ -6618,16 +6617,16 @@ packages: dependencies: '@wagmi/connectors': 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(@wagmi/core@2.13.4)(ioredis@5.4.1)(react-dom@18.2.0)(react-native@0.74.3)(react@18.2.0)(typescript@5.2.2)(viem@2.18.2)(zod@3.23.8) '@wagmi/core': 2.13.4(@types/react@18.2.37)(react@18.2.0)(typescript@5.2.2)(viem@2.18.2) - '@walletconnect/ethereum-provider': 2.15.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) - '@walletconnect/utils': 2.15.0(@vercel/kv@1.0.1)(ioredis@5.4.1) - '@web3modal/common': 5.1.0 - '@web3modal/polyfills': 5.1.0 - '@web3modal/scaffold': 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) - '@web3modal/scaffold-react': 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react-dom@18.2.0)(react@18.2.0) - '@web3modal/scaffold-utils': 5.1.0(@types/react@18.2.37)(react@18.2.0) - '@web3modal/scaffold-vue': 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0)(vue@3.3.8) - '@web3modal/siwe': 5.1.0(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) - '@web3modal/wallet': 5.1.0 + '@walletconnect/ethereum-provider': 2.15.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) + '@walletconnect/utils': 2.15.1(@vercel/kv@1.0.1)(ioredis@5.4.1) + '@web3modal/common': 5.1.1 + '@web3modal/polyfills': 5.1.1 + '@web3modal/scaffold': 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) + '@web3modal/scaffold-react': 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react-dom@18.2.0)(react@18.2.0) + '@web3modal/scaffold-utils': 5.1.1(@types/react@18.2.37)(react@18.2.0) + '@web3modal/scaffold-vue': 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0)(vue@3.3.8) + '@web3modal/siwe': 5.1.1(@types/react@18.2.37)(@vercel/kv@1.0.1)(ioredis@5.4.1)(react@18.2.0) + '@web3modal/wallet': 5.1.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) viem: 2.18.2(typescript@5.2.2)(zod@3.23.8) @@ -6654,12 +6653,12 @@ packages: - utf-8-validate dev: false - /@web3modal/wallet@5.1.0: - resolution: {integrity: sha512-5LdsFMp6wozdvEchfnagsAH/u1moqfRFnBb2iA2gDQZWH0Y+M9UIkw6iRUw0QFnae+uB4ALyUJ3Te0L8VLWmhQ==} + /@web3modal/wallet@5.1.1: + resolution: {integrity: sha512-i0UOh5GuXy0qJbI9bdAf4iPto7ZPX99rjbyiFs3VAR79DM5Ja4f7f2fgBaZy7LVcUr/Gk5LCGyr5Dffmn7d/YQ==} dependencies: '@walletconnect/logger': 2.1.2 - '@web3modal/common': 5.1.0 - '@web3modal/polyfills': 5.1.0 + '@web3modal/common': 5.1.1 + '@web3modal/polyfills': 5.1.1 zod: 3.22.4 dev: false @@ -8322,18 +8321,6 @@ packages: minimalistic-crypto-utils: 1.0.1 dev: false - /elliptic@6.5.7: - resolution: {integrity: sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==} - dependencies: - bn.js: 4.12.0 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - dev: false - /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: false @@ -8363,7 +8350,7 @@ packages: '@socket.io/component-emitter': 3.1.2 debug: 4.3.4 engine.io-parser: 5.2.3 - ws: 8.17.1 + ws: 8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.4) xmlhttprequest-ssl: 2.0.0 transitivePeerDependencies: - bufferutil @@ -10153,7 +10140,7 @@ packages: peerDependencies: ws: '*' dependencies: - ws: 8.17.1 + ws: 8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.4) dev: false /iterator.prototype@1.1.2: @@ -10400,7 +10387,7 @@ packages: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - ws: 8.17.1 + ws: 8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.4) xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -12169,6 +12156,10 @@ packages: es-abstract: 1.22.3 dev: true + /obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + dev: false + /ofetch@1.3.4: resolution: {integrity: sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==} dependencies: @@ -12452,19 +12443,26 @@ packages: engines: {node: '>=4.0.0'} dev: false + /pg-numeric@1.0.2: + resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==} + engines: {node: '>=4'} + dev: false + /pg-protocol@1.6.0: resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==} dev: false - /pg-types@2.2.0: - resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} - engines: {node: '>=4'} + /pg-types@4.0.2: + resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==} + engines: {node: '>=10'} dependencies: pg-int8: 1.0.1 - postgres-array: 2.0.0 - postgres-bytea: 1.0.0 - postgres-date: 1.0.7 - postgres-interval: 1.2.0 + pg-numeric: 1.0.2 + postgres-array: 3.0.2 + postgres-bytea: 3.0.0 + postgres-date: 2.1.0 + postgres-interval: 3.0.0 + postgres-range: 1.1.4 dev: false /picocolors@1.0.0: @@ -12672,26 +12670,30 @@ packages: picocolors: 1.0.1 source-map-js: 1.2.0 - /postgres-array@2.0.0: - resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} - engines: {node: '>=4'} + /postgres-array@3.0.2: + resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==} + engines: {node: '>=12'} dev: false - /postgres-bytea@1.0.0: - resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} - engines: {node: '>=0.10.0'} - dev: false - - /postgres-date@1.0.7: - resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} - engines: {node: '>=0.10.0'} - dev: false - - /postgres-interval@1.2.0: - resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} - engines: {node: '>=0.10.0'} + /postgres-bytea@3.0.0: + resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==} + engines: {node: '>= 6'} dependencies: - xtend: 4.0.2 + obuf: 1.1.2 + dev: false + + /postgres-date@2.1.0: + resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==} + engines: {node: '>=12'} + dev: false + + /postgres-interval@3.0.0: + resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==} + engines: {node: '>=12'} + dev: false + + /postgres-range@1.1.4: + resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==} dev: false /preact-render-to-string@5.2.6(preact@10.19.1): @@ -15436,8 +15438,8 @@ packages: node-gyp-build: 4.6.1 dev: false - /utf-8-validate@6.0.3: - resolution: {integrity: sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==} + /utf-8-validate@6.0.4: + resolution: {integrity: sha512-xu9GQDeFp+eZ6LnCywXN/zBancWvOpUMzgjLPSjy4BRHSmTelvn2E0DG0o1sTiw5hkCKBHo8rwSKncfRfv2EEQ==} engines: {node: '>=6.14.2'} requiresBuild: true dependencies: @@ -15566,7 +15568,7 @@ packages: isows: 1.0.4(ws@8.17.1) typescript: 5.2.2 webauthn-p256: 0.0.5 - ws: 8.17.1 + ws: 8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.4) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -15893,8 +15895,8 @@ packages: optional: true dev: false - /ws@8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3): - resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} + /ws@8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.4): + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -15906,20 +15908,7 @@ packages: optional: true dependencies: bufferutil: 4.0.8 - utf-8-validate: 6.0.3 - dev: false - - /ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true + utf-8-validate: 6.0.4 dev: false /xml-name-validator@4.0.0: diff --git a/prisma/schema.prisma b/prisma/schema.prisma index ae889d29..8c0ab7c3 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -11,59 +11,61 @@ generator client { } model User { - id String @id @default(uuid()) - address String @unique - name String? - ensName String? - email String? @unique - emailVerified DateTime? - image String? - bio String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - spaces Space[] - posts Post[] - members Member[] - trades Trade[] - holders Holder[] - sponsors Sponsor[] - comments Comment[] - lists List[] - contributors Contributor[] - messages Message[] + id String @id @default(uuid()) + address String @unique + name String? + ensName String? + email String? @unique + emailVerified DateTime? + image String? + bio String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + spaces Space[] + posts Post[] + members Member[] + subscriptionRecords SubscriptionRecord[] + holders Holder[] + sponsors Sponsor[] + comments Comment[] + lists List[] + contributors Contributor[] + messages Message[] + trades Trade[] @@index([id]) @@index([address]) } model Space { - id String @id @default(uuid()) - name String - description String @default("") @db.Text - logo String? @default("https://public.blob.vercel-storage.com/eEZHAoPTOBSYGBE3/JRajRyC-PhBHEinQkupt02jqfKacBVHLWJq7Iy.png") @db.Text - font String @default("font-cal") - image String? @default("") @db.Text - imageBlurhash String? @default("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAhCAYAAACbffiEAAAACXBIWXMAABYlAAAWJQFJUiTwAAABfUlEQVR4nN3XyZLDIAwE0Pz/v3q3r55JDlSBplsIEI49h76k4opexCK/juP4eXjOT149f2Tf9ySPgcjCc7kdpBTgDPKByKK2bTPFEdMO0RDrusJ0wLRBGCIuelmWJAjkgPGDSIQEMBDCfA2CEPM80+Qwl0JkNxBimiaYGOTUlXYI60YoehzHJDEm7kxjV3whOQTD3AaCuhGKHoYhyb+CBMwjIAFz647kTqyapdV4enGINuDJMSScPmijSwjCaHeLcT77C7EC0C1ugaCTi2HYfAZANgj6Z9A8xY5eiYghDMNQBJNCWhASot0jGsSCUiHWZcSGQjaWWCDaGMOWnsCcn2QhVkRuxqqNxMSdUSElCDbp1hbNOsa6Ugxh7xXauF4DyM1m5BLtCylBXgaxvPXVwEoOBjeIFVODtW74oj1yBQah3E8tyz3SkpolKS9Geo9YMD1QJR1Go4oJkgO1pgbNZq0AOUPChyjvh7vlXaQa+X1UXwKxgHokB2XPxbX+AnijwIU4ahazAAAAAElFTkSuQmCC") @db.Text - subdomain String? @unique - customDomain String? @unique - memberCount Int @default(0) - sponsorCount Int @default(0) - postCount Int @default(0) - message404 String? @default("Blimey! You've found a page that doesn't exist.") @db.Text - symbolName String @unique - spaceAddress String? @unique // space on chain address - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade) - userId String - posts Post[] - channels Channel[] - members Member[] - trades Trade[] - holders Holder[] - sponsors Sponsor[] - contributors Contributor[] - messages Message[] + id String @id @default(uuid()) + name String + description String @default("") @db.Text + logo String? @default("https://public.blob.vercel-storage.com/eEZHAoPTOBSYGBE3/JRajRyC-PhBHEinQkupt02jqfKacBVHLWJq7Iy.png") @db.Text + font String @default("font-cal") + image String? @default("") @db.Text + imageBlurhash String? @default("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAhCAYAAACbffiEAAAACXBIWXMAABYlAAAWJQFJUiTwAAABfUlEQVR4nN3XyZLDIAwE0Pz/v3q3r55JDlSBplsIEI49h76k4opexCK/juP4eXjOT149f2Tf9ySPgcjCc7kdpBTgDPKByKK2bTPFEdMO0RDrusJ0wLRBGCIuelmWJAjkgPGDSIQEMBDCfA2CEPM80+Qwl0JkNxBimiaYGOTUlXYI60YoehzHJDEm7kxjV3whOQTD3AaCuhGKHoYhyb+CBMwjIAFz647kTqyapdV4enGINuDJMSScPmijSwjCaHeLcT77C7EC0C1ugaCTi2HYfAZANgj6Z9A8xY5eiYghDMNQBJNCWhASot0jGsSCUiHWZcSGQjaWWCDaGMOWnsCcn2QhVkRuxqqNxMSdUSElCDbp1hbNOsa6Ugxh7xXauF4DyM1m5BLtCylBXgaxvPXVwEoOBjeIFVODtW74oj1yBQah3E8tyz3SkpolKS9Geo9YMD1QJR1Go4oJkgO1pgbNZq0AOUPChyjvh7vlXaQa+X1UXwKxgHokB2XPxbX+AnijwIU4ahazAAAAAElFTkSuQmCC") @db.Text + subdomain String? @unique + customDomain String? @unique + memberCount Int @default(0) + sponsorCount Int @default(0) + postCount Int @default(0) + message404 String? @default("Blimey! You've found a page that doesn't exist.") @db.Text + symbolName String @unique + spaceAddress String? @unique // space on chain address + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade) + userId String + posts Post[] + channels Channel[] + members Member[] + subscriptionRecords SubscriptionRecord[] + holders Holder[] + sponsors Sponsor[] + contributors Contributor[] + messages Message[] + trades Trade[] @@index([userId]) @@index([name]) @@ -200,6 +202,26 @@ model Sponsor { @@index([userId]) } +enum SubscriptionType { + SUBSCRIBE + UNSUBSCRIBE +} + +model SubscriptionRecord { + id String @id @default(uuid()) + duration Int @default(0) + type SubscriptionType + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + Space Space @relation(fields: [spaceId], references: [id]) + spaceId String + user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade) + userId String + + @@index([spaceId]) + @@index([type]) +} + enum TradeType { BUY SELL @@ -207,7 +229,8 @@ enum TradeType { model Trade { id String @id @default(uuid()) - duration Int @default(0) + amountIn String @default("0") + amountOut String @default("0") type TradeType createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -217,6 +240,7 @@ model Trade { userId String @@index([spaceId]) + @@index([type]) } enum ChannelType { diff --git a/server/_app.ts b/server/_app.ts index 05960cea..c9e25766 100644 --- a/server/_app.ts +++ b/server/_app.ts @@ -10,6 +10,7 @@ import { messageRouter } from './routers/message' import { postRouter } from './routers/post' import { spaceRouter } from './routers/space' import { sponsorRouter } from './routers/sponsor' +import { subscriptionRecordRouter } from './routers/subscriptionRecord' import { tradeRouter } from './routers/trade' import { userRouter } from './routers/user' import { createCallerFactory, publicProcedure, router } from './trpc' @@ -26,6 +27,7 @@ export const appRouter = router({ trade: tradeRouter, sponsor: sponsorRouter, contributor: contributorRouter, + subscriptionRecord: subscriptionRecordRouter, }) export const createCaller = createCallerFactory(appRouter) diff --git a/server/routers/subscriptionRecord.ts b/server/routers/subscriptionRecord.ts new file mode 100644 index 00000000..5f4bb029 --- /dev/null +++ b/server/routers/subscriptionRecord.ts @@ -0,0 +1,45 @@ +import { TradeSource } from '@/lib/constants' +import { precision } from '@/lib/math' +import { prisma } from '@/lib/prisma' +import { SubscriptionRecord } from '@prisma/client' +import { TRPCError } from '@trpc/server' +import { z } from 'zod' +import { protectedProcedure, publicProcedure, router } from '../trpc' + +enum SubscriptionType { + SUBSCRIBE = 'SUBSCRIBE', + UNSUBSCRIBE = 'UNSUBSCRIBE', +} + +export const subscriptionRecordRouter = router({ + listBySpaceId: publicProcedure.input(z.string()).query(async ({ input }) => { + return [] as (SubscriptionRecord & { + user: { + name: string | null + ensName: string | null + email: string | null + address: string + } + })[] + }), + + upsertSubscription: protectedProcedure + .input( + z.object({ + spaceId: z.string(), + tradeDuration: z.number(), + type: z.enum([ + SubscriptionType.SUBSCRIBE, + SubscriptionType.UNSUBSCRIBE, + ]), + start: z.number(), + checkpoint: z.number(), + duration: z.number(), + amount: z.string(), + consumed: z.string(), + }), + ) + .mutation(async ({ ctx, input }) => { + return true + }), +}) diff --git a/server/routers/trade.ts b/server/routers/trade.ts index 0afe1c61..ff5a58e3 100644 --- a/server/routers/trade.ts +++ b/server/routers/trade.ts @@ -19,37 +19,13 @@ export const tradeRouter = router({ })[] }), - tradeSpaceKey: protectedProcedure + create: protectedProcedure .input( z.object({ spaceId: z.string(), - tradeDuration: z.number(), type: z.enum([TradeType.BUY, TradeType.SELL]), - - start: z.number(), - checkpoint: z.number(), - duration: z.number(), - amount: z.string(), - consumed: z.string(), - }), - ) - .mutation(async ({ ctx, input }) => { - return true - }), - - tradeSponsorKey: protectedProcedure - .input( - z.object({ - spaceId: z.string(), - holdAmount: z.string(), - tradeAmount: z.string(), - price: z.string(), - type: z.enum([TradeType.BUY, TradeType.SELL]), - name: z.string().optional(), - logo: z.string().optional(), - homeUrl: z.string().optional(), - cover: z.string().optional(), - description: z.string().optional(), + amountIn: z.string(), + amountOut: z.string(), }), ) .mutation(async ({ ctx, input }) => {