UNPKG

bigblocks

Version:

Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React

178 lines (177 loc) 6.5 kB
// useFollowUser Hook - Follow/unfollow users by BAP ID import { useMutation } from "@tanstack/react-query"; import { useBitcoinAuth } from "../../../hooks/useBitcoinAuth.js"; import { broadcastSocialTransaction } from "../../../lib/broadcast"; import { SocialActions } from "../../../lib/protocol.js"; export function useFollowUser(options = {}) { const { app: _app = "bigblocks", onSuccess, onError } = options; const { user } = useBitcoinAuth(); const followMutation = useMutation({ mutationFn: async ({ idKey }) => { if (!user) { throw { code: "UNAUTHORIZED", message: "User must be authenticated to follow others", }; } if (!idKey) { throw { code: "INVALID_BAP_ID", message: "BAP ID is required to follow a user", }; } // Validate BAP ID format (basic validation) if (typeof idKey !== "string" || idKey.trim().length === 0) { throw { code: "INVALID_BAP_ID", message: "Invalid BAP ID format", }; } // Prevent self-following if (user.idKey === idKey) { throw { code: "INVALID_CONTENT", message: "Cannot follow yourself", }; } try { const signingKey = user.signingKey; if (!signingKey) { throw { code: "UNAUTHORIZED", message: "No signing key available", }; } // Build follow transaction const signedTransaction = await SocialActions.follow(idKey); // Broadcast to Bitcoin network const result = await broadcastSocialTransaction(signedTransaction); if (!result.success) { throw { code: "BROADCAST_FAILED", message: result.error || "Failed to broadcast follow", }; } return { ...result, action: "follow" }; } catch (error) { if (error.code) { throw error; } throw { code: "TRANSACTION_FAILED", message: "Failed to create follow transaction", details: error, }; } }, onSuccess: (data) => { onSuccess?.({ ...data, action: "follow" }); }, onError: (error) => { console.error("Follow user failed:", error); onError?.(error); }, }); return { mutate: followMutation.mutate, mutateAsync: followMutation.mutateAsync, isLoading: followMutation.isPending, isError: followMutation.isError, isSuccess: followMutation.isSuccess, error: followMutation.error, data: followMutation.data, reset: followMutation.reset, }; } // Unfollow hook export function useUnfollowUser(options = {}) { const { app: _app = "bigblocks", onSuccess, onError } = options; const { user } = useBitcoinAuth(); const unfollowMutation = useMutation({ mutationFn: async ({ idKey }) => { if (!user) { throw { code: "UNAUTHORIZED", message: "User must be authenticated to unfollow others", }; } if (!idKey) { throw { code: "INVALID_BAP_ID", message: "BAP ID is required to unfollow a user", }; } if (typeof idKey !== "string" || idKey.trim().length === 0) { throw { code: "INVALID_BAP_ID", message: "Invalid BAP ID format", }; } try { const signingKey = user.signingKey; if (!signingKey) { throw { code: "UNAUTHORIZED", message: "No signing key available", }; } // Build unfollow transaction const signedTransaction = await SocialActions.unfollow(idKey); // Broadcast to Bitcoin network const result = await broadcastSocialTransaction(signedTransaction); if (!result.success) { throw { code: "BROADCAST_FAILED", message: result.error || "Failed to broadcast unfollow", }; } return { ...result, action: "unfollow" }; } catch (error) { if (error.code) { throw error; } throw { code: "TRANSACTION_FAILED", message: "Failed to create unfollow transaction", details: error, }; } }, onSuccess: (data) => { onSuccess?.({ ...data, action: "unfollow" }); }, onError: (error) => { console.error("Unfollow user failed:", error); onError?.(error); }, }); return { mutate: unfollowMutation.mutate, mutateAsync: unfollowMutation.mutateAsync, isLoading: unfollowMutation.isPending, isError: unfollowMutation.isError, isSuccess: unfollowMutation.isSuccess, error: unfollowMutation.error, data: unfollowMutation.data, reset: unfollowMutation.reset, }; } // Combined hook for toggling follow status export function useToggleFollow(options = {}) { const followUser = useFollowUser(options); const unfollowUser = useUnfollowUser(options); return { follow: followUser, unfollow: unfollowUser, toggle: (idKey, currentlyFollowing) => { if (currentlyFollowing) { return unfollowUser.mutate({ idKey }); } return followUser.mutate({ idKey }); }, isLoading: followUser.isLoading || unfollowUser.isLoading, error: followUser.error || unfollowUser.error, }; }