import { useQuery, useMutation, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'
import { Address, Hash } from 'viem'
import { useAssemble } from '../provider'
import type {
Comment,
CommentsResponse,
PaymentSplit
} from '../../types'
/**
* Query Keys for Social Features
*/
export const socialKeys = {
all: ['social'] as const,
friends: () => [...socialKeys.all, 'friends'] as const,
friendsList: (user: Address) => [...socialKeys.friends(), user] as const,
friendship: (user1: Address, user2: Address) =>
[...socialKeys.friends(), 'status', user1, user2] as const,
comments: () => [...socialKeys.all, 'comments'] as const,
eventComments: (eventId: bigint) => [...socialKeys.comments(), 'event', eventId] as const,
comment: (commentId: bigint) => [...socialKeys.comments(), 'detail', commentId] as const,
commentLike: (commentId: bigint, user: Address) =>
[...socialKeys.comments(), 'like', commentId, user] as const,
withdrawals: (user: Address) => [...socialKeys.all, 'withdrawals', user] as const,
paymentSplits: (eventId: bigint) => [...socialKeys.all, 'splits', eventId] as const,
}
/**
* Hook to get friends list for a user
*/
export function useFriends(
userAddress: Address,
options?: UseQueryOptions
) {
const { client } = useAssemble()
return useQuery({
queryKey: socialKeys.friendsList(userAddress),
queryFn: () => client.social.getFriends(userAddress),
enabled: !!userAddress,
...options,
})
}
/**
* Hook to check friendship status between two users
*/
export function useFriendship(
user1: Address,
user2: Address,
options?: UseQueryOptions
) {
const { client } = useAssemble()
return useQuery({
queryKey: socialKeys.friendship(user1, user2),
queryFn: () => client.social.isFriend(user1, user2),
enabled: !!user1 && !!user2,
...options,
})
}
/**
* Hook to get comments for an event
*/
export function useEventComments(
eventId: bigint,
options?: UseQueryOptions
) {
const { client } = useAssemble()
return useQuery({
queryKey: socialKeys.eventComments(eventId),
queryFn: () => client.social.getEventComments(eventId),
enabled: !!eventId,
...options,
})
}
/**
* Hook to get a specific comment
*/
export function useComment(
commentId: bigint,
options?: UseQueryOptions
) {
const { client } = useAssemble()
return useQuery({
queryKey: socialKeys.comment(commentId),
queryFn: () => client.social.getComment(commentId),
enabled: !!commentId,
...options,
})
}
/**
* Hook to check if a user has liked a comment
*/
export function useCommentLike(
commentId: bigint,
userAddress: Address,
options?: UseQueryOptions
) {
const { client } = useAssemble()
return useQuery({
queryKey: socialKeys.commentLike(commentId, userAddress),
queryFn: () => client.social.hasLikedComment(commentId, userAddress),
enabled: !!commentId && !!userAddress,
...options,
})
}
/**
* Hook to get pending withdrawals for a user
*/
export function usePendingWithdrawals(
userAddress: Address,
options?: UseQueryOptions
) {
const { client } = useAssemble()
return useQuery({
queryKey: socialKeys.withdrawals(userAddress),
queryFn: () => client.social.getPendingWithdrawals(userAddress),
enabled: !!userAddress,
...options,
})
}
/**
* Hook to get payment splits for an event
*/
export function usePaymentSplits(
eventId: bigint,
options?: UseQueryOptions
) {
const { client } = useAssemble()
return useQuery({
queryKey: socialKeys.paymentSplits(eventId),
queryFn: () => client.social.getPaymentSplits(eventId),
enabled: !!eventId,
...options,
})
}
/**
* Mutation hook to add a friend
*/
export function useAddFriend(
options?: UseMutationOptions
) {
const { client, isConnected } = useAssemble()
const queryClient = useQueryClient()
return useMutation({
mutationFn: (friendAddress: Address) => {
if (!isConnected) {
throw new Error('Wallet not connected')
}
return client.social.addFriend(friendAddress)
},
onSuccess: () => {
// Invalidate friends queries
queryClient.invalidateQueries({ queryKey: socialKeys.friends() })
},
...options,
})
}
/**
* Mutation hook to remove a friend
*/
export function useRemoveFriend(
options?: UseMutationOptions
) {
const { client, isConnected } = useAssemble()
const queryClient = useQueryClient()
return useMutation({
mutationFn: (friendAddress: Address) => {
if (!isConnected) {
throw new Error('Wallet not connected')
}
return client.social.removeFriend(friendAddress)
},
onSuccess: () => {
// Invalidate friends queries
queryClient.invalidateQueries({ queryKey: socialKeys.friends() })
},
...options,
})
}
/**
* Mutation hook to post a comment
*/
export function usePostComment(
options?: UseMutationOptions
) {
const { client, isConnected } = useAssemble()
const queryClient = useQueryClient()
return useMutation({
mutationFn: ({ eventId, content, parentId = 0n }) => {
if (!isConnected) {
throw new Error('Wallet not connected')
}
return client.social.postComment(eventId, content, parentId)
},
onSuccess: (_, { eventId }) => {
// Invalidate comments for this event
queryClient.invalidateQueries({ queryKey: socialKeys.eventComments(eventId) })
},
...options,
})
}
/**
* Mutation hook to like a comment
*/
export function useLikeComment(
options?: UseMutationOptions
) {
const { client, isConnected } = useAssemble()
const queryClient = useQueryClient()
return useMutation({
mutationFn: (commentId: bigint) => {
if (!isConnected) {
throw new Error('Wallet not connected')
}
return client.social.likeComment(commentId)
},
onSuccess: (_, commentId) => {
// Invalidate comment like status and comment details
queryClient.invalidateQueries({
queryKey: socialKeys.comments(),
predicate: (query) =>
query.queryKey.includes('like') && query.queryKey.includes(commentId)
})
queryClient.invalidateQueries({ queryKey: socialKeys.comment(commentId) })
},
...options,
})
}
/**
* Mutation hook to unlike a comment
*/
export function useUnlikeComment(
options?: UseMutationOptions
) {
const { client, isConnected } = useAssemble()
const queryClient = useQueryClient()
return useMutation({
mutationFn: (commentId: bigint) => {
if (!isConnected) {
throw new Error('Wallet not connected')
}
return client.social.unlikeComment(commentId)
},
onSuccess: (_, commentId) => {
// Invalidate comment like status and comment details
queryClient.invalidateQueries({
queryKey: socialKeys.comments(),
predicate: (query) =>
query.queryKey.includes('like') && query.queryKey.includes(commentId)
})
queryClient.invalidateQueries({ queryKey: socialKeys.comment(commentId) })
},
...options,
})
}
/**
* Mutation hook to tip an event
*/
export function useTipEvent(
options?: UseMutationOptions
) {
const { client, isConnected } = useAssemble()
const queryClient = useQueryClient()
return useMutation({
mutationFn: ({ eventId, amount, referrer, platformFeeBps }) => {
if (!isConnected) {
throw new Error('Wallet not connected')
}
return client.social.tipEvent(eventId, amount, referrer, platformFeeBps)
},
onSuccess: () => {
// Invalidate withdrawals queries
queryClient.invalidateQueries({
queryKey: socialKeys.all,
predicate: (query) => query.queryKey.includes('withdrawals')
})
},
...options,
})
}
/**
* Mutation hook to delete a comment
*/
export function useDeleteComment(
options?: UseMutationOptions
) {
const { client, isConnected } = useAssemble()
const queryClient = useQueryClient()
return useMutation({
mutationFn: ({ commentId, eventId }) => {
if (!isConnected) {
throw new Error('Wallet not connected')
}
return client.social.deleteComment(commentId, eventId)
},
onSuccess: (_, { eventId }) => {
// Invalidate comments for this event
queryClient.invalidateQueries({ queryKey: socialKeys.eventComments(eventId) })
},
...options,
})
}