@sudobility/indexer_client 0.0.118 → 0.0.120

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 +56 -554
  2. package/package.json +9 -9
package/README.md CHANGED
@@ -1,594 +1,96 @@
1
1
  # @sudobility/indexer_client
2
2
 
3
- TypeScript client library for the blockchain mail Indexer API. Compatible with React and React Native applications.
4
-
5
- ## Features
6
-
7
- - ✅ **Complete Type Safety** - Full TypeScript support with `@sudobility/types`
8
- - ✅ **React Integration** - Built-in hooks using `@tanstack/react-query`
9
- - ✅ **Multi-Chain Support** - EVM and Solana blockchains
10
- - ✅ **Authentication** - SIWE/SIWS signature verification
11
- - ✅ **Points System** - Track and display user points
12
- - ✅ **Referral System** - Generate and track referral codes
13
- - ✅ **Name Service** - ENS and SNS resolution
14
- - ✅ **Delegation** - Wallet delegation management
15
- - ✅ **Development Mode** - Mock data for testing
3
+ TypeScript client library for the 0xMail blockchain indexer REST and GraphQL APIs. Provides an `IndexerClient` class, TanStack React Query hooks, GraphQL/admin/webhook helpers, and a business service layer. Works cross-platform on React and React Native via an injected `NetworkClient` interface.
16
4
 
17
5
  ## Installation
18
6
 
19
7
  ```bash
20
- npm install @sudobility/indexer_client
21
- ```
22
-
23
- ### Peer Dependencies
24
-
25
- ```bash
26
- npm install react @tanstack/react-query axios @sudobility/di@^1.4.7 @sudobility/types@^1.8.29
27
- ```
28
-
29
- **Current Versions:**
30
- - `@sudobility/di` v1.4.7
31
- - `@sudobility/types` v1.8.29
32
-
33
- ## Quick Start
34
-
35
- ### 1. Setup React Query
36
-
37
- ```typescript
38
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
39
-
40
- const queryClient = new QueryClient({
41
- defaultOptions: {
42
- queries: {
43
- staleTime: 5 * 60 * 1000, // 5 minutes
44
- },
45
- },
46
- });
47
-
48
- function App() {
49
- return (
50
- <QueryClientProvider client={queryClient}>
51
- {/* Your app */}
52
- </QueryClientProvider>
53
- );
54
- }
8
+ bun add @sudobility/indexer_client
55
9
  ```
56
10
 
57
- ### 2. Use Hooks
58
-
59
- ```typescript
60
- import { useIndexerPoints } from '@sudobility/indexer_client';
61
-
62
- function PointsDisplay({ wallet, signature, message }) {
63
- const { data, isLoading } = useIndexerPoints(
64
- 'https://indexer.example.com',
65
- false, // dev mode
66
- wallet,
67
- signature,
68
- message
69
- );
70
-
71
- if (isLoading) return <div>Loading...</div>;
72
- if (!data?.success) return <div>Error</div>;
73
-
74
- return <div>Points: {data.data.pointsEarned}</div>;
75
- }
76
- ```
77
-
78
- ## API Coverage
79
-
80
- | Feature | Status | Endpoints |
81
- |---------|--------|-----------|
82
- | Mail & User Management | ✅ 71% | 12/17 implemented |
83
- | Points System | ✅ 100% | 3/3 implemented |
84
- | Referral System | ✅ 100% | Fully implemented |
85
- | OAuth 2.0 | ❌ 0% | Planned for v1.0 |
86
- | KYC Verification | ❌ 0% | Optional feature |
87
- | Solana Admin | ❌ 0% | Admin tools |
11
+ Peer dependencies: `react` (>=18), `@tanstack/react-query` (>=5), `@sudobility/di`, `@sudobility/types`, `@sudobility/mail_box_types`, `@sudobility/configs`.
88
12
 
