bigblocks
Version:
Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React
161 lines (160 loc) • 5.86 kB
JavaScript
// useLikePost Hook - Like/unlike posts with emoji reactions
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 useLikePost(options = {}) {
const { app: _app = "bigblocks", onSuccess, onError } = options;
const { user } = useBitcoinAuth();
const likeMutation = useMutation({
mutationFn: async ({ txid, emoji: _emoji = "❤" }) => {
if (!user) {
throw {
code: "UNAUTHORIZED",
message: "User must be authenticated to like posts",
};
}
if (!txid) {
throw {
code: "INVALID_CONTENT",
message: "Transaction ID is required to like a post",
};
}
// Validate txid format (64 character hex string)
if (!/^[a-fA-F0-9]{64}$/.test(txid)) {
throw {
code: "INVALID_CONTENT",
message: "Invalid transaction ID format",
};
}
try {
const signingKey = user.signingKey;
if (!signingKey) {
throw {
code: "UNAUTHORIZED",
message: "No signing key available",
};
}
// Build like transaction
const signedTransaction = await SocialActions.like(txid, _emoji);
// Broadcast to Bitcoin network
const result = await broadcastSocialTransaction(signedTransaction);
if (!result.success) {
throw {
code: "BROADCAST_FAILED",
message: result.error || "Failed to broadcast like",
};
}
return { ...result, transaction: signedTransaction };
}
catch (error) {
if (error.code) {
throw error;
}
throw {
code: "TRANSACTION_FAILED",
message: "Failed to create like transaction",
details: error,
};
}
},
onSuccess: (data) => {
onSuccess?.(data);
},
onError: (error) => {
console.error("Like post failed:", error);
onError?.(error);
},
});
return {
mutate: likeMutation.mutate,
mutateAsync: likeMutation.mutateAsync,
isLoading: likeMutation.isPending,
isError: likeMutation.isError,
isSuccess: likeMutation.isSuccess,
error: likeMutation.error,
data: likeMutation.data,
reset: likeMutation.reset,
};
}
// Unlike hook
export function useUnlikePost(options = {}) {
const { app: _app = "bigblocks", onSuccess, onError } = options;
const { user } = useBitcoinAuth();
return useMutation({
mutationFn: async ({ txid, emoji: _emoji = "❤" }) => {
if (!user) {
throw {
code: "UNAUTHORIZED",
message: "User must be authenticated to unlike posts",
};
}
if (!txid) {
throw {
code: "INVALID_CONTENT",
message: "Transaction ID is required to unlike a post",
};
}
if (!/^[a-fA-F0-9]{64}$/.test(txid)) {
throw {
code: "INVALID_CONTENT",
message: "Invalid transaction ID format",
};
}
try {
const signingKey = user.signingKey;
if (!signingKey) {
throw {
code: "UNAUTHORIZED",
message: "No signing key available",
};
}
// Build unlike transaction
const signedTransaction = await SocialActions.unlike(txid);
// Broadcast to Bitcoin network
const result = await broadcastSocialTransaction(signedTransaction);
if (!result.success) {
throw {
code: "BROADCAST_FAILED",
message: result.error || "Failed to broadcast unlike",
};
}
return { ...result, transaction: signedTransaction };
}
catch (error) {
if (error.code) {
throw error;
}
throw {
code: "TRANSACTION_FAILED",
message: "Failed to create unlike transaction",
details: error,
};
}
},
onSuccess: (data) => {
onSuccess?.(data);
},
onError: (error) => {
console.error("Unlike post failed:", error);
onError?.(error);
},
});
}
// Combined hook for toggling likes
export function useToggleLike(options = {}) {
const likePost = useLikePost(options);
const unlikePostMutation = useUnlikePost(options);
return {
like: likePost,
unlike: unlikePostMutation,
toggle: (txid, emoji, currentlyLiked) => {
if (currentlyLiked) {
return unlikePostMutation.mutate({ txid, emoji });
}
return likePost.mutate({ txid, emoji });
},
isLoading: likePost.isLoading || unlikePostMutation.isPending,
error: likePost.error || unlikePostMutation.error,
};
}