@sudobility/heavymath_indexer_client 0.0.35 → 0.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"useFavorites.d.ts","sourceRoot":"","sources":["../../src/hooks/useFavorites.ts"],"names":[],"mappings":"AAMA,OAAO,EAIL,eAAe,EACf,cAAc,EACd,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAwBzD,wBAAgB,YAAY,CAC1B,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,OAAO,CAAC,EAAE,sBAAsB,EAChC,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,GAC7F;IACD,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,KAAK,EAAE,cAAc,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC7D,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,iBAAiB,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,qBAAqB,CAAC,CAAC;IAC9F,cAAc,EAAE,iBAAiB,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACpE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAyIA;AAcD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;eAnKnF,kBAAkB,EAAE;WACxB,cAAc,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;eACjD,OAAO;aACT,OAAO;WACT,KAAK,GAAG,IAAI;iBACN,iBAAiB,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,qBAAqB,CAAC;oBAC7E,iBAAiB,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC;aAC1D,MAAM,IAAI;EA+JpB;AAeD,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,IAAI,EAAE,qBAAqB,GAC1B;IACD,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC,CA2BA;AAYD,wBAAgB,qBAAqB,gCAEpC;AAcD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EAAE,GAChB;IACD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;CACpB,CAuBA"}
1
+ {"version":3,"file":"useFavorites.d.ts","sourceRoot":"","sources":["../../src/hooks/useFavorites.ts"],"names":[],"mappings":"AAMA,OAAO,EAIL,eAAe,EACf,cAAc,EACd,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAwBzD,wBAAgB,YAAY,CAC1B,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,OAAO,CAAC,EAAE,sBAAsB,EAChC,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,GAC7F;IACD,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,KAAK,EAAE,cAAc,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC7D,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,iBAAiB,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,qBAAqB,CAAC,CAAC;IAC9F,cAAc,EAAE,iBAAiB,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACpE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAyIA;AAcD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;eAnKnF,kBAAkB,EAAE;WACxB,cAAc,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;eACjD,OAAO;aACT,OAAO;WACT,KAAK,GAAG,IAAI;iBACN,iBAAiB,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,qBAAqB,CAAC;oBAC7E,iBAAiB,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC;aAC1D,MAAM,IAAI;EA+JpB;AAeD,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,IAAI,EAAE,qBAAqB,GAC1B;IACD,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC,CA2BA;AAYD,wBAAgB,qBAAqB,gCAEpC;AAcD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EAAE,GAChB;IACD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;CACpB,CAgBA"}
@@ -141,15 +141,8 @@ const FIVE_MINUTES = 5 * 60 * 1000;
141
141
  export function useFavoriteCounts(client, category, subcategory, type, itemIds) {
142
142
  const enabled = itemIds.length > 0;
143
143
  const query = useQuery({
144
- queryKey: [
145
- 'heavymath',
146
- 'favoriteCounts',
147
- category,
148
- subcategory,
149
- type,
150
- ...itemIds.slice().sort(),
151
- ],
152
- queryFn: () => client.getFavoriteCounts({ category, subcategory, type, itemIds }),
144
+ queryKey: ['heavymath', 'favoriteCounts', category, subcategory, type],
145
+ queryFn: () => client.getFavoriteCounts({ category, subcategory, type }),
153
146
  enabled,
154
147
  staleTime: FIVE_MINUTES,
155
148
  });
@@ -1 +1 @@
1
- {"version":3,"file":"useFavorites.js","sourceRoot":"","sources":["../../src/hooks/useFavorites.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * React hooks for wallet favorites operations\n * Uses Zustand for local persistence and React Query for API sync\n */\n\nimport { useCallback, useEffect } from 'react';\nimport {\n useQuery,\n useMutation,\n useQueryClient,\n UseQueryOptions,\n UseQueryResult,\n UseMutationResult,\n} from '@tanstack/react-query';\nimport type {\n WalletFavoriteData,\n PaginatedResponse,\n ApiResponse,\n WalletFavoritesFilters,\n CreateFavoriteRequest,\n} from '../types';\nimport { IndexerClient } from '../network/IndexerClient';\nimport { useFavoritesStore } from '../stores/favorites-store';\n\n/**\n * Hook for managing wallet favorites\n * Uses Zustand for local persistence with optimistic updates\n *\n * @example\n * ```tsx\n * const { favorites, isLoading, addFavorite, removeFavorite, refresh } = useFavorites(\n * client,\n * '0x123...'\n * );\n *\n * // Add a favorite (optimistic update)\n * await addFavorite({ category: 'sports', subcategory: 'soccer', type: 'team', id: 'team-123' });\n *\n * // Remove a favorite (optimistic update)\n * await removeFavorite(favoriteId);\n *\n * // Manually refresh from server\n * refresh();\n * ```\n */\nexport function useFavorites(\n client: IndexerClient,\n walletAddress: string | undefined,\n filters?: WalletFavoritesFilters,\n options?: Omit<UseQueryOptions<PaginatedResponse<WalletFavoriteData>>, 'queryKey' | 'queryFn'>\n): {\n favorites: WalletFavoriteData[];\n query: UseQueryResult<PaginatedResponse<WalletFavoriteData>>;\n isLoading: boolean;\n isError: boolean;\n error: Error | null;\n addFavorite: UseMutationResult<ApiResponse<WalletFavoriteData>, Error, CreateFavoriteRequest>;\n removeFavorite: UseMutationResult<ApiResponse<void>, Error, number>;\n refresh: () => void;\n} {\n const queryClient = useQueryClient();\n const queryKey = ['heavymath', 'favorites', walletAddress, filters];\n\n // Zustand store actions\n const {\n getFavorites,\n setFavorites,\n addFavoriteOptimistic,\n updateFavoriteFromServer,\n removeFavoriteOptimistic,\n rollbackAdd,\n rollbackRemove,\n findFavorite,\n needsRefresh,\n } = useFavoritesStore();\n\n // Get favorites from store (for optimistic UI)\n const storedFavorites = walletAddress ? getFavorites(walletAddress) : [];\n\n // Filter stored favorites if filters are provided\n const filteredFavorites = storedFavorites.filter(fav => {\n if (filters?.category && fav.category !== filters.category) return false;\n if (filters?.subcategory && fav.subcategory !== filters.subcategory) return false;\n if (filters?.type && fav.type !== filters.type) return false;\n return true;\n });\n\n // Query for fetching favorites from server\n const query = useQuery({\n queryKey,\n queryFn: async () => {\n if (!walletAddress) {\n return {\n success: true,\n data: [],\n pagination: {\n totalCount: 0,\n pageSize: filters?.limit ?? 50,\n hasNextPage: false,\n hasPreviousPage: false,\n },\n timestamp: new Date().toISOString(),\n } as PaginatedResponse<WalletFavoriteData>;\n }\n const response = await client.getFavorites(walletAddress, filters);\n // Update store with server data (without filters to get all favorites)\n if (!filters) {\n setFavorites(walletAddress, response.data ?? []);\n }\n return response;\n },\n staleTime: 2 * 60 * 1000, // 2 minutes\n retry: false,\n // Only fetch if store needs refresh or no data\n enabled: walletAddress ? needsRefresh(walletAddress) || storedFavorites.length === 0 : false,\n ...options,\n });\n\n // Sync store when query succeeds (for filtered queries)\n useEffect(() => {\n if (query.data?.data && walletAddress && !filters) {\n setFavorites(walletAddress, query.data.data);\n }\n }, [query.data, walletAddress, filters, setFavorites]);\n\n // Refresh function - invalidates query and forces refetch\n const refresh = useCallback(() => {\n if (walletAddress) {\n // Clear the lastFetched to force refresh\n queryClient.invalidateQueries({ queryKey });\n }\n }, [queryClient, queryKey, walletAddress]);\n\n // Mutation for adding a favorite with optimistic update\n const addFavorite = useMutation({\n mutationFn: async (favorite: CreateFavoriteRequest) => {\n if (!walletAddress) {\n throw new Error('Wallet address is required to add favorites');\n }\n return await client.addFavorite(walletAddress, favorite);\n },\n onMutate: async (favorite: CreateFavoriteRequest) => {\n if (!walletAddress) return;\n // Optimistic update\n addFavoriteOptimistic(walletAddress, favorite);\n return { favorite };\n },\n onSuccess: (response, _favorite) => {\n if (!walletAddress || !response.data) return;\n // Update with server response (real ID)\n updateFavoriteFromServer(walletAddress, response.data);\n },\n onError: (_error, favorite) => {\n if (!walletAddress) return;\n // Rollback optimistic update\n rollbackAdd(walletAddress, favorite.id);\n },\n });\n\n // Mutation for removing a favorite with optimistic update\n const removeFavorite = useMutation({\n mutationFn: async (favoriteId: number) => {\n if (!walletAddress) {\n throw new Error('Wallet address is required to remove favorites');\n }\n return await client.removeFavorite(walletAddress, favoriteId);\n },\n onMutate: async (favoriteId: number) => {\n if (!walletAddress) return;\n // Save favorite for potential rollback\n const favorite = findFavorite(\n walletAddress,\n storedFavorites.find(f => f.id === favoriteId)?.itemId ?? ''\n );\n // Optimistic update\n removeFavoriteOptimistic(walletAddress, favoriteId);\n return { favorite };\n },\n onError: (_error, _favoriteId, context) => {\n if (!walletAddress || !context?.favorite) return;\n // Rollback optimistic update\n rollbackRemove(walletAddress, context.favorite);\n },\n });\n\n return {\n // Use filtered favorites from store for immediate UI updates\n favorites: filteredFavorites,\n query,\n isLoading: query.isLoading && storedFavorites.length === 0,\n isError: query.isError,\n error: query.error,\n addFavorite,\n removeFavorite,\n refresh,\n };\n}\n\n/**\n * Get favorites for a specific category\n *\n * @example\n * ```tsx\n * const { favorites, addFavorite, removeFavorite } = useCategoryFavorites(\n * client,\n * '0x123...',\n * 'sports'\n * );\n * ```\n */\nexport function useCategoryFavorites(\n client: IndexerClient,\n walletAddress: string | undefined,\n category: string,\n options?: Omit<UseQueryOptions<PaginatedResponse<WalletFavoriteData>>, 'queryKey' | 'queryFn'>\n) {\n return useFavorites(client, walletAddress, { category }, options);\n}\n\n/**\n * Check if an item is favorited\n * Uses Zustand store for immediate response\n *\n * @example\n * ```tsx\n * const { isFavorite, toggleFavorite } = useIsFavorite(\n * client,\n * '0x123...',\n * { category: 'sports', subcategory: 'soccer', type: 'team', id: 'team-123' }\n * );\n * ```\n */\nexport function useIsFavorite(\n client: IndexerClient,\n walletAddress: string | undefined,\n item: CreateFavoriteRequest\n): {\n isFavorite: boolean;\n favoriteId: number | undefined;\n isLoading: boolean;\n toggleFavorite: () => Promise<void>;\n} {\n const { isFavorite: checkIsFavorite, findFavorite } = useFavoritesStore();\n\n // Use store directly for immediate response\n const isFavorited = walletAddress ? checkIsFavorite(walletAddress, item.id) : false;\n const existingFavorite = walletAddress ? findFavorite(walletAddress, item.id) : undefined;\n\n const { addFavorite, removeFavorite, isLoading } = useFavorites(client, walletAddress, {\n category: item.category,\n subcategory: item.subcategory,\n type: item.type,\n });\n\n const toggleFavorite = useCallback(async () => {\n if (existingFavorite) {\n await removeFavorite.mutateAsync(existingFavorite.id);\n } else {\n await addFavorite.mutateAsync(item);\n }\n }, [existingFavorite, addFavorite, removeFavorite, item]);\n\n return {\n isFavorite: isFavorited,\n favoriteId: existingFavorite?.id,\n isLoading: isLoading || addFavorite.isPending || removeFavorite.isPending,\n toggleFavorite,\n };\n}\n\n/**\n * Hook to access the favorites store directly\n * Useful for reading favorites without API calls\n *\n * @example\n * ```tsx\n * const { getFavorites, isFavorite, clearAll } = useFavoritesStoreHook();\n * const favorites = getFavorites('0x123...');\n * ```\n */\nexport function useFavoritesStoreHook() {\n return useFavoritesStore();\n}\n\nconst FIVE_MINUTES = 5 * 60 * 1000;\n\n/**\n * Hook to get favorite counts across all wallets for specific items.\n * Useful for dealers to see how popular an entity is.\n *\n * @example\n * ```tsx\n * const { counts, isLoading } = useFavoriteCounts(client, 'sports', 'soccer', 'team', ['1', '2', '3']);\n * // counts['1'] === 5, counts['2'] === 12\n * ```\n */\nexport function useFavoriteCounts(\n client: IndexerClient,\n category: string,\n subcategory: string,\n type: string,\n itemIds: string[]\n): {\n counts: Record<string, number>;\n isLoading: boolean;\n} {\n const enabled = itemIds.length > 0;\n\n const query = useQuery({\n queryKey: [\n 'heavymath',\n 'favoriteCounts',\n category,\n subcategory,\n type,\n ...itemIds.slice().sort(),\n ],\n queryFn: () => client.getFavoriteCounts({ category, subcategory, type, itemIds }),\n enabled,\n staleTime: FIVE_MINUTES,\n });\n\n const counts = query.data?.data ?? {};\n\n return {\n counts,\n isLoading: query.isLoading,\n };\n}\n"]}
1
+ {"version":3,"file":"useFavorites.js","sourceRoot":"","sources":["../../src/hooks/useFavorites.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * React hooks for wallet favorites operations\n * Uses Zustand for local persistence and React Query for API sync\n */\n\nimport { useCallback, useEffect } from 'react';\nimport {\n useQuery,\n useMutation,\n useQueryClient,\n UseQueryOptions,\n UseQueryResult,\n UseMutationResult,\n} from '@tanstack/react-query';\nimport type {\n WalletFavoriteData,\n PaginatedResponse,\n ApiResponse,\n WalletFavoritesFilters,\n CreateFavoriteRequest,\n} from '../types';\nimport { IndexerClient } from '../network/IndexerClient';\nimport { useFavoritesStore } from '../stores/favorites-store';\n\n/**\n * Hook for managing wallet favorites\n * Uses Zustand for local persistence with optimistic updates\n *\n * @example\n * ```tsx\n * const { favorites, isLoading, addFavorite, removeFavorite, refresh } = useFavorites(\n * client,\n * '0x123...'\n * );\n *\n * // Add a favorite (optimistic update)\n * await addFavorite({ category: 'sports', subcategory: 'soccer', type: 'team', id: 'team-123' });\n *\n * // Remove a favorite (optimistic update)\n * await removeFavorite(favoriteId);\n *\n * // Manually refresh from server\n * refresh();\n * ```\n */\nexport function useFavorites(\n client: IndexerClient,\n walletAddress: string | undefined,\n filters?: WalletFavoritesFilters,\n options?: Omit<UseQueryOptions<PaginatedResponse<WalletFavoriteData>>, 'queryKey' | 'queryFn'>\n): {\n favorites: WalletFavoriteData[];\n query: UseQueryResult<PaginatedResponse<WalletFavoriteData>>;\n isLoading: boolean;\n isError: boolean;\n error: Error | null;\n addFavorite: UseMutationResult<ApiResponse<WalletFavoriteData>, Error, CreateFavoriteRequest>;\n removeFavorite: UseMutationResult<ApiResponse<void>, Error, number>;\n refresh: () => void;\n} {\n const queryClient = useQueryClient();\n const queryKey = ['heavymath', 'favorites', walletAddress, filters];\n\n // Zustand store actions\n const {\n getFavorites,\n setFavorites,\n addFavoriteOptimistic,\n updateFavoriteFromServer,\n removeFavoriteOptimistic,\n rollbackAdd,\n rollbackRemove,\n findFavorite,\n needsRefresh,\n } = useFavoritesStore();\n\n // Get favorites from store (for optimistic UI)\n const storedFavorites = walletAddress ? getFavorites(walletAddress) : [];\n\n // Filter stored favorites if filters are provided\n const filteredFavorites = storedFavorites.filter(fav => {\n if (filters?.category && fav.category !== filters.category) return false;\n if (filters?.subcategory && fav.subcategory !== filters.subcategory) return false;\n if (filters?.type && fav.type !== filters.type) return false;\n return true;\n });\n\n // Query for fetching favorites from server\n const query = useQuery({\n queryKey,\n queryFn: async () => {\n if (!walletAddress) {\n return {\n success: true,\n data: [],\n pagination: {\n totalCount: 0,\n pageSize: filters?.limit ?? 50,\n hasNextPage: false,\n hasPreviousPage: false,\n },\n timestamp: new Date().toISOString(),\n } as PaginatedResponse<WalletFavoriteData>;\n }\n const response = await client.getFavorites(walletAddress, filters);\n // Update store with server data (without filters to get all favorites)\n if (!filters) {\n setFavorites(walletAddress, response.data ?? []);\n }\n return response;\n },\n staleTime: 2 * 60 * 1000, // 2 minutes\n retry: false,\n // Only fetch if store needs refresh or no data\n enabled: walletAddress ? needsRefresh(walletAddress) || storedFavorites.length === 0 : false,\n ...options,\n });\n\n // Sync store when query succeeds (for filtered queries)\n useEffect(() => {\n if (query.data?.data && walletAddress && !filters) {\n setFavorites(walletAddress, query.data.data);\n }\n }, [query.data, walletAddress, filters, setFavorites]);\n\n // Refresh function - invalidates query and forces refetch\n const refresh = useCallback(() => {\n if (walletAddress) {\n // Clear the lastFetched to force refresh\n queryClient.invalidateQueries({ queryKey });\n }\n }, [queryClient, queryKey, walletAddress]);\n\n // Mutation for adding a favorite with optimistic update\n const addFavorite = useMutation({\n mutationFn: async (favorite: CreateFavoriteRequest) => {\n if (!walletAddress) {\n throw new Error('Wallet address is required to add favorites');\n }\n return await client.addFavorite(walletAddress, favorite);\n },\n onMutate: async (favorite: CreateFavoriteRequest) => {\n if (!walletAddress) return;\n // Optimistic update\n addFavoriteOptimistic(walletAddress, favorite);\n return { favorite };\n },\n onSuccess: (response, _favorite) => {\n if (!walletAddress || !response.data) return;\n // Update with server response (real ID)\n updateFavoriteFromServer(walletAddress, response.data);\n },\n onError: (_error, favorite) => {\n if (!walletAddress) return;\n // Rollback optimistic update\n rollbackAdd(walletAddress, favorite.id);\n },\n });\n\n // Mutation for removing a favorite with optimistic update\n const removeFavorite = useMutation({\n mutationFn: async (favoriteId: number) => {\n if (!walletAddress) {\n throw new Error('Wallet address is required to remove favorites');\n }\n return await client.removeFavorite(walletAddress, favoriteId);\n },\n onMutate: async (favoriteId: number) => {\n if (!walletAddress) return;\n // Save favorite for potential rollback\n const favorite = findFavorite(\n walletAddress,\n storedFavorites.find(f => f.id === favoriteId)?.itemId ?? ''\n );\n // Optimistic update\n removeFavoriteOptimistic(walletAddress, favoriteId);\n return { favorite };\n },\n onError: (_error, _favoriteId, context) => {\n if (!walletAddress || !context?.favorite) return;\n // Rollback optimistic update\n rollbackRemove(walletAddress, context.favorite);\n },\n });\n\n return {\n // Use filtered favorites from store for immediate UI updates\n favorites: filteredFavorites,\n query,\n isLoading: query.isLoading && storedFavorites.length === 0,\n isError: query.isError,\n error: query.error,\n addFavorite,\n removeFavorite,\n refresh,\n };\n}\n\n/**\n * Get favorites for a specific category\n *\n * @example\n * ```tsx\n * const { favorites, addFavorite, removeFavorite } = useCategoryFavorites(\n * client,\n * '0x123...',\n * 'sports'\n * );\n * ```\n */\nexport function useCategoryFavorites(\n client: IndexerClient,\n walletAddress: string | undefined,\n category: string,\n options?: Omit<UseQueryOptions<PaginatedResponse<WalletFavoriteData>>, 'queryKey' | 'queryFn'>\n) {\n return useFavorites(client, walletAddress, { category }, options);\n}\n\n/**\n * Check if an item is favorited\n * Uses Zustand store for immediate response\n *\n * @example\n * ```tsx\n * const { isFavorite, toggleFavorite } = useIsFavorite(\n * client,\n * '0x123...',\n * { category: 'sports', subcategory: 'soccer', type: 'team', id: 'team-123' }\n * );\n * ```\n */\nexport function useIsFavorite(\n client: IndexerClient,\n walletAddress: string | undefined,\n item: CreateFavoriteRequest\n): {\n isFavorite: boolean;\n favoriteId: number | undefined;\n isLoading: boolean;\n toggleFavorite: () => Promise<void>;\n} {\n const { isFavorite: checkIsFavorite, findFavorite } = useFavoritesStore();\n\n // Use store directly for immediate response\n const isFavorited = walletAddress ? checkIsFavorite(walletAddress, item.id) : false;\n const existingFavorite = walletAddress ? findFavorite(walletAddress, item.id) : undefined;\n\n const { addFavorite, removeFavorite, isLoading } = useFavorites(client, walletAddress, {\n category: item.category,\n subcategory: item.subcategory,\n type: item.type,\n });\n\n const toggleFavorite = useCallback(async () => {\n if (existingFavorite) {\n await removeFavorite.mutateAsync(existingFavorite.id);\n } else {\n await addFavorite.mutateAsync(item);\n }\n }, [existingFavorite, addFavorite, removeFavorite, item]);\n\n return {\n isFavorite: isFavorited,\n favoriteId: existingFavorite?.id,\n isLoading: isLoading || addFavorite.isPending || removeFavorite.isPending,\n toggleFavorite,\n };\n}\n\n/**\n * Hook to access the favorites store directly\n * Useful for reading favorites without API calls\n *\n * @example\n * ```tsx\n * const { getFavorites, isFavorite, clearAll } = useFavoritesStoreHook();\n * const favorites = getFavorites('0x123...');\n * ```\n */\nexport function useFavoritesStoreHook() {\n return useFavoritesStore();\n}\n\nconst FIVE_MINUTES = 5 * 60 * 1000;\n\n/**\n * Hook to get favorite counts across all wallets for specific items.\n * Useful for dealers to see how popular an entity is.\n *\n * @example\n * ```tsx\n * const { counts, isLoading } = useFavoriteCounts(client, 'sports', 'soccer', 'team', ['1', '2', '3']);\n * // counts['1'] === 5, counts['2'] === 12\n * ```\n */\nexport function useFavoriteCounts(\n client: IndexerClient,\n category: string,\n subcategory: string,\n type: string,\n itemIds: string[]\n): {\n counts: Record<string, number>;\n isLoading: boolean;\n} {\n const enabled = itemIds.length > 0;\n\n const query = useQuery({\n queryKey: ['heavymath', 'favoriteCounts', category, subcategory, type],\n queryFn: () => client.getFavoriteCounts({ category, subcategory, type }),\n enabled,\n staleTime: FIVE_MINUTES,\n });\n\n const counts = query.data?.data ?? {};\n\n return {\n counts,\n isLoading: query.isLoading,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"IndexerClient.d.ts","sourceRoot":"","sources":["../../src/network/IndexerClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"IndexerClient.d.ts","sourceRoot":"","sources":["../../src/network/IndexerClient.ts"],"names":[],"mappings":"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"}
@@ -236,7 +236,9 @@ export class IndexerClient {
236
236
  params.append('category', filters.category);
237
237
  params.append('subcategory', filters.subcategory);
238
238
  params.append('type', filters.type);
239
- params.append('itemIds', filters.itemIds.join(','));
239
+ if (filters.itemIds && filters.itemIds.length > 0) {
240
+ params.append('itemIds', filters.itemIds.join(','));
241
+ }
240
242
  const path = `/api/favorites/counts?${params.toString()}`;
241
243
  const response = await this.networkClient.get(buildUrl(this.baseUrl, path));
242
244
  if (!response.ok || !response.data) {
@@ -1 +1 @@
1
- {"version":3,"file":"IndexerClient.js","sourceRoot":"","sources":["../../src/network/IndexerClient.ts"],"names":[],"mappings":"AA4CA,SAAS,QAAQ,CAAC,OAAe,EAAE,IAAY;IAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;IAC1D,OAAO,GAAG,IAAI,GAAG,QAAQ,EAAE,CAAC;AAC9B,CAAC;AAWD,SAAS,cAAc,CACrB,QAAkC,EAClC,SAAiB,EACjB,GAAY;IAEZ,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAsC,CAAC;IAC7D,MAAM,YAAY,GAAG,IAAI,EAAE,KAAK,IAAI,QAAQ,CAAC,UAAU,IAAI,aAAa,SAAS,EAAE,CAAC;IACpF,MAAM,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACzC,OAAO,IAAI,KAAK,CAAC,cAAc,QAAQ,CAAC,MAAM,MAAM,YAAY,GAAG,SAAS,EAAE,CAAC,CAAC;AAClF,CAAC;AAOD,MAAM,OAAO,aAAa;IASxB,YAAY,WAAmB,EAAE,aAA4B;QAC3D,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAcD,KAAK,CAAC,UAAU,CAAC,OAAuB;QACtC,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAErC,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,OAAO,EAAE,QAAQ;YAAE,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnE,IAAI,OAAO,EAAE,KAAK;YAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrE,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAExE,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,oBAAoB,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAExE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAC7B,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAChD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAUD,KAAK,CAAC,SAAS,CAAC,EAAU;QACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CACjE,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAUD,KAAK,CAAC,oBAAoB,CAAC,QAAgB;QACzC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,kBAAkB,CAAC,QAAQ,CAAC,cAAc,CAAC,CACnF,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAUD,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QACrC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC/E,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAcD,KAAK,CAAC,cAAc,CAAC,OAA2B;QAC9C,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAErC,IAAI,OAAO,EAAE,IAAI;YAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,OAAO,EAAE,OAAO,KAAK,SAAS;YAAE,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzF,IAAI,OAAO,EAAE,KAAK;YAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrE,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAExE,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,mBAAmB,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAEvE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAC7B,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAUD,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CACrE,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAcD,KAAK,CAAC,UAAU,CAAC,OAAuB;QACtC,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAErC,IAAI,OAAO,EAAE,KAAK;YAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1D,IAAI,OAAO,EAAE,KAAK;YAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrE,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAExE,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,oBAAoB,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAExE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAC7B,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAChD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAUD,KAAK,CAAC,SAAS,CAAC,EAAU;QACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CACjE,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAUD,KAAK,CAAC,oBAAoB,CAAC,QAAgB;QACzC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,kBAAkB,CAAC,QAAQ,CAAC,cAAc,CAAC,CACnF,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAUD,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QACrC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC/E,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAcD,KAAK,CAAC,cAAc,CAAC,OAA2B;QAC9C,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAErC,IAAI,OAAO,EAAE,UAAU;YAAE,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QACzE,IAAI,OAAO,EAAE,IAAI;YAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,OAAO,EAAE,KAAK;YAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrE,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAExE,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,mBAAmB,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAEvE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAC7B,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAcD,KAAK,CAAC,iBAAiB,CAAC,OAAuB;QAC7C,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAErC,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,OAAO,EAAE,QAAQ,KAAK,SAAS;YAAE,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC5F,IAAI,OAAO,EAAE,KAAK;YAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrE,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAExE,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,uBAAuB,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAE3E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAC7B,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAUD,KAAK,CAAC,gBAAgB,CAAC,EAAU;QAC/B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,wBAAwB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CACzE,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAiBD,KAAK,CAAC,qBAAqB,CACzB,QAAgB,EAChB,MAAoC;QAEpC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAC5C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,kBAAkB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EACpF,MAAM,CACP,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,0BAA0B,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAUD,KAAK,CAAC,qBAAqB,CAAC,QAAgB;QAC1C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,kBAAkB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CACrF,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,0BAA0B,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAeD,KAAK,CAAC,qBAAqB,CAAC,QAAgB;QAC1C,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAE3F,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAE3C,GAAG,CAAC,CAAC;QAEP,IAAI,QAAQ,CAAC,EAAE,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YACjC,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,QAAQ,CAAC,IAAoC;aACpD,CAAC;QACJ,CAAC;QAGD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAA8C,CAAC;QAC1E,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,SAAS,IAAI;gBAClB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,cAAc,QAAQ,CAAC,MAAM,sCAAsC;gBAC1E,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC;SACF,CAAC;IACJ,CAAC;IAeD,KAAK,CAAC,YAAY,CAChB,aAAqB,EACrB,OAAgC;QAEhC,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAErC,IAAI,OAAO,EAAE,QAAQ;YAAE,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnE,IAAI,OAAO,EAAE,WAAW;YAAE,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QAC5E,IAAI,OAAO,EAAE,IAAI;YAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,OAAO,EAAE,KAAK;YAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrE,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAExE,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,eAAe,kBAAkB,CAAC,aAAa,CAAC,aAAa,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAEjH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAC7B,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QAClD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAWD,KAAK,CAAC,WAAW,CACf,aAAqB,EACrB,QAA+B;QAE/B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAC5C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,kBAAkB,CAAC,aAAa,CAAC,YAAY,CAAC,EACpF,QAAQ,CACT,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAWD,KAAK,CAAC,cAAc,CAAC,aAAqB,EAAE,UAAkB;QAC5D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAC9C,QAAQ,CACN,IAAI,CAAC,OAAO,EACZ,eAAe,kBAAkB,CAAC,aAAa,CAAC,cAAc,UAAU,EAAE,CAC3E,CACF,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IASD,KAAK,CAAC,iBAAiB,CACrB,OAA8B;QAE9B,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAEpD,MAAM,IAAI,GAAG,yBAAyB,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAE1D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAC7B,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAaD,KAAK,CAAC,cAAc;QAClB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAC7C,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IASD,KAAK,CAAC,SAAS;QACb,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CACtC,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAeD,KAAK,CAAC,YAAY,CAAC,KAAa;QAC9B,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAE1B,MAAM,IAAI,GAAG,sBAAsB,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAEvD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAC7B,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QAClD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAmBD,KAAK,CAAC,aAAa,CACjB,KAAa,EACb,QAAgB,EAChB,MAA0B;QAE1B,MAAM,YAAY,GAAG,IAAI,eAAe,EAAE,CAAC;QAC3C,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;oBAC1C,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,eAAe,kBAAkB,CAAC,KAAK,CAAC,GAAG,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAE1G,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAC7B,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,cAAc,CAAC,QAAQ,EAAE,oBAAoB,KAAK,GAAG,QAAQ,GAAG,CAAC,CAAC;QAC1E,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;CACF","sourcesContent":["/**\n * @fileoverview Indexer API Client\n * @description Low-level HTTP client for all Heavymath Indexer REST endpoints.\n * Each public method maps 1:1 to a REST API endpoint. Uses an injected\n * NetworkClient for transport, making it environment-agnostic (browser, Node, React Native).\n */\n\nimport type { NetworkClient, NetworkResponse } from '@sudobility/types';\nimport type {\n ApiResponse,\n PaginatedResponse,\n MarketData,\n PredictionData,\n DealerNftData,\n DealerPermissionData,\n MarketStateHistoryData,\n FeeWithdrawalData,\n OracleRequestData,\n MarketStatsData,\n HealthData,\n MarketFilters,\n PredictionFilters,\n DealerFilters,\n WithdrawalFilters,\n OracleFilters,\n WalletFavoriteData,\n WalletFavoritesFilters,\n CreateFavoriteRequest,\n FavoriteCountsFilters,\n SetMarketOracleConfigRequest,\n MarketOracleConfigData,\n MarketResolutionCheck,\n MarketResolutionCheckSuccess,\n MarketResolutionCheckError,\n} from '../types';\nimport type { SportsApiResponse, SportsQueryParams, SportsSearchResponse } from '../types/sports';\n\n/**\n * Build a full URL by joining a base URL and path.\n *\n * @param baseUrl - The base URL (trailing slash is stripped)\n * @param path - The path to append (leading slash is ensured)\n * @returns The combined URL string\n */\nfunction buildUrl(baseUrl: string, path: string): string {\n const base = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n const fullPath = path.startsWith('/') ? path : `/${path}`;\n return `${base}${fullPath}`;\n}\n\n/**\n * Create a standardized Error from an API response failure.\n * Includes the HTTP status code, endpoint URL, and error details for easier debugging.\n *\n * @param response - The failed network response\n * @param operation - A description of the operation that failed (used in error message)\n * @param url - Optional request URL to include in the error message for debugging\n * @returns An Error with a formatted message including the HTTP status code\n */\nfunction handleApiError(\n response: NetworkResponse<unknown>,\n operation: string,\n url?: string\n): Error {\n const data = response.data as { error?: string } | undefined;\n const errorMessage = data?.error || response.statusText || `Failed to ${operation}`;\n const urlSuffix = url ? ` [${url}]` : '';\n return new Error(`API Error (${response.status}): ${errorMessage}${urlSuffix}`);\n}\n\n/**\n * Indexer API client for Heavymath Prediction Market.\n * Provides type-safe methods for all REST endpoints exposed by the heavymath_indexer.\n * Requires a `NetworkClient` instance (from `@sudobility/di`) for HTTP transport.\n */\nexport class IndexerClient {\n private readonly baseUrl: string;\n private readonly networkClient: NetworkClient;\n\n /**\n * Create an IndexerClient instance\n * @param endpointUrl - The base URL for the indexer API\n * @param networkClient - A NetworkClient instance from @sudobility/di\n */\n constructor(endpointUrl: string, networkClient: NetworkClient) {\n this.baseUrl = endpointUrl;\n this.networkClient = networkClient;\n }\n\n // =============================================================================\n // MARKET ENDPOINTS\n // =============================================================================\n\n /**\n * Get all markets with optional filtering.\n * GET /api/markets\n *\n * @param filters - Optional query parameters (status, dealer, category, limit, offset)\n * @returns Paginated list of markets\n * @throws Error if the API request fails\n */\n async getMarkets(filters?: MarketFilters): Promise<PaginatedResponse<MarketData>> {\n const params = new URLSearchParams();\n\n if (filters?.status) params.append('status', filters.status);\n if (filters?.dealer) params.append('dealer', filters.dealer);\n if (filters?.category) params.append('category', filters.category);\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/markets/list${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<MarketData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get markets');\n }\n\n return response.data;\n }\n\n /**\n * Get a specific market by ID.\n * GET /api/markets/:id\n *\n * @param id - The chain-prefixed market ID (e.g., \"1-market-123\")\n * @returns The market data wrapped in an API response\n * @throws Error if the market is not found or the request fails\n */\n async getMarket(id: string): Promise<ApiResponse<MarketData>> {\n const response = await this.networkClient.get<ApiResponse<MarketData>>(\n buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(id)}`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get market');\n }\n\n return response.data;\n }\n\n /**\n * Get all predictions for a specific market.\n * GET /api/markets/:id/predictions\n *\n * @param marketId - The chain-prefixed market ID\n * @returns Array of predictions for the market\n * @throws Error if the request fails\n */\n async getMarketPredictions(marketId: string): Promise<ApiResponse<PredictionData[]>> {\n const response = await this.networkClient.get<ApiResponse<PredictionData[]>>(\n buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(marketId)}/predictions`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get market predictions');\n }\n\n return response.data;\n }\n\n /**\n * Get state transition history for a market.\n * GET /api/markets/:id/history\n *\n * @param marketId - The chain-prefixed market ID\n * @returns Array of state history entries for the market\n * @throws Error if the request fails\n */\n async getMarketHistory(marketId: string): Promise<ApiResponse<MarketStateHistoryData[]>> {\n const response = await this.networkClient.get<ApiResponse<MarketStateHistoryData[]>>(\n buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(marketId)}/history`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get market history');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // PREDICTION ENDPOINTS\n // =============================================================================\n\n /**\n * Get predictions with optional filtering.\n * GET /api/predictions\n *\n * @param filters - Optional query parameters (user, market, claimed, limit, offset)\n * @returns Paginated list of predictions\n * @throws Error if the request fails\n */\n async getPredictions(filters?: PredictionFilters): Promise<PaginatedResponse<PredictionData>> {\n const params = new URLSearchParams();\n\n if (filters?.user) params.append('user', filters.user);\n if (filters?.market) params.append('market', filters.market);\n if (filters?.claimed !== undefined) params.append('claimed', filters.claimed.toString());\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/predictions${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<PredictionData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get predictions');\n }\n\n return response.data;\n }\n\n /**\n * Get a specific prediction by ID.\n * GET /api/predictions/:id\n *\n * @param id - The chain-prefixed prediction ID (e.g., \"1-market-123-0xuser...\")\n * @returns The prediction data wrapped in an API response\n * @throws Error if the prediction is not found or the request fails\n */\n async getPrediction(id: string): Promise<ApiResponse<PredictionData>> {\n const response = await this.networkClient.get<ApiResponse<PredictionData>>(\n buildUrl(this.baseUrl, `/api/predictions/${encodeURIComponent(id)}`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get prediction');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // DEALER NFT ENDPOINTS\n // =============================================================================\n\n /**\n * Get all dealer NFTs with optional filtering.\n * GET /api/dealers\n *\n * @param filters - Optional query parameters (owner, limit, offset)\n * @returns Paginated list of dealer NFTs\n * @throws Error if the request fails\n */\n async getDealers(filters?: DealerFilters): Promise<PaginatedResponse<DealerNftData>> {\n const params = new URLSearchParams();\n\n if (filters?.owner) params.append('owner', filters.owner);\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/dealers/list${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<DealerNftData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get dealers');\n }\n\n return response.data;\n }\n\n /**\n * Get a specific dealer NFT by ID.\n * GET /api/dealers/:id\n *\n * @param id - The chain-prefixed dealer ID (e.g., \"1-1\")\n * @returns The dealer NFT data wrapped in an API response\n * @throws Error if the dealer is not found or the request fails\n */\n async getDealer(id: string): Promise<ApiResponse<DealerNftData>> {\n const response = await this.networkClient.get<ApiResponse<DealerNftData>>(\n buildUrl(this.baseUrl, `/api/dealers/${encodeURIComponent(id)}`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get dealer');\n }\n\n return response.data;\n }\n\n /**\n * Get permissions for a specific dealer NFT.\n * GET /api/dealers/:id/permissions\n *\n * @param dealerId - The chain-prefixed dealer ID\n * @returns Array of permission entries for the dealer\n * @throws Error if the request fails\n */\n async getDealerPermissions(dealerId: string): Promise<ApiResponse<DealerPermissionData[]>> {\n const response = await this.networkClient.get<ApiResponse<DealerPermissionData[]>>(\n buildUrl(this.baseUrl, `/api/dealers/${encodeURIComponent(dealerId)}/permissions`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get dealer permissions');\n }\n\n return response.data;\n }\n\n /**\n * Get all markets created by a specific dealer NFT.\n * GET /api/dealers/:id/markets\n *\n * @param dealerId - The chain-prefixed dealer ID\n * @returns Array of markets created by this dealer\n * @throws Error if the request fails\n */\n async getDealerMarkets(dealerId: string): Promise<ApiResponse<MarketData[]>> {\n const response = await this.networkClient.get<ApiResponse<MarketData[]>>(\n buildUrl(this.baseUrl, `/api/dealers/${encodeURIComponent(dealerId)}/markets`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get dealer markets');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // FEE WITHDRAWAL ENDPOINTS\n // =============================================================================\n\n /**\n * Get fee withdrawals with optional filtering.\n * GET /api/withdrawals\n *\n * @param filters - Optional query parameters (withdrawer, type, market, limit, offset)\n * @returns Paginated list of fee withdrawals\n * @throws Error if the request fails\n */\n async getWithdrawals(filters?: WithdrawalFilters): Promise<PaginatedResponse<FeeWithdrawalData>> {\n const params = new URLSearchParams();\n\n if (filters?.withdrawer) params.append('withdrawer', filters.withdrawer);\n if (filters?.type) params.append('type', filters.type);\n if (filters?.market) params.append('market', filters.market);\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/withdrawals${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<FeeWithdrawalData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get withdrawals');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // ORACLE REQUEST ENDPOINTS\n // =============================================================================\n\n /**\n * Get oracle requests with optional filtering.\n * GET /api/oracle/requests\n *\n * @param filters - Optional query parameters (market, timedOut, limit, offset)\n * @returns Paginated list of oracle requests\n * @throws Error if the request fails\n */\n async getOracleRequests(filters?: OracleFilters): Promise<PaginatedResponse<OracleRequestData>> {\n const params = new URLSearchParams();\n\n if (filters?.market) params.append('market', filters.market);\n if (filters?.timedOut !== undefined) params.append('timedOut', filters.timedOut.toString());\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/oracle/requests${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<OracleRequestData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get oracle requests');\n }\n\n return response.data;\n }\n\n /**\n * Get a specific oracle request by ID.\n * GET /api/oracle/requests/:id\n *\n * @param id - The oracle request ID\n * @returns The oracle request data wrapped in an API response\n * @throws Error if the oracle request is not found or the request fails\n */\n async getOracleRequest(id: string): Promise<ApiResponse<OracleRequestData>> {\n const response = await this.networkClient.get<ApiResponse<OracleRequestData>>(\n buildUrl(this.baseUrl, `/api/oracle/requests/${encodeURIComponent(id)}`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get oracle request');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // ORACLE RESOLUTION ENDPOINTS\n // =============================================================================\n\n /**\n * Set the oracle resolution config for a market.\n * POST /api/markets/:id/oracle-config\n *\n * Called after on-chain market creation to store which team's win = positive outcome.\n *\n * @param marketId - Chain-prefixed market ID\n * @param config - Oracle config with positive team info\n * @returns The created oracle config\n * @throws Error if the market is not found or doesn't have an oracle\n */\n async setMarketOracleConfig(\n marketId: string,\n config: SetMarketOracleConfigRequest\n ): Promise<ApiResponse<MarketOracleConfigData>> {\n const response = await this.networkClient.post<ApiResponse<MarketOracleConfigData>>(\n buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(marketId)}/oracle-config`),\n config\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'set market oracle config');\n }\n\n return response.data;\n }\n\n /**\n * Get the oracle resolution config for a market.\n * GET /api/markets/:id/oracle-config\n *\n * @param marketId - Chain-prefixed market ID\n * @returns The oracle config data\n * @throws Error if the config is not found\n */\n async getMarketOracleConfig(marketId: string): Promise<ApiResponse<MarketOracleConfigData>> {\n const response = await this.networkClient.get<ApiResponse<MarketOracleConfigData>>(\n buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(marketId)}/oracle-config`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get market oracle config');\n }\n\n return response.data;\n }\n\n /**\n * Check if a market can be resolved via oracle.\n * GET /api/markets/:id/resolve\n *\n * Returns the resolution result if the game has ended (HTTP 200),\n * or an error if the game hasn't ended yet (HTTP 400).\n *\n * Unlike other methods, this does NOT throw on 400 — it returns a\n * structured result so the UI can display the reason.\n *\n * @param marketId - Chain-prefixed market ID\n * @returns Resolution check result (ok: true with data, or ok: false with error)\n */\n async checkMarketResolution(marketId: string): Promise<MarketResolutionCheck> {\n const url = buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(marketId)}/resolve`);\n\n const response = await this.networkClient.get<\n MarketResolutionCheckSuccess | MarketResolutionCheckError\n >(url);\n\n if (response.ok && response.data) {\n return {\n ok: true,\n data: response.data as MarketResolutionCheckSuccess,\n };\n }\n\n // 400 or other error — return structured error instead of throwing\n const errorData = response.data as MarketResolutionCheckError | undefined;\n return {\n ok: false,\n error: errorData ?? {\n success: false,\n error: `API Error (${response.status}): Failed to check market resolution`,\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n // =============================================================================\n // WALLET FAVORITES ENDPOINTS\n // =============================================================================\n\n /**\n * Get favorites for a wallet address.\n * GET /api/wallet/:address/favorites\n *\n * @param walletAddress - The wallet address to get favorites for\n * @param filters - Optional query parameters (category, subcategory, type, limit, offset)\n * @returns Paginated list of wallet favorites\n * @throws Error if the request fails\n */\n async getFavorites(\n walletAddress: string,\n filters?: WalletFavoritesFilters\n ): Promise<PaginatedResponse<WalletFavoriteData>> {\n const params = new URLSearchParams();\n\n if (filters?.category) params.append('category', filters.category);\n if (filters?.subcategory) params.append('subcategory', filters.subcategory);\n if (filters?.type) params.append('type', filters.type);\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/wallet/${encodeURIComponent(walletAddress)}/favorites${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<WalletFavoriteData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get favorites');\n }\n\n return response.data;\n }\n\n /**\n * Add a favorite for a wallet address.\n * POST /api/wallet/:address/favorites\n *\n * @param walletAddress - The wallet address to add a favorite for\n * @param favorite - The favorite item to add (category, subcategory, type, id)\n * @returns The newly created favorite data\n * @throws Error if the request fails\n */\n async addFavorite(\n walletAddress: string,\n favorite: CreateFavoriteRequest\n ): Promise<ApiResponse<WalletFavoriteData>> {\n const response = await this.networkClient.post<ApiResponse<WalletFavoriteData>>(\n buildUrl(this.baseUrl, `/api/wallet/${encodeURIComponent(walletAddress)}/favorites`),\n favorite\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'add favorite');\n }\n\n return response.data;\n }\n\n /**\n * Remove a favorite by ID.\n * DELETE /api/wallet/:address/favorites/:id\n *\n * @param walletAddress - The wallet address that owns the favorite\n * @param favoriteId - The numeric ID of the favorite to remove\n * @returns An API response confirming deletion\n * @throws Error if the favorite is not found or the request fails\n */\n async removeFavorite(walletAddress: string, favoriteId: number): Promise<ApiResponse<void>> {\n const response = await this.networkClient.delete<ApiResponse<void>>(\n buildUrl(\n this.baseUrl,\n `/api/wallet/${encodeURIComponent(walletAddress)}/favorites/${favoriteId}`\n )\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'remove favorite');\n }\n\n return response.data;\n }\n\n /**\n * Get favorite counts across all wallets for specific items.\n * GET /api/favorites/counts\n *\n * @param filters - Required filters: category, subcategory, type, itemIds\n * @returns Map of itemId to favorite count (items with 0 favorites are omitted)\n */\n async getFavoriteCounts(\n filters: FavoriteCountsFilters\n ): Promise<ApiResponse<Record<string, number>>> {\n const params = new URLSearchParams();\n params.append('category', filters.category);\n params.append('subcategory', filters.subcategory);\n params.append('type', filters.type);\n params.append('itemIds', filters.itemIds.join(','));\n\n const path = `/api/favorites/counts?${params.toString()}`;\n\n const response = await this.networkClient.get<ApiResponse<Record<string, number>>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get favorite counts');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // ANALYTICS ENDPOINTS\n // =============================================================================\n\n /**\n * Get market statistics.\n * GET /api/stats/markets\n *\n * @returns Aggregate market statistics (totals, breakdowns by status)\n * @throws Error if the request fails\n */\n async getMarketStats(): Promise<ApiResponse<MarketStatsData>> {\n const response = await this.networkClient.get<ApiResponse<MarketStatsData>>(\n buildUrl(this.baseUrl, '/api/stats/markets')\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get market stats');\n }\n\n return response.data;\n }\n\n /**\n * Get health status of the indexer.\n * GET /api/health\n *\n * @returns The indexer health status\n * @throws Error if the request fails\n */\n async getHealth(): Promise<ApiResponse<HealthData>> {\n const response = await this.networkClient.get<ApiResponse<HealthData>>(\n buildUrl(this.baseUrl, '/api/health')\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get health');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // SPORTS API PROXY ENDPOINTS\n // =============================================================================\n\n /**\n * Cross-sport team search.\n * Searches teams across all sports via the indexer's aggregated search endpoint.\n * GET /api/sports/search?q={query}\n *\n * @param query - Search query (minimum 3 characters)\n * @returns Aggregated search results grouped by sport\n * @throws Error if the request fails\n */\n async searchSports(query: string): Promise<ApiResponse<SportsSearchResponse>> {\n const params = new URLSearchParams();\n params.append('q', query);\n\n const path = `/api/sports/search?${params.toString()}`;\n\n const response = await this.networkClient.get<ApiResponse<SportsSearchResponse>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'search sports');\n }\n\n return response.data;\n }\n\n /**\n * Generic sports API proxy call.\n * Proxies any api-sports.io request through the indexer with server-side caching.\n * Returns the raw api-sports.io response body (passthrough format).\n *\n * @param sport - Sport identifier (e.g., 'football', 'basketball')\n * @param endpoint - API endpoint path (e.g., '/countries', '/fixtures')\n * @param params - Optional query parameters to forward\n * @returns The raw api-sports.io response\n * @throws Error if the request fails\n *\n * @example\n * ```ts\n * const data = await client.getSportsData('football', '/countries');\n * const leagues = await client.getSportsData('basketball', '/leagues', { season: '2023-2024' });\n * ```\n */\n async getSportsData<T = unknown>(\n sport: string,\n endpoint: string,\n params?: SportsQueryParams\n ): Promise<SportsApiResponse<T>> {\n const searchParams = new URLSearchParams();\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n }\n }\n\n const queryString = searchParams.toString();\n const path = `/api/sports/${encodeURIComponent(sport)}${endpoint}${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<SportsApiResponse<T>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, `get sports data (${sport}${endpoint})`);\n }\n\n return response.data;\n }\n}\n"]}
1
+ {"version":3,"file":"IndexerClient.js","sourceRoot":"","sources":["../../src/network/IndexerClient.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Indexer API Client\n * @description Low-level HTTP client for all Heavymath Indexer REST endpoints.\n * Each public method maps 1:1 to a REST API endpoint. Uses an injected\n * NetworkClient for transport, making it environment-agnostic (browser, Node, React Native).\n */\n\nimport type { NetworkClient, NetworkResponse } from '@sudobility/types';\nimport type {\n ApiResponse,\n PaginatedResponse,\n MarketData,\n PredictionData,\n DealerNftData,\n DealerPermissionData,\n MarketStateHistoryData,\n FeeWithdrawalData,\n OracleRequestData,\n MarketStatsData,\n HealthData,\n MarketFilters,\n PredictionFilters,\n DealerFilters,\n WithdrawalFilters,\n OracleFilters,\n WalletFavoriteData,\n WalletFavoritesFilters,\n CreateFavoriteRequest,\n FavoriteCountsFilters,\n SetMarketOracleConfigRequest,\n MarketOracleConfigData,\n MarketResolutionCheck,\n MarketResolutionCheckSuccess,\n MarketResolutionCheckError,\n} from '../types';\nimport type { SportsApiResponse, SportsQueryParams, SportsSearchResponse } from '../types/sports';\n\n/**\n * Build a full URL by joining a base URL and path.\n *\n * @param baseUrl - The base URL (trailing slash is stripped)\n * @param path - The path to append (leading slash is ensured)\n * @returns The combined URL string\n */\nfunction buildUrl(baseUrl: string, path: string): string {\n const base = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n const fullPath = path.startsWith('/') ? path : `/${path}`;\n return `${base}${fullPath}`;\n}\n\n/**\n * Create a standardized Error from an API response failure.\n * Includes the HTTP status code, endpoint URL, and error details for easier debugging.\n *\n * @param response - The failed network response\n * @param operation - A description of the operation that failed (used in error message)\n * @param url - Optional request URL to include in the error message for debugging\n * @returns An Error with a formatted message including the HTTP status code\n */\nfunction handleApiError(\n response: NetworkResponse<unknown>,\n operation: string,\n url?: string\n): Error {\n const data = response.data as { error?: string } | undefined;\n const errorMessage = data?.error || response.statusText || `Failed to ${operation}`;\n const urlSuffix = url ? ` [${url}]` : '';\n return new Error(`API Error (${response.status}): ${errorMessage}${urlSuffix}`);\n}\n\n/**\n * Indexer API client for Heavymath Prediction Market.\n * Provides type-safe methods for all REST endpoints exposed by the heavymath_indexer.\n * Requires a `NetworkClient` instance (from `@sudobility/di`) for HTTP transport.\n */\nexport class IndexerClient {\n private readonly baseUrl: string;\n private readonly networkClient: NetworkClient;\n\n /**\n * Create an IndexerClient instance\n * @param endpointUrl - The base URL for the indexer API\n * @param networkClient - A NetworkClient instance from @sudobility/di\n */\n constructor(endpointUrl: string, networkClient: NetworkClient) {\n this.baseUrl = endpointUrl;\n this.networkClient = networkClient;\n }\n\n // =============================================================================\n // MARKET ENDPOINTS\n // =============================================================================\n\n /**\n * Get all markets with optional filtering.\n * GET /api/markets\n *\n * @param filters - Optional query parameters (status, dealer, category, limit, offset)\n * @returns Paginated list of markets\n * @throws Error if the API request fails\n */\n async getMarkets(filters?: MarketFilters): Promise<PaginatedResponse<MarketData>> {\n const params = new URLSearchParams();\n\n if (filters?.status) params.append('status', filters.status);\n if (filters?.dealer) params.append('dealer', filters.dealer);\n if (filters?.category) params.append('category', filters.category);\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/markets/list${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<MarketData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get markets');\n }\n\n return response.data;\n }\n\n /**\n * Get a specific market by ID.\n * GET /api/markets/:id\n *\n * @param id - The chain-prefixed market ID (e.g., \"1-market-123\")\n * @returns The market data wrapped in an API response\n * @throws Error if the market is not found or the request fails\n */\n async getMarket(id: string): Promise<ApiResponse<MarketData>> {\n const response = await this.networkClient.get<ApiResponse<MarketData>>(\n buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(id)}`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get market');\n }\n\n return response.data;\n }\n\n /**\n * Get all predictions for a specific market.\n * GET /api/markets/:id/predictions\n *\n * @param marketId - The chain-prefixed market ID\n * @returns Array of predictions for the market\n * @throws Error if the request fails\n */\n async getMarketPredictions(marketId: string): Promise<ApiResponse<PredictionData[]>> {\n const response = await this.networkClient.get<ApiResponse<PredictionData[]>>(\n buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(marketId)}/predictions`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get market predictions');\n }\n\n return response.data;\n }\n\n /**\n * Get state transition history for a market.\n * GET /api/markets/:id/history\n *\n * @param marketId - The chain-prefixed market ID\n * @returns Array of state history entries for the market\n * @throws Error if the request fails\n */\n async getMarketHistory(marketId: string): Promise<ApiResponse<MarketStateHistoryData[]>> {\n const response = await this.networkClient.get<ApiResponse<MarketStateHistoryData[]>>(\n buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(marketId)}/history`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get market history');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // PREDICTION ENDPOINTS\n // =============================================================================\n\n /**\n * Get predictions with optional filtering.\n * GET /api/predictions\n *\n * @param filters - Optional query parameters (user, market, claimed, limit, offset)\n * @returns Paginated list of predictions\n * @throws Error if the request fails\n */\n async getPredictions(filters?: PredictionFilters): Promise<PaginatedResponse<PredictionData>> {\n const params = new URLSearchParams();\n\n if (filters?.user) params.append('user', filters.user);\n if (filters?.market) params.append('market', filters.market);\n if (filters?.claimed !== undefined) params.append('claimed', filters.claimed.toString());\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/predictions${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<PredictionData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get predictions');\n }\n\n return response.data;\n }\n\n /**\n * Get a specific prediction by ID.\n * GET /api/predictions/:id\n *\n * @param id - The chain-prefixed prediction ID (e.g., \"1-market-123-0xuser...\")\n * @returns The prediction data wrapped in an API response\n * @throws Error if the prediction is not found or the request fails\n */\n async getPrediction(id: string): Promise<ApiResponse<PredictionData>> {\n const response = await this.networkClient.get<ApiResponse<PredictionData>>(\n buildUrl(this.baseUrl, `/api/predictions/${encodeURIComponent(id)}`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get prediction');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // DEALER NFT ENDPOINTS\n // =============================================================================\n\n /**\n * Get all dealer NFTs with optional filtering.\n * GET /api/dealers\n *\n * @param filters - Optional query parameters (owner, limit, offset)\n * @returns Paginated list of dealer NFTs\n * @throws Error if the request fails\n */\n async getDealers(filters?: DealerFilters): Promise<PaginatedResponse<DealerNftData>> {\n const params = new URLSearchParams();\n\n if (filters?.owner) params.append('owner', filters.owner);\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/dealers/list${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<DealerNftData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get dealers');\n }\n\n return response.data;\n }\n\n /**\n * Get a specific dealer NFT by ID.\n * GET /api/dealers/:id\n *\n * @param id - The chain-prefixed dealer ID (e.g., \"1-1\")\n * @returns The dealer NFT data wrapped in an API response\n * @throws Error if the dealer is not found or the request fails\n */\n async getDealer(id: string): Promise<ApiResponse<DealerNftData>> {\n const response = await this.networkClient.get<ApiResponse<DealerNftData>>(\n buildUrl(this.baseUrl, `/api/dealers/${encodeURIComponent(id)}`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get dealer');\n }\n\n return response.data;\n }\n\n /**\n * Get permissions for a specific dealer NFT.\n * GET /api/dealers/:id/permissions\n *\n * @param dealerId - The chain-prefixed dealer ID\n * @returns Array of permission entries for the dealer\n * @throws Error if the request fails\n */\n async getDealerPermissions(dealerId: string): Promise<ApiResponse<DealerPermissionData[]>> {\n const response = await this.networkClient.get<ApiResponse<DealerPermissionData[]>>(\n buildUrl(this.baseUrl, `/api/dealers/${encodeURIComponent(dealerId)}/permissions`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get dealer permissions');\n }\n\n return response.data;\n }\n\n /**\n * Get all markets created by a specific dealer NFT.\n * GET /api/dealers/:id/markets\n *\n * @param dealerId - The chain-prefixed dealer ID\n * @returns Array of markets created by this dealer\n * @throws Error if the request fails\n */\n async getDealerMarkets(dealerId: string): Promise<ApiResponse<MarketData[]>> {\n const response = await this.networkClient.get<ApiResponse<MarketData[]>>(\n buildUrl(this.baseUrl, `/api/dealers/${encodeURIComponent(dealerId)}/markets`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get dealer markets');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // FEE WITHDRAWAL ENDPOINTS\n // =============================================================================\n\n /**\n * Get fee withdrawals with optional filtering.\n * GET /api/withdrawals\n *\n * @param filters - Optional query parameters (withdrawer, type, market, limit, offset)\n * @returns Paginated list of fee withdrawals\n * @throws Error if the request fails\n */\n async getWithdrawals(filters?: WithdrawalFilters): Promise<PaginatedResponse<FeeWithdrawalData>> {\n const params = new URLSearchParams();\n\n if (filters?.withdrawer) params.append('withdrawer', filters.withdrawer);\n if (filters?.type) params.append('type', filters.type);\n if (filters?.market) params.append('market', filters.market);\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/withdrawals${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<FeeWithdrawalData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get withdrawals');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // ORACLE REQUEST ENDPOINTS\n // =============================================================================\n\n /**\n * Get oracle requests with optional filtering.\n * GET /api/oracle/requests\n *\n * @param filters - Optional query parameters (market, timedOut, limit, offset)\n * @returns Paginated list of oracle requests\n * @throws Error if the request fails\n */\n async getOracleRequests(filters?: OracleFilters): Promise<PaginatedResponse<OracleRequestData>> {\n const params = new URLSearchParams();\n\n if (filters?.market) params.append('market', filters.market);\n if (filters?.timedOut !== undefined) params.append('timedOut', filters.timedOut.toString());\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/oracle/requests${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<OracleRequestData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get oracle requests');\n }\n\n return response.data;\n }\n\n /**\n * Get a specific oracle request by ID.\n * GET /api/oracle/requests/:id\n *\n * @param id - The oracle request ID\n * @returns The oracle request data wrapped in an API response\n * @throws Error if the oracle request is not found or the request fails\n */\n async getOracleRequest(id: string): Promise<ApiResponse<OracleRequestData>> {\n const response = await this.networkClient.get<ApiResponse<OracleRequestData>>(\n buildUrl(this.baseUrl, `/api/oracle/requests/${encodeURIComponent(id)}`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get oracle request');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // ORACLE RESOLUTION ENDPOINTS\n // =============================================================================\n\n /**\n * Set the oracle resolution config for a market.\n * POST /api/markets/:id/oracle-config\n *\n * Called after on-chain market creation to store which team's win = positive outcome.\n *\n * @param marketId - Chain-prefixed market ID\n * @param config - Oracle config with positive team info\n * @returns The created oracle config\n * @throws Error if the market is not found or doesn't have an oracle\n */\n async setMarketOracleConfig(\n marketId: string,\n config: SetMarketOracleConfigRequest\n ): Promise<ApiResponse<MarketOracleConfigData>> {\n const response = await this.networkClient.post<ApiResponse<MarketOracleConfigData>>(\n buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(marketId)}/oracle-config`),\n config\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'set market oracle config');\n }\n\n return response.data;\n }\n\n /**\n * Get the oracle resolution config for a market.\n * GET /api/markets/:id/oracle-config\n *\n * @param marketId - Chain-prefixed market ID\n * @returns The oracle config data\n * @throws Error if the config is not found\n */\n async getMarketOracleConfig(marketId: string): Promise<ApiResponse<MarketOracleConfigData>> {\n const response = await this.networkClient.get<ApiResponse<MarketOracleConfigData>>(\n buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(marketId)}/oracle-config`)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get market oracle config');\n }\n\n return response.data;\n }\n\n /**\n * Check if a market can be resolved via oracle.\n * GET /api/markets/:id/resolve\n *\n * Returns the resolution result if the game has ended (HTTP 200),\n * or an error if the game hasn't ended yet (HTTP 400).\n *\n * Unlike other methods, this does NOT throw on 400 — it returns a\n * structured result so the UI can display the reason.\n *\n * @param marketId - Chain-prefixed market ID\n * @returns Resolution check result (ok: true with data, or ok: false with error)\n */\n async checkMarketResolution(marketId: string): Promise<MarketResolutionCheck> {\n const url = buildUrl(this.baseUrl, `/api/markets/${encodeURIComponent(marketId)}/resolve`);\n\n const response = await this.networkClient.get<\n MarketResolutionCheckSuccess | MarketResolutionCheckError\n >(url);\n\n if (response.ok && response.data) {\n return {\n ok: true,\n data: response.data as MarketResolutionCheckSuccess,\n };\n }\n\n // 400 or other error — return structured error instead of throwing\n const errorData = response.data as MarketResolutionCheckError | undefined;\n return {\n ok: false,\n error: errorData ?? {\n success: false,\n error: `API Error (${response.status}): Failed to check market resolution`,\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n // =============================================================================\n // WALLET FAVORITES ENDPOINTS\n // =============================================================================\n\n /**\n * Get favorites for a wallet address.\n * GET /api/wallet/:address/favorites\n *\n * @param walletAddress - The wallet address to get favorites for\n * @param filters - Optional query parameters (category, subcategory, type, limit, offset)\n * @returns Paginated list of wallet favorites\n * @throws Error if the request fails\n */\n async getFavorites(\n walletAddress: string,\n filters?: WalletFavoritesFilters\n ): Promise<PaginatedResponse<WalletFavoriteData>> {\n const params = new URLSearchParams();\n\n if (filters?.category) params.append('category', filters.category);\n if (filters?.subcategory) params.append('subcategory', filters.subcategory);\n if (filters?.type) params.append('type', filters.type);\n if (filters?.limit) params.append('limit', filters.limit.toString());\n if (filters?.offset) params.append('offset', filters.offset.toString());\n\n const queryString = params.toString();\n const path = `/api/wallet/${encodeURIComponent(walletAddress)}/favorites${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<PaginatedResponse<WalletFavoriteData>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get favorites');\n }\n\n return response.data;\n }\n\n /**\n * Add a favorite for a wallet address.\n * POST /api/wallet/:address/favorites\n *\n * @param walletAddress - The wallet address to add a favorite for\n * @param favorite - The favorite item to add (category, subcategory, type, id)\n * @returns The newly created favorite data\n * @throws Error if the request fails\n */\n async addFavorite(\n walletAddress: string,\n favorite: CreateFavoriteRequest\n ): Promise<ApiResponse<WalletFavoriteData>> {\n const response = await this.networkClient.post<ApiResponse<WalletFavoriteData>>(\n buildUrl(this.baseUrl, `/api/wallet/${encodeURIComponent(walletAddress)}/favorites`),\n favorite\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'add favorite');\n }\n\n return response.data;\n }\n\n /**\n * Remove a favorite by ID.\n * DELETE /api/wallet/:address/favorites/:id\n *\n * @param walletAddress - The wallet address that owns the favorite\n * @param favoriteId - The numeric ID of the favorite to remove\n * @returns An API response confirming deletion\n * @throws Error if the favorite is not found or the request fails\n */\n async removeFavorite(walletAddress: string, favoriteId: number): Promise<ApiResponse<void>> {\n const response = await this.networkClient.delete<ApiResponse<void>>(\n buildUrl(\n this.baseUrl,\n `/api/wallet/${encodeURIComponent(walletAddress)}/favorites/${favoriteId}`\n )\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'remove favorite');\n }\n\n return response.data;\n }\n\n /**\n * Get favorite counts across all wallets for specific items.\n * GET /api/favorites/counts\n *\n * @param filters - Required filters: category, subcategory, type, itemIds\n * @returns Map of itemId to favorite count (items with 0 favorites are omitted)\n */\n async getFavoriteCounts(\n filters: FavoriteCountsFilters\n ): Promise<ApiResponse<Record<string, number>>> {\n const params = new URLSearchParams();\n params.append('category', filters.category);\n params.append('subcategory', filters.subcategory);\n params.append('type', filters.type);\n // itemIds is optional — omit to get all non-zero counts for the category\n if (filters.itemIds && filters.itemIds.length > 0) {\n params.append('itemIds', filters.itemIds.join(','));\n }\n\n const path = `/api/favorites/counts?${params.toString()}`;\n const response = await this.networkClient.get<ApiResponse<Record<string, number>>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get favorite counts');\n }\n return response.data;\n }\n\n // =============================================================================\n // ANALYTICS ENDPOINTS\n // =============================================================================\n\n /**\n * Get market statistics.\n * GET /api/stats/markets\n *\n * @returns Aggregate market statistics (totals, breakdowns by status)\n * @throws Error if the request fails\n */\n async getMarketStats(): Promise<ApiResponse<MarketStatsData>> {\n const response = await this.networkClient.get<ApiResponse<MarketStatsData>>(\n buildUrl(this.baseUrl, '/api/stats/markets')\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get market stats');\n }\n\n return response.data;\n }\n\n /**\n * Get health status of the indexer.\n * GET /api/health\n *\n * @returns The indexer health status\n * @throws Error if the request fails\n */\n async getHealth(): Promise<ApiResponse<HealthData>> {\n const response = await this.networkClient.get<ApiResponse<HealthData>>(\n buildUrl(this.baseUrl, '/api/health')\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'get health');\n }\n\n return response.data;\n }\n\n // =============================================================================\n // SPORTS API PROXY ENDPOINTS\n // =============================================================================\n\n /**\n * Cross-sport team search.\n * Searches teams across all sports via the indexer's aggregated search endpoint.\n * GET /api/sports/search?q={query}\n *\n * @param query - Search query (minimum 3 characters)\n * @returns Aggregated search results grouped by sport\n * @throws Error if the request fails\n */\n async searchSports(query: string): Promise<ApiResponse<SportsSearchResponse>> {\n const params = new URLSearchParams();\n params.append('q', query);\n\n const path = `/api/sports/search?${params.toString()}`;\n\n const response = await this.networkClient.get<ApiResponse<SportsSearchResponse>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, 'search sports');\n }\n\n return response.data;\n }\n\n /**\n * Generic sports API proxy call.\n * Proxies any api-sports.io request through the indexer with server-side caching.\n * Returns the raw api-sports.io response body (passthrough format).\n *\n * @param sport - Sport identifier (e.g., 'football', 'basketball')\n * @param endpoint - API endpoint path (e.g., '/countries', '/fixtures')\n * @param params - Optional query parameters to forward\n * @returns The raw api-sports.io response\n * @throws Error if the request fails\n *\n * @example\n * ```ts\n * const data = await client.getSportsData('football', '/countries');\n * const leagues = await client.getSportsData('basketball', '/leagues', { season: '2023-2024' });\n * ```\n */\n async getSportsData<T = unknown>(\n sport: string,\n endpoint: string,\n params?: SportsQueryParams\n ): Promise<SportsApiResponse<T>> {\n const searchParams = new URLSearchParams();\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n }\n }\n\n const queryString = searchParams.toString();\n const path = `/api/sports/${encodeURIComponent(sport)}${endpoint}${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.networkClient.get<SportsApiResponse<T>>(\n buildUrl(this.baseUrl, path)\n );\n\n if (!response.ok || !response.data) {\n throw handleApiError(response, `get sports data (${sport}${endpoint})`);\n }\n\n return response.data;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudobility/heavymath_indexer_client",
3
- "version": "0.0.35",
3
+ "version": "0.0.36",
4
4
  "description": "React and React Native compatible client library for Heavymath prediction market indexer API with TypeScript support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -42,14 +42,14 @@
42
42
  "author": "John Huang",
43
43
  "license": "BUSL-1.1",
44
44
  "peerDependencies": {
45
- "@sudobility/heavymath_types": "^0.0.20",
45
+ "@sudobility/heavymath_types": "^0.0.21",
46
46
  "@sudobility/types": "^1.9.61",
47
47
  "@tanstack/react-query": ">=5.0.0",
48
48
  "react": ">=18.0.0",
49
49
  "zustand": "^5.0.0"
50
50
  },
51
51
  "devDependencies": {
52
- "@sudobility/heavymath_types": "^0.0.20",
52
+ "@sudobility/heavymath_types": "^0.0.21",
53
53
  "@sudobility/types": "^1.9.61",
54
54
  "@tanstack/react-query": "^5.90.5",
55
55
  "@testing-library/dom": "^10.4.1",