89
- See [docs/COVERAGE.md](docs/COVERAGE.md) for complete endpoint matrix.
90
-
91
- ## Documentation
92
-
93
- - **[docs/API.md](docs/API.md)** - Complete API endpoint documentation
94
- - **[docs/EXAMPLES.md](docs/EXAMPLES.md)** - Code examples for all features
95
- - **[docs/HOOKS_DOCUMENTATION.md](docs/HOOKS_DOCUMENTATION.md)** - Comprehensive hook documentation
96
- - **[docs/AI_DEVELOPMENT_GUIDE.md](docs/AI_DEVELOPMENT_GUIDE.md)** - Guide for AI-assisted development
97
- - **[docs/CONTRIBUTING.md](docs/CONTRIBUTING.md)** - Development and contribution guidelines
98
- - **[docs/COVERAGE.md](docs/COVERAGE.md)** - API implementation status
99
-
100
- ## Core Components
101
-
102
- ### IndexerClient
103
-
104
- Low-level HTTP client for direct API access:
13
+ ## Usage
105
14
 
106
15
  ```typescript
107
16
  import { IndexerClient } from '@sudobility/indexer_client';
108
17
 
109
- const client = new IndexerClient('https://indexer.example.com', false);
110
-
111
- // Validate wallet address
112
- const result = await client.validateUsername('0x742d35Cc...');
113
-
114
- // Get signing message
115
- const msgResult = await client.getMessage(
116
- '0x742d35Cc...',
117
- 1, // chainId
118
- 'example.com',
119
- 'https://example.com'
120
- );
121
-
122
- // Get points balance (requires signature)
123
- const points = await client.getPointsBalance(wallet, signature, message);
18
+ // Core client (uses injected NetworkClient for cross-platform HTTP)
19
+ const client = new IndexerClient(endpointUrl, networkClient, dev);
20
+ const accounts = await client.getWalletAccounts(walletAddress, auth);
21
+ const points = await client.getPointsBalance(walletAddress, auth);
124
22
  ```
125
23
 
126
24
  ### React Hooks
127
25
 
