@sudobility/heavymath_indexer_client 0.0.18 → 0.0.19

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.
Files changed (2) hide show
  1. package/README.md +44 -341
  2. package/package.json +5 -5
package/README.md CHANGED
@@ -1,380 +1,83 @@
1
- # @heavymath/indexer_client
1
+ # @sudobility/heavymath_indexer_client
2
2
 
3
- TypeScript client library for the Heavymath Prediction Market Indexer API. Provides React hooks, business services, and low-level API clients for querying prediction market data.
4
-
5
- ## Features
6
-
7
- - **Full API Coverage** - All REST endpoints supported
8
- - **React Hooks** - Built-in hooks using @tanstack/react-query
9
- - **Business Services** - High-level services with caching
10
- - **Network Layer** - Low-level API client for custom integrations
11
- - **TypeScript First** - Full type definitions included
12
- - **React Native Compatible** - Works in React Native environments
13
- - **Dependency Injection** - Uses NetworkClient from @sudobility/di
3
+ React and React Native compatible client library for the Heavymath prediction market indexer API. Provides a four-layer architecture (hooks, stores, business, network) with React Query integration, Zustand stores for optimistic updates, and SSE real-time subscriptions.
14
4
 
15
5
  ## Installation
16
6
 
17
7
  ```bash
18
- npm install @heavymath/indexer_client
8
+ bun add @sudobility/heavymath_indexer_client
19
9
  ```
20
10
 
21
- ## Peer Dependencies
11
+ ### Peer Dependencies
22
12
 
23
13
  ```bash
24
- npm install react @tanstack/react-query @sudobility/types @sudobility/heavymath_types @sudobility/di
14
+ bun add react @tanstack/react-query zustand @sudobility/types @sudobility/heavymath_types
25
15
  ```
26
16
 
27
- ## Quick Start
28
-
29
- ### 1. Setup React Query Provider
17
+ ## Usage
30
18
 
31
- ```tsx
32
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
19
+ ```typescript
20
+ import { IndexerClient, useActiveMarkets, useFavorites } from '@sudobility/heavymath_indexer_client';
33
21
 
34
- const queryClient = new QueryClient();
22
+ // Create client with injected NetworkClient
23
+ const client = new IndexerClient('http://localhost:42069', networkClient);
35
24
 
