UNPKG

bigblocks

Version:

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

113 lines (112 loc) 4.95 kB
// useApiClient Hook - Type-safe API client using bmap-api-types import { ApiError as BaseApiError } from "../../../lib/api-error.js"; // Re-export ApiError for backward compatibility export { ApiError } from "../../../lib/api-error.js"; import { Timeframe, } from "bmap-api-types"; import { BMAP_API_URL } from "../constants.js"; // Generic API fetcher with proper error handling async function fetchApi(endpoint, options) { const response = await fetch(`${BMAP_API_URL}${endpoint}`, { ...options, headers: { "Content-Type": "application/json", ...options?.headers, }, }); const data = await response.json(); // Check if it's an API wrapper response if ("status" in data) { const apiResponse = data; if (apiResponse.status === "error") { const errorResponse = apiResponse; const message = errorResponse.error || "API request failed"; throw new BaseApiError("NETWORK_ERROR", message, errorResponse); } // Extract data from success response return apiResponse.data; } // If not wrapped, check if it's an error if (!response.ok) { throw new BaseApiError("NETWORK_ERROR", response.statusText, { status: response.status, statusText: response.statusText, }); } return data; } // Type-safe API client export const apiClient = { // Posts endpoints posts: { search: (params) => fetchApi(`/social/post/search?q=${encodeURIComponent(params.q)}&limit=${params.limit}&offset=${params.offset}`), byBapId: (params) => fetchApi(`/social/post/bap/${params.bapId}?page=${params.page}&limit=${params.limit}`), byAddress: (params) => fetchApi(`/social/post/address/${params.address}?page=${params.page}&limit=${params.limit}`), single: (txid) => fetchApi(`/social/post/${txid}`), replies: (txid, page = 1, limit = 20) => fetchApi(`/social/post/${txid}/reply?page=${page}&limit=${limit}`), trending: (timeframe = Timeframe.Day, limit = 20) => fetchApi(`/social/post/trending?timeframe=${timeframe}&limit=${limit}`), }, // Generic transaction fetcher for any transaction type transactions: { single: (txid) => fetchApi(`/tx/${txid}`), // Specific transaction type fetchers follow: (txid) => fetchApi(`/social/follow/${txid}`), unfollow: (txid) => fetchApi(`/social/unfollow/${txid}`), }, // Messages endpoints messages: { direct: (params) => fetchApi(`/social/@/${params.bapId}/messages?page=${params.page}&limit=${params.limit}${params.targetBapId ? `&targetBapId=${params.targetBapId}` : ""}`), channel: (channelId, page = 1, limit = 20) => fetchApi(`/social/channels/${channelId}/messages?page=${page}&limit=${limit}`), }, // Likes endpoints likes: { forPost: (txid) => fetchApi(`/social/post/${txid}/like`), byUser: (bapId, page = 1, limit = 20) => fetchApi(`/social/bap/${bapId}/like?page=${page}&limit=${limit}`), }, // Identity endpoints identity: { search: (query, limit = 10) => fetchApi(`/social/identity/search?q=${encodeURIComponent(query)}&limit=${limit}`), byBapId: (bapId) => fetchApi(`/social/identity/${bapId}`), }, // Channels channels: { list: () => fetchApi("/social/channels"), single: (channelId) => fetchApi(`/social/channel/${channelId}`), }, // Friends friends: { byBapId: (bapId) => fetchApi(`/social/friend/${bapId}`), // Friend request management (uses different base URL) accept: async (bapId) => { const response = await fetch(`${BMAP_API_URL}/social/friend/accept`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ bapId }), }); if (!response.ok) { throw new BaseApiError("NETWORK_ERROR", `Failed to accept friend request: ${response.statusText}`, { status: response.status, statusText: response.statusText, }); } return response.json(); }, reject: async (bapId) => { const response = await fetch(`${BMAP_API_URL}/social/friend/reject`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ bapId }), }); if (!response.ok) { throw new BaseApiError("NETWORK_ERROR", `Failed to reject friend request: ${response.statusText}`, { status: response.status, statusText: response.statusText, }); } return response.json(); }, }, }; // Hook for easy access to the API client export function useApiClient() { return apiClient; }