128
- High-level hooks with automatic caching and refetching:
129
-
130
- #### useIndexerMail
131
- ```typescript
132
- import { useIndexerMail } from '@sudobility/indexer_client';
133
-
134
- const { data, isLoading, error, refetch } = useIndexerMail(
135
- endpointUrl,
136
- dev,
137
- walletAddress,
138
- signature,
139
- message
140
- );
141
- ```
142
-
143
- #### useIndexerPoints
144
- ```typescript
145
- import { useIndexerPoints } from '@sudobility/indexer_client';
146
-
147
- const { data, isLoading } = useIndexerPoints(
148
- endpointUrl,
149
- dev,
150
- walletAddress,
151
- signature,
152
- message
153
- );
154
- ```
155
-
156
- #### useIndexerReferralCode
157
- ```typescript
158
- import { useIndexerReferralCode } from '@sudobility/indexer_client';
159
-
160
- const { data, isLoading } = useIndexerReferralCode(
161
- endpointUrl,
162
- dev,
163
- walletAddress,
164
- signature,
165
- message
166
- );
167
- ```
168
-
169
- #### useIndexerReferralStats
170
- ```typescript
171
- import { useIndexerReferralStats } from '@sudobility/indexer_client';
172
-
173
- const { data, isLoading } = useIndexerReferralStats(
174
- endpointUrl,
175
- dev,
176
- referralCode
177
- );
178
- ```
179
-
180
- #### useWalletNames / useResolveNameToAddress
181
- ```typescript
182
- import { useWalletNames, useResolveNameToAddress } from '@sudobility/indexer_client';
183
-
184
- // Get all names for a wallet
185
- const { data: names } = useWalletNames(
186
- endpointUrl,
187
- dev,
188
- walletAddress,
189
- signature,
190
- message
191
- );
192
-
193
- // Resolve name to address
194
- const { data: resolved } = useResolveNameToAddress(
195
- endpointUrl,
196
- dev,
197
- 'vitalik.eth'
198
- );
199
- ```
200
-
201
- ### Business Services
202
-
203
- #### IndexerService
204
- Caching wrapper for public endpoints:
205
-
206
- ```typescript
207
- import { IndexerService } from '@sudobility/indexer_client';
208
-
209
- const config = {
210
- indexerBackendUrl: 'https://indexer.example.com'
211
- };
212
-
213
- const service = IndexerService.getInstance(config);
214
-
215
- // Get leaderboard (cached for 5 minutes)
216
- const leaderboard = await service.getLeaderboard(10);
217
-
218
- // Get public stats
219
- const stats = await service.getPublicStats();
220
- ```
221
-
222
- ### Factory Helpers
223
-
224
- Create helper instances with automatic client injection:
225
-
226
26
  ```typescript
227
27
  import {
228
- createIndexerAdmin,
229
- createIndexerGraphQL,
230
- createIndexerWebhook,
231
- createIndexerHelpers
28
+ useIndexerGetWalletAccounts,
29
+ useIndexerPointsInfo,
30
+ useIndexerPointsLeaderboard,
31
+ useIndexerGetDelegatedTo,
32
+ useWalletNames,
33
+ useResolveNameToAddress,
34
+ useIndexerMailTemplates,
35
+ useIndexerMailWebhooks,
36
+ useIndexerReferralCode,
232
37
  } from '@sudobility/indexer_client';
233
38
 
234
- const config = {
235
- indexerBackendUrl: 'https://indexer.example.com'
236
- };
237
-
238
- // Create individual helpers
239
- const admin = createIndexerAdmin(config);
240
- const graphql = createIndexerGraphQL(config);
241
- const webhook = createIndexerWebhook(config);
242
-
243
- // Or create all at once
244
- const { admin, graphql, webhook } = createIndexerHelpers(config);
245
- ```
246
-
247
- ## Authentication
248
-
249
- All protected endpoints require signature authentication:
250
-
251
- ### 1. Generate Message
252
-
253
- ```typescript
254
- const msgResult = await client.getMessage(
255
- walletAddress,
256
- chainId,
257
- 'domain.com',
258
- 'https://domain.com'
259
- );
260
- const message = msgResult.data.message;
261
- ```
262
-
263
- ### 2. Sign Message
264
-
265
- **EVM (ethers.js):**
266
- ```typescript
267
- import { ethers } from 'ethers';
268
-
269
- const provider = new ethers.BrowserProvider(window.ethereum);
270
- const signer = await provider.getSigner();
271
- const signature = await signer.signMessage(message);
272
- ```
273
-
274
- **Solana:**
275
- ```typescript
276
- import { useWallet } from '@solana/wallet-adapter-react';
277
- import bs58 from 'bs58';
278
-
279
- const { publicKey, signMessage } = useWallet();
280
- const encodedMessage = new TextEncoder().encode(message);
281
- const signatureBuffer = await signMessage(encodedMessage);
282
- const signature = bs58.encode(signatureBuffer);
283
- ```
284
-
285
- ### 3. Make Authenticated Request
286
-
287
- ```typescript
288
- const result = await client.getWalletAccounts(
289
- walletAddress,
290
- signature,
291
- message
292
- );
293
- ```
294
-
295
- ## Common Use Cases
296
-
297
- ### Get Email Accounts
298
-
299
- ```typescript
300
- const accounts = await client.getWalletAccounts(
301
- walletAddress,
302
- signature,
303
- message
304
- );
305
-
306
- if (accounts.success) {
307
- accounts.data.accounts.forEach(account => {
308
- console.log('Primary:', account.primaryAccount);
309
- account.domainAccounts.forEach(domain => {
310
- console.log('Domain:', domain.account);
311
- });
312
- });
313
- }
314
- ```
315
-
316
- ### Apply Referral Code
317
-
318
- ```typescript
319
- // Referral code is applied on first /accounts call
320
- const accounts = await client.getWalletAccounts(
321
- walletAddress,
322
- signature,
323
- message,
324
- 'ABC123XYZ' // Referral code (applied once)
325
- );
326
- ```
327
-
328
- ### Check Points Balance
329
-
330
- ```typescript
331
- const points = await client.getPointsBalance(
332
- walletAddress,
333
- signature,
334
- message
335
- );
336
-
337
- console.log(`Points: ${points.data.pointsEarned}`);
338
- ```
339
-
340
- ### Generate Referral Code
341
-
342
- ```typescript
343
- const referral = await client.getReferralCode(
344
- walletAddress,
345
- signature,
346
- message
347
- );
348
-
349
- console.log(`Code: ${referral.data.referralCode}`);
350
- console.log(`Redemptions: ${referral.data.totalRedemptions}`);
351
- ```
352
-
353
- ### Resolve ENS/SNS Name
354
-
355
- ```typescript
356
- const resolved = await client.resolveNameToAddress('vitalik.eth');
357
-
358
- if (resolved.success) {
359
- console.log('Address:', resolved.data.address);
360
- console.log('Chain:', resolved.data.chainType);
361
- }
362
- ```
39
+ // Public endpoints (no auth)
40
+ const { data } = useIndexerPointsInfo(networkClient, endpointUrl, dev);
41
+ const { data } = useResolveNameToAddress(networkClient, endpointUrl, dev, 'vitalik.eth');
363
42
 
