@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.
- package/README.md +44 -341
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,380 +1,83 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @sudobility/heavymath_indexer_client
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
8
|
+
bun add @sudobility/heavymath_indexer_client
|
|
19
9
|
```
|
|
20
10
|
|
|
21
|
-
|
|
11
|
+
### Peer Dependencies
|
|
22
12
|
|
|
23
13
|
```bash
|
|
24
|
-
|
|
14
|
+
bun add react @tanstack/react-query zustand @sudobility/types @sudobility/heavymath_types
|
|
25
15
|
```
|
|
26
16
|
|
|
27
|
-
##
|
|
28
|
-
|
|
29
|
-
### 1. Setup React Query Provider
|
|
17
|
+
## Usage
|
|
30
18
|
|
|
31
|
-
```
|
|
32
|
-
import {
|
|
19
|
+
```typescript
|
|
20
|
+
import { IndexerClient, useActiveMarkets, useFavorites } from '@sudobility/heavymath_indexer_client';
|
|
33
21
|
|
|
34
|
-
|
|
22
|
+
// Create client with injected NetworkClient
|
|
23
|
+
const client = new IndexerClient('http://localhost:42069', networkClient);
|
|
35
24
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
-
###
|
|
35
|
+
### Markets
|
|
36
|
+
`useMarkets`, `useActiveMarkets`, `useMarket`, `useMarketPredictions`, `useMarketHistory`, `useMarketDetails`
|
|
63
37
|
|
|
64
|
-
|
|
65
|
-
|
|
38
|
+
### Predictions
|
|
39
|
+
`usePredictions`, `useUserPredictions`, `useActiveBets`, `usePastBets`, `usePrediction`, `useUserBettingHistory`
|
|
66
40
|
|
|
67
|
-
|
|
68
|
-
|
|
41
|
+
### Dealers
|
|
42
|
+
`useDealers`, `useIsDealer`, `useDealerNFTs`, `useDealer`, `useDealerPermissions`, `useDealerMarkets`, `useDealerDashboard`
|
|
69
43
|
|
|
70
|
-
|
|
71
|
-
|
|
44
|
+
### Withdrawals / Oracle
|
|
45
|
+
`useWithdrawals`, `useDealerWithdrawals`, `useSystemWithdrawals`, `useMarketWithdrawals`, `useOracleRequests`, `useOracleRequest`, `useMarketOracle`
|
|
72
46
|
|
|
73
|
-
|
|
47
|
+
### Favorites (with Zustand optimistic updates)
|
|
48
|
+
`useFavorites`, `useCategoryFavorites`, `useIsFavorite`
|
|
74
49
|
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
83
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
#
|
|
361
|
-
|
|
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
|
-
|
|
367
|
-
npm run lint
|
|
74
|
+
## Related Packages
|
|
368
75
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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
|
|
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.
|
|
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.
|
|
46
|
-
"@sudobility/types": "^1.9.
|
|
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.
|
|
53
|
-
"@sudobility/types": "^1.9.
|
|
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",
|