36
- function App() {
37
- return (
38
- <QueryClientProvider client={queryClient}>
39
- <YourApp />
40
- </QueryClientProvider>
41
- );
25
+ // Use hooks in React components
26
+ function Dashboard({ wallet }) {
27
+ const { data: markets } = useActiveMarkets(client, 20);
28
+ const { favorites, addFavorite, removeFavorite } = useFavorites(client, wallet);
29
+ // ...
42
30
  }
43
31
  ```
44
32
 
45
- ### 2. Create IndexerClient with NetworkClient
46
-
47
- ```tsx
48
- import { useMemo } from 'react';
49
- import { useNetworkService } from '@sudobility/di'; // Or your DI container
50
- import { IndexerClient } from '@heavymath/indexer_client';
51
-
52
- // Create a hook to provide IndexerClient
53
- function useIndexerClient() {
54
- const networkClient = useNetworkService();
55
- return useMemo(
56
- () => new IndexerClient('http://localhost:42069', networkClient),
57
- [networkClient]
58
- );
59
- }
60
- ```
33
+ ## Available Hooks
61
34
 
62
- ### 3. Use Hooks in Your Components
35
+ ### Markets
36
+ `useMarkets`, `useActiveMarkets`, `useMarket`, `useMarketPredictions`, `useMarketHistory`, `useMarketDetails`
63
37
 
64
- ```tsx
65
- import { useActiveMarkets, useUserPredictions } from '@heavymath/indexer_client';
38
+ ### Predictions
39
+ `usePredictions`, `useUserPredictions`, `useActiveBets`, `usePastBets`, `usePrediction`, `useUserBettingHistory`
66
40
 
67
- function BettorDashboard({ wallet }: { wallet: string }) {
68
- const client = useIndexerClient();
41
+ ### Dealers
42
+ `useDealers`, `useIsDealer`, `useDealerNFTs`, `useDealer`, `useDealerPermissions`, `useDealerMarkets`, `useDealerDashboard`
69
43
 
70
- const { data: markets, isLoading: marketsLoading } = useActiveMarkets(client, 20);
71
- const { data: myBets, isLoading: betsLoading } = useUserPredictions(client, wallet);
44
+ ### Withdrawals / Oracle
45
+ `useWithdrawals`, `useDealerWithdrawals`, `useSystemWithdrawals`, `useMarketWithdrawals`, `useOracleRequests`, `useOracleRequest`, `useMarketOracle`
72
46
 
73
- if (marketsLoading || betsLoading) return <div>Loading...</div>;
47
+ ### Favorites (with Zustand optimistic updates)
48
+ `useFavorites`, `useCategoryFavorites`, `useIsFavorite`
74
49
 
75
- return (
76
- <div>
77
- <h2>Active Markets</h2>
78
- {markets?.data?.map(market => (
79
- <MarketCard key={market.id} market={market} />
80
- ))}
50
+ ### SSE (real-time)
51
+ `useSSE`, `useMarketUpdates`, `useAllMarketUpdates`, `useUserPredictionUpdates`
81
52
 
82
- <h2>My Bets</h2>
83
- {myBets?.data?.map(bet => (
84
- <BetCard key={bet.id} bet={bet} />
85
- ))}
86
- </div>
87
- );
88
- }
89
- ```
53
+ ### Stats
54
+ `useMarketStats`, `useHealth`
90
55
 
91
56
  ## Architecture
92
57
 
93
- The library is organized into three layers:
94
-
95
- ### 1. Network Layer
96
-
97
- Low-level API client that accepts a `NetworkClient` instance.
98
-
99
- ```tsx
100
- import type { NetworkClient } from '@sudobility/types';
101
- import { IndexerClient } from '@heavymath/indexer_client';
102
-
103
- // Get NetworkClient from your DI container
104
- const networkClient: NetworkClient = getNetworkService();
105
-
106
- const client = new IndexerClient('http://localhost:42069', networkClient);
107
-
108
- // Direct API calls
109
- const markets = await client.getMarkets({ status: 'Active', limit: 10 });
110
- const market = await client.getMarket('1-market-123');
111
- ```
112
-
113
- ### 2. Business Layer
114
-
115
- High-level services with caching and business logic.
116
-
117
- ```tsx
118
- import type { NetworkClient } from '@sudobility/types';
119
- import { IndexerService } from '@heavymath/indexer_client';
120
-
121
- const networkClient: NetworkClient = getNetworkService();
122
-
123
- const service = new IndexerService({
124
- indexerUrl: 'http://localhost:42069',
125
- networkClient,
126
- cacheTTL: 5 * 60 * 1000, // 5 minutes (optional)
127
- });
128
-
129
- // Business methods with caching
130
- const activeMarkets = await service.getActiveMarkets(20);
131
- const userPredictions = await service.getUserPredictions('0x123...');
132
- const dealerDashboard = await service.getDealerDashboard('0x123...');
133
- ```
134
-
135
- ### 3. Hooks Layer
136
-
137
- React hooks using @tanstack/react-query for data fetching.
138
-
139
- ```tsx
140
- import { useActiveMarkets, useUserPredictions, useDealerDashboard } from '@heavymath/indexer_client';
141
-
142
- // All hooks take IndexerClient as first parameter
143
- const { data, isLoading, error, refetch } = useActiveMarkets(client, 20);
144
- ```
145
-
146
- ## Common Use Cases
147
-
148
- ### Dealer Dashboard
149
-
150
- ```tsx
151
- import { useDealerDashboard, useIsDealer } from '@heavymath/indexer_client';
152
-
153
- function DealerDashboard({ wallet }: { wallet: string }) {
154
- const client = useIndexerClient();
155
-
156
- const { data: isDealer, isLoading: checkingDealer } = useIsDealer(client, wallet);
157
- const { nfts, markets, isLoading } = useDealerDashboard(client, wallet);
158
-
159
- if (checkingDealer) return <div>Checking dealer status...</div>;
160
- if (!isDealer) return <div>You are not a dealer</div>;
161
- if (isLoading) return <div>Loading dashboard...</div>;
162
-
163
- return (
164
- <div>
165
- <h2>My Dealer NFTs</h2>
166
- {nfts.data?.map(nft => (
167
- <div key={nft.id}>Token #{nft.tokenId}</div>
168
- ))}
169
-
170
- <h2>My Markets</h2>
171
- {markets.data?.map(market => (
172
- <MarketCard key={market.id} market={market} />
173
- ))}
174
- </div>
175
- );
176
- }
177
- ```
178
-
179
- ### Market Details Page
180
-
181
- ```tsx
182
- import { useMarketDetails } from '@heavymath/indexer_client';
183
-
184
- function MarketPage({ marketId }: { marketId: string }) {
185
- const client = useIndexerClient();
186
-
187
- const { market, predictions, history, isLoading, isError } = useMarketDetails(client, marketId);
188
-
189
- if (isLoading) return <div>Loading...</div>;
190
- if (isError) return <div>Error loading market</div>;
191
-
192
- return (
193
- <div>
194
- <h1>{market.data?.data?.title}</h1>
195
- <p>{market.data?.data?.description}</p>
196
- <p>Status: {market.data?.data?.status}</p>
197
-
198
- <h2>Predictions ({predictions.data?.data?.length || 0})</h2>
199
- {predictions.data?.data?.map(pred => (
200
- <div key={pred.id}>
201
- {pred.userAddress}: {pred.percentage}%
202
- </div>
203
- ))}
204
-
205
- <h2>State History</h2>
206
- {history.data?.data?.map(state => (
207
- <div key={state.id}>
208
- {state.fromState} → {state.toState}
209
- </div>
210
- ))}
211
- </div>
212
- );
213
- }
214
58
  ```
215
-
216
- ### Wallet Favorites
217
-
218
- ```tsx
219
- import { useFavorites } from '@heavymath/indexer_client';
220
-
221
- function FavoritesPage({ wallet }: { wallet: string }) {
222
- const client = useIndexerClient();
223
-
224
- const { favorites, isLoading, addFavorite, removeFavorite, refresh } = useFavorites(
225
- client,
226
- wallet
227
- );
228
-
229
- const handleAddFavorite = async () => {
230
- await addFavorite.mutateAsync({
231
- category: 'sports',
232
- subcategory: 'soccer',
233
- type: 'team',
234
- id: 'team-123',
235
- });
236
- };
237
-
238
- const handleRemoveFavorite = async (id: number) => {
239
- await removeFavorite.mutateAsync(id);
240
- };
241
-
242
- if (isLoading) return <div>Loading...</div>;
243
-
244
- return (
245
- <div>
246
- <h2>My Favorites</h2>
247
- {favorites.map(fav => (
248
- <div key={fav.id}>
249
- {fav.category}/{fav.subcategory}: {fav.itemId}
250
- <button onClick={() => handleRemoveFavorite(fav.id)}>Remove</button>
251
- </div>
252
- ))}
253
- <button onClick={handleAddFavorite}>Add Favorite</button>
254
- </div>
255
- );
256
- }
59
+ Hooks (React Query) --> Zustand Stores --> Business Layer (caching) --> Network Layer (HTTP)
257
60
  ```
258
61
 
259
- ## Available Hooks
260
-
261
- ### Market Hooks
262
- - `useMarkets(client, filters?)` - Get all markets with filtering
263
- - `useActiveMarkets(client, limit?)` - Get active markets only
264
- - `useMarket(client, marketId)` - Get specific market
265
- - `useMarketPredictions(client, marketId)` - Get market's predictions
266
- - `useMarketHistory(client, marketId)` - Get market's state history
267
- - `useMarketDetails(client, marketId)` - Get complete market details
268
-
269
- ### Prediction Hooks
270
- - `usePredictions(client, filters?)` - Get predictions with filtering
271
- - `useUserPredictions(client, wallet, filters?)` - Get user's predictions
272
- - `useActiveBets(client, wallet)` - Get user's active bets
273
- - `usePastBets(client, wallet)` - Get user's claimed bets
274
- - `usePrediction(client, predictionId)` - Get specific prediction
275
- - `useUserBettingHistory(client, wallet)` - Get complete betting history
276
-
277
- ### Dealer Hooks
278
- - `useDealers(client, filters?)` - Get dealer NFTs with filtering
279
- - `useIsDealer(client, wallet)` - Check if wallet is a dealer
280
- - `useDealerNFTs(client, wallet)` - Get wallet's dealer NFTs
281
- - `useDealer(client, dealerId)` - Get specific dealer NFT
282
- - `useDealerPermissions(client, dealerId)` - Get dealer's permissions
283
- - `useDealerMarkets(client, dealerId)` - Get dealer's markets
284
- - `useDealerDashboard(client, wallet)` - Get complete dealer dashboard
285
-
286
- ### Withdrawal Hooks
287
- - `useWithdrawals(client, filters?)` - Get withdrawals with filtering
288
- - `useDealerWithdrawals(client, dealer)` - Get dealer's withdrawals
289
- - `useSystemWithdrawals(client)` - Get system withdrawals
290
- - `useMarketWithdrawals(client, marketId)` - Get market's withdrawals
291
-
292
- ### Oracle Hooks
293
- - `useOracleRequests(client, filters?)` - Get oracle requests with filtering
294
- - `useOracleRequest(client, requestId)` - Get specific oracle request
295
- - `useMarketOracle(client, marketId)` - Get market's oracle request
296
- - `useTimedOutOracleRequests(client)` - Get timed out requests
297
- - `usePendingOracleRequests(client)` - Get pending requests
298
-
299
- ### Favorites Hooks
300
- - `useFavorites(client, wallet, filters?)` - Get favorites with add/remove/refresh
301
- - `useCategoryFavorites(client, wallet, category)` - Get favorites by category
302
- - `useIsFavorite(client, wallet, item)` - Check if item is favorited with toggle
303
-
304
- ### Stats Hooks
305
- - `useMarketStats(client)` - Get market statistics
306
- - `useHealth(client)` - Get indexer health status
307
-
308
- ## API Endpoints
309
-
310
- The client supports all REST endpoints:
311
-
312
- - **Markets**: `/api/markets`, `/api/markets/:id`, `/api/markets/:id/predictions`, `/api/markets/:id/history`
313
- - **Predictions**: `/api/predictions`, `/api/predictions/:id`
314
- - **Dealers**: `/api/dealers`, `/api/dealers/:id`, `/api/dealers/:id/permissions`, `/api/dealers/:id/markets`
315
- - **Withdrawals**: `/api/withdrawals`
316
- - **Oracle**: `/api/oracle/requests`, `/api/oracle/requests/:id`
317
- - **Favorites**: `/api/wallet/:address/favorites` (GET, POST, DELETE)
318
- - **Analytics**: `/api/stats/markets`, `/api/health`
319
-
320
- ## TypeScript Support
321
-
322
- Full TypeScript definitions included:
323
-
324
- ```tsx
325
- import type {
326
- // Core types (from @sudobility/heavymath_types)
327
- MarketData,
328
- PredictionData,
329
- DealerNftData,
330
- DealerPermissionData,
331
- MarketStateHistoryData,
332
- FeeWithdrawalData,
333
- OracleRequestData,
334
- WalletFavoriteData,
335
- CreateFavoriteRequest,
336
- // Enums
337
- MarketStatus,
338
- ClaimType,
339
- WithdrawalType,
340
- // Response wrappers (from @sudobility/types)
341
- ApiResponse,
342
- PaginatedResponse,
343
- NetworkClient,
344
- // Filter types
345
- MarketFilters,
346
- PredictionFilters,
347
- DealerFilters,
348
- WithdrawalFilters,
349
- OracleFilters,
350
- WalletFavoritesFilters,
351
- } from '@heavymath/indexer_client';
352
- ```
62
+ All hooks accept `IndexerClient` as their first parameter. SSE hooks accept an endpoint URL.
353
63
 
354
64
  ## Development
355
65
 
356
66
  ```bash
357
- # Install dependencies
358
- npm install
359
-
360
- # Build
361
- npm run build
362
-
363
- # Type check
364
- npm run typecheck
67
+ bun run build # Compile TypeScript to dist/
68
+ bun run typecheck # Type validation
69
+ bun run test:run # Run tests once
70
+ bun run lint # ESLint check
71
+ bun run check-all # Lint + typecheck + tests
72
+ ```
365
73
 
366
- # Lint
367
- npm run lint
74
+ ## Related Packages
368
75
 
369
- # Format
370
- npm run format
371
-
372
- # Run all checks
373
- npm run check-all
374
- ```
76
+ - `@sudobility/heavymath_types` -- shared type definitions
77
+ - `@sudobility/heavymath_indexer` -- the backend indexer this client connects to
78
+ - `@sudobility/heavymath_lib` -- business logic hooks
79
+ - `heavymath_app` -- frontend web application
375
80
 
376
81
  ## License
377
82
 
378
- BUSL 1.1 - Business Use Source License
379
-
380
- Copyright (c) 2025 Sudobility Inc.
83
+ BUSL-1.1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudobility/heavymath_indexer_client",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
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,15 +42,15 @@
42
42
  "author": "John Huang",
43
43
  "license": "BUSL-1.1",
44
44
  "peerDependencies": {
45
- "@sudobility/heavymath_types": "^0.0.10",
46
- "@sudobility/types": "^1.9.55",
45
+ "@sudobility/heavymath_types": "^0.0.11",
46
+ "@sudobility/types": "^1.9.57",
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.10",
53
- "@sudobility/types": "^1.9.55",
52
+ "@sudobility/heavymath_types": "^0.0.11",
53
+ "@sudobility/types": "^1.9.57",
54
54
  "@tanstack/react-query": "^5.90.5",
55
55
  "@testing-library/dom": "^10.4.1",
56
56
  "@testing-library/react": "^16.3.0",