364
- ## Development Mode
365
-
366
- Enable development mode to use mock data:
367
-
368
- ```typescript
369
- const client = new IndexerClient('https://indexer.example.com', true); // dev = true
370
- ```
371
-
372
- Mock data is defined in `src/hooks/mocks.ts`.
373
-
374
- ## Error Handling
375
-
376
- All API responses follow this structure:
377
-
378
- ```typescript
379
- interface ApiResponse<T> {
380
- success: boolean;
381
- data: T | null;
382
- error?: string;
383
- timestamp: string;
384
- }
385
- ```
386
-
387
- Handle errors consistently:
388
-
389
- ```typescript
390
- const result = await client.someMethod();
391
-
392
- if (!result.success) {
393
- console.error('Error:', result.error);
394
- return;
395
- }
396
-
397
- // Use result.data
43
+ // Authenticated endpoints (wallet signature required)
44
+ const { data } = useIndexerGetWalletAccounts(networkClient, endpointUrl, dev, walletAddress, auth);
398
45
  ```
399
46
 
400
- ## TypeScript Support
401
-
402
- All types must be imported from `@sudobility/types`:
47
+ ### Utility Helpers
403
48
 
404
49
  ```typescript
405
- import type {
406
- AddressValidationResponse,
407
- EmailAccountsResponse,
408
- PointsResponse,
409
- ReferralCodeResponse,
410
- LeaderboardResponse,
411
- Optional,
412
- // ... and more
413
- } from '@sudobility/types';
414
- ```
415
-
416
- **Important:** As of version 0.0.26, this library no longer re-exports types from `@sudobility/types`. You must import types directly from `@sudobility/types`:
417
-
418
- ```typescript
419
- // ✅ Correct
420
- import type { PointsResponse } from '@sudobility/types';
421
- import { useIndexerPoints } from '@sudobility/indexer_client';
422
-
423
- // ❌ Incorrect (will cause errors)
424
- import type { PointsResponse } from '@sudobility/indexer_client';
425
- ```
50
+ import { createIndexerHelpers } from '@sudobility/indexer_client';
426
51
 
427
- ## Testing
52
+ const { admin, graphql, webhook } = createIndexerHelpers(config, networkClient);
428
53
 
429
- ### Unit Tests
430
-
431
- ```bash
432
- # Run unit tests
433
- npm test
434
-
435
- # Run unit tests once
436
- npm run test:run
437
-
438
- # Run with coverage
439
- npm run test:coverage
440
- ```
441
-
442
- ### Integration Tests
443
-
444
- Integration tests run against a real indexer endpoint. See [src/__integration__/README.md](src/__integration__/README.md) for details.
445
-
446
- ```bash
447
- # Setup
448
- cp .env.example .env.test
449
- # Edit .env.test and set INTEGRATION_TEST_INDEXER_URL
450
-
451
- # Run integration tests
452
- npm run test:integration
453
-
454
- # Run integration tests in watch mode
455
- npm run test:integration:watch
456
- ```
457
-
458
- ### Other Commands
459
-
460
- ```bash
461
- # Type checking
462
- npm run typecheck
463
-
464
- # Linting
465
- npm run lint
466
-
467
- # All checks (lint + typecheck + unit tests)
468
- npm run check-all
469
- ```
470
-
471
- ## Building
472
-
473
- ```bash
474
- # Build for production
475
- npm run build
476
-
477
- # Build and watch
478
- npm run build:watch
479
-
480
- # Clean build artifacts
481
- npm run clean
54
+ // Admin: campaigns, points awards, user flags
55
+ // GraphQL: mails, delegations, statistics
56
+ // Webhook: email-sent, login, referral events
482
57
  ```
483
58
 
484
- ## Roadmap
485
-
486
- ### v0.1.0 (Current)
487
- - ✅ Core mail and user management
488
- - ✅ Points system
489
- - ✅ Referral system
490
- - ✅ Name service integration
491
- - ✅ React hooks
492
-
493
- ### v1.0.0 (Planned)
494
- - [ ] Complete OAuth 2.0 flow
495
- - [ ] Block status monitoring
496
- - [ ] Authentication status check
497
- - [ ] Enhanced GraphQL support
498
-
499
- ### v1.1.0 (Future)
500
- - [ ] KYC verification module
501
- - [ ] Solana admin tools
502
- - [ ] Advanced caching strategies
503
- - [ ] Request deduplication
504
-
505
- See [docs/COVERAGE.md](docs/COVERAGE.md) for detailed implementation status.
506
-
507
- ## CI/CD
59
+ ## API
508
60
 
509
- This project uses GitHub Actions for automated testing and releases.
61
+ | Export | Description |
62
+ |--------|-------------|
63
+ | `IndexerClient` | Core REST API client (~40 endpoints) |
64
+ | `IndexerService` | Singleton with 5-min in-memory cache (public endpoints) |
65
+ | `useIndexer*` hooks | 18 individual TanStack React Query hooks |
66
+ | `IndexerMockData` | Static mock factories for all response types |
67
+ | `IndexerAdminHelper` | Admin API helper (campaigns, points, flags) |
68
+ | `IndexerGraphQLHelper` | GraphQL query helper (mails, delegations, stats) |
69
+ | `IndexerWebhookHelper` | Webhook processing helper |
70
+ | `createAuthHeaders` | Build signature auth headers (`x-signature`, `x-message`, `x-signer`) |
510
71
 
511
- ### Automated Workflow
512
-
513
- On every push to `main`:
514
- 1. ✅ Run tests on Node.js 20.x and 22.x
515
- 2. ✅ Type checking and linting
516
- 3. ✅ Build verification
517
- 4. ✅ Create GitHub release
518
- 5. ✅ Publish to NPM
519
-
520
- ### Triggering a Release
72
+ ## Development
521
73
 
522
74
  ```bash
523
- # Bump version
524
- npm version patch # 0.0.1 -> 0.0.2
525
-
526
- # Push to trigger release
527
- git push origin main
75
+ bun install
76
+ bun run check-all # lint + typecheck + test:run
77
+ bun run build # TypeScript compilation
78
+ bun run test # Vitest (watch mode)
79
+ bun run test:run # Single run
80
+ bun run test:coverage # Coverage (70% threshold)
81
+ bun run test:integration # Integration tests (requires live indexer)
82
+ bun run typecheck # tsc --noEmit
83
+ bun run lint # ESLint
528
84
  ```
529
85
 
530
- See [.github/workflows/README.md](.github/workflows/README.md) for detailed CI/CD documentation.
531
-
532
- ## Contributing
533
-
534
- See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) for guidelines.
86
+ ## Related Packages
535
87
 
536
- ## Backend Repository
537
-
538
- This client library connects to the mail_box_indexer backend, located at `../mail_box_indexer`.
539
-
540
- The backend provides:
541
- - Blockchain indexing (Ponder framework)
542
- - REST API (Hono framework)
543
- - GraphQL API
544
- - OAuth 2.0 server
545
- - KYC integration (Sumsub)
546
- - Multi-chain support (EVM + Solana)
547
-
548
- ## Architecture
549
-
550
- ```
551
- ┌─────────────────────────────────────────────────────┐
552
- │ React Application │
553
- │ │
554
- │ ┌────────────────────────────────────────────────┐ │
555
- │ │ React Query Hooks │ │
556
- │ │ useIndexerMail, useIndexerPoints, etc. │ │
557
- │ └────────────────────────────────────────────────┘ │
558
- │ ↓ │
559
- │ ┌────────────────────────────────────────────────┐ │
560
- │ │ Business Services │ │
561
- │ │ IndexerService, IndexerAdminHelper, etc. │ │
562
- │ └────────────────────────────────────────────────┘ │
563
- │ ↓ │
564
- │ ┌────────────────────────────────────────────────┐ │
565
- │ │ IndexerClient (HTTP) │ │
566
- │ │ axios │ │
567
- │ └────────────────────────────────────────────────┘ │
568
- └─────────────────────────────────────────────────────┘
569
-
570
- ┌─────────────────────────────────────────────────────┐
571
- │ mail_box_indexer Backend │
572
- │ │
573
- │ REST API (Hono) + GraphQL + OAuth 2.0 │
574
- │ PostgreSQL Database (Ponder framework) │
575
- │ Multi-chain indexing (EVM + Solana) │
576
- └─────────────────────────────────────────────────────┘
577
- ```
88
+ - `@0xmail/indexer` -- the backend this client connects to
89
+ - `@sudobility/di` -- provides `NetworkClient` interface
90
+ - `@sudobility/mail_box_types` -- shared API response types
91
+ - `@sudobility/types` -- core types (ChainType, Optional)
92
+ - `@sudobility/configs` -- application configuration
578
93
 
579
94
  ## License
580
95
 
581
- MIT
582
-
583
- ## Support
584
-
585
- For questions and support:
586
- - GitHub Issues: https://github.com/johnqh/mail_box_indexer_client/issues
587
- - Documentation: See `docs/API.md` and `docs/EXAMPLES.md`
588
- - Backend: `../mail_box_indexer`
589
-
590
- ## Version
591
-
592
- Current version: **0.0.28**
593
-
594
- See [docs/COVERAGE.md](docs/COVERAGE.md) for implementation roadmap.
96
+ BUSL-1.1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudobility/indexer_client",
3
- "version": "0.0.118",
3
+ "version": "0.0.120",
4
4
  "description": "React and React Native compatible client library for blockchain mail indexer API with TypeScript support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -42,18 +42,18 @@
42
42
  "author": "John Huang",
43
43
  "license": "BUSL-1.1",
44
44
  "peerDependencies": {
45
- "@sudobility/di": "^1.5.43",
46
- "@sudobility/mail_box_types": "^1.0.15",
47
- "@sudobility/types": "^1.9.55",
45
+ "@sudobility/di": "^1.5.45",
46
+ "@sudobility/mail_box_types": "^1.0.16",
47
+ "@sudobility/types": "^1.9.57",
48
48
  "@tanstack/react-query": ">=5.0.0",
49
49
  "react": ">=18.0.0",
50
- "@sudobility/configs": "^0.0.66"
50
+ "@sudobility/configs": "^0.0.68"
51
51
  },
52
52
  "devDependencies": {
53
- "@sudobility/configs": "^0.0.66",
54
- "@sudobility/di": "^1.5.43",
55
- "@sudobility/mail_box_types": "^1.0.15",
56
- "@sudobility/types": "^1.9.55",
53
+ "@sudobility/configs": "^0.0.68",
54
+ "@sudobility/di": "^1.5.45",
55
+ "@sudobility/mail_box_types": "^1.0.16",
56
+ "@sudobility/types": "^1.9.57",
57
57
  "@tanstack/react-query": "^5.90.5",
58
58
  "@testing-library/dom": "^10.4.1",
59
59
  "@testing-library/react": "^16.3.0",