@fenelabs/fene-sdk 0.3.2 → 0.3.6

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 CHANGED
@@ -1,485 +1,238 @@
1
- # Fene Network SDK
1
+ # @resonance/sdk
2
2
 
3
- Official TypeScript/JavaScript SDK for interacting with the Fene Network API.
3
+ TypeScript SDK for the Resonance API.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @fenelabs/fene-sdk
9
- # or
10
- yarn add @fenelabs/fene-sdk
11
- # or
12
- pnpm add @fenelabs/fene-sdk
8
+ pnpm add @resonance/sdk
13
9
  ```
14
10
 
15
11
  ## Quick Start
16
12
 
17
13
  ```typescript
18
- import { ResonanceSDK } from '@fenelabs/fene-sdk';
14
+ import { createResonanceClient } from "@resonance/sdk";
19
15
 
20
- // Initialize the SDK
21
- const sdk = new ResonanceSDK({
22
- apiUrl: 'https://api.fene.network',
23
- timeout: 30000, // Optional, default 30s
16
+ const client = createResonanceClient({
17
+ baseUrl: "https://api.fene.network",
24
18
  });
25
19
 
26
- // Get global network statistics
27
- const stats = await sdk.global.getStats();
28
- console.log('Total Network Stake:', stats.total_network_stake);
20
+ // Get network stats
21
+ const stats = await client.getNetworkStats();
22
+ console.log(`Total validators: ${stats.total_validators}`);
29
23
 
30
- // Get validator details
31
- const validator = await sdk.validators.get('0x1234...');
32
- console.log('Validator Status:', validator.status);
24
+ // Get APR
25
+ const apr = await client.getNetworkAPR();
26
+ console.log(`Network APR: ${apr.network_apr}%`);
33
27
  ```
34
28
 
35
29
  ## Authentication
36
30
 
37
- The SDK supports wallet-based authentication using Web3 providers:
38
-
39
31
  ```typescript
40
- import { ethers } from 'ethers';
41
- import { ResonanceSDK } from '@fenelabs/fene-sdk';
32
+ import { createResonanceClient } from "@resonance/sdk";
33
+ import { signMessage } from "viem/wallet";
42
34
 
43
- const sdk = new ResonanceSDK({
44
- apiUrl: 'https://api.fene.network',
35
+ const client = createResonanceClient({
36
+ baseUrl: "https://api.fene.network",
37
+ onTokenExpired: () => {
38
+ console.log("Token expired, please re-authenticate");
39
+ },
45
40
  });
46
41
 
47
- // Connect wallet (browser environment)
48
- const provider = new ethers.BrowserProvider(window.ethereum);
49
- const authResponse = await sdk.auth.connectWallet(provider, 'delegator');
42
+ // 1. Get nonce
43
+ const { message } = await client.getNonce("0x...");
50
44
 
51
- // Set the JWT token for authenticated requests
52
- sdk.setAuthToken(authResponse.token);
45
+ // 2. Sign message (using viem or wagmi)
46
+ const signature = await signMessage({ message });
53
47
 
54
- // Check authentication status
55
- if (sdk.isAuthenticated()) {
56
- console.log('User is authenticated');
57
- }
48
+ // 3. Verify and get JWT
49
+ const auth = await client.verify("0x...", signature);
50
+ console.log(`Logged in as: ${auth.role}`);
58
51
 
59
- // Logout
60
- sdk.logout();
52
+ // Now authenticated requests work
53
+ await client.updateGeoLocation({ latitude: 0, longitude: 0, node_type: "rpc" });
61
54
  ```
62
55
 
63
- ## API Reference
56
+ ## Error Handling
64
57
 
65
- ### Global Network Stats
58
+ The SDK provides structured error handling matching the API's error system:
66
59
 
67
60
  ```typescript
68
- // Get global network statistics
69
- const stats = await sdk.global.getStats();
70
-
71
- // Get network APR
72
- const apr = await sdk.global.getNetworkAPR();
73
-
74
- // Get network APR breakdown
75
- const breakdown = await sdk.global.getNetworkAPRBreakdown();
76
-
77
- // Get delegator leaderboard
78
- const delegatorLeaderboard = await sdk.global.getLeaderboardDelegators(10, 0);
79
-
80
- // Get validator leaderboard
81
- const validatorLeaderboard = await sdk.global.getLeaderboardValidators(10, 0);
82
- ```
83
-
84
- ### Validators
85
-
86
- ```typescript
87
- // Get all validators
88
- const allValidators = await sdk.validators.getAll();
89
-
90
- // Get specific validator details
91
- const validator = await sdk.validators.get('0x1234...');
92
-
93
- // Get validator delegators
94
- const delegators = await sdk.validators.getDelegators('0x1234...');
95
-
96
- // Get validator stake breakdown
97
- const stakeBreakdown = await sdk.validators.getStakeBreakdown('0x1234...');
98
-
99
- // Get validator epoch details
100
- const epochData = await sdk.validators.getEpoch('0x1234...', 100);
101
-
102
- // Get validator history
103
- const history = await sdk.validators.getHistory('0x1234...', 1, 100);
104
-
105
- // Get validator withdrawals
106
- const withdrawals = await sdk.validators.getWithdrawals('0x1234...', 50, 0);
107
-
108
- // Get validator metrics
109
- const metrics = await sdk.validators.getMetrics('0x1234...');
110
-
111
- // Get validator slashing events
112
- const slashing = await sdk.validators.getSlashing('0x1234...');
113
-
114
- // Get validator APR
115
- const validatorAPR = await sdk.validators.getAPR('0x1234...');
116
- ```
117
-
118
- ### Delegators
119
-
120
- ```typescript
121
- // Get all delegators
122
- const allDelegators = await sdk.delegators.getAll();
123
-
124
- // Get specific delegator details
125
- const delegator = await sdk.delegators.get('0xabcd...');
126
-
127
- // Get delegator stakes breakdown
128
- const stakes = await sdk.delegators.getStakes('0xabcd...');
129
-
130
- // Get delegator rewards history
131
- const rewards = await sdk.delegators.getRewards('0xabcd...', 50, 0);
61
+ import {
62
+ createResonanceClient,
63
+ ResonanceError,
64
+ ErrorCode,
65
+ isAuthError,
66
+ isNotFoundError,
67
+ } from "@resonance/sdk";
132
68
 
133
- // Get delegator withdrawals
134
- const withdrawals = await sdk.delegators.getWithdrawals('0xabcd...', 50, 0);
69
+ const client = createResonanceClient({ baseUrl: "https://api.fene.network" });
135
70
 
136
- // Get delegator unbonding status
137
- const unbonding = await sdk.delegators.getUnbonding('0xabcd...');
71
+ try {
72
+ const validator = await client.getValidator("0xinvalid");
73
+ } catch (error) {
74
+ if (error instanceof ResonanceError) {
75
+ console.log(`Error code: ${error.code}`);
76
+ console.log(`Message: ${error.message}`);
77
+ console.log(`Status: ${error.statusCode}`);
78
+
79
+ // Check specific error types
80
+ if (error.is(ErrorCode.VALIDATOR_NOT_FOUND)) {
81
+ // Handle validator not found
82
+ }
138
83
 
139
- // Get delegator active validators
140
- const validators = await sdk.delegators.getValidators('0xabcd...');
84
+ // Or use helper functions
85
+ if (isAuthError(error)) {
86
+ // Re-authenticate
87
+ } else if (isNotFoundError(error)) {
88
+ // Handle not found
89
+ }
90
+ }
91
+ }
141
92
  ```
142
93
 
143
- ### Referrals
144
-
145
- ```typescript
146
- // Validate a referral code
147
- const validation = await sdk.referrals.validate('REF123');
148
-
149
- // Create a new referral code (requires authentication)
150
- const referralCode = await sdk.referrals.create({
151
- validator_address: '0x1234...',
152
- max_quota: 100,
153
- expires_in_days: 30,
154
- });
155
-
156
- // Apply a referral code
157
- await sdk.referrals.apply({
158
- referral_code: 'REF123',
159
- delegator_address: '0xabcd...',
160
- });
161
-
162
- // Delete a referral code (requires authentication)
163
- await sdk.referrals.delete('REF123');
94
+ ### Error Codes
164
95
 
165
- // Unlink a delegator from referral (requires authentication)
166
- await sdk.referrals.unlink('0xabcd...');
96
+ The SDK recognizes these error codes from the API:
167
97
 
168
- // Get delegator referral information
169
- const delegatorRef = await sdk.referrals.getDelegatorReferral('0xabcd...');
98
+ - **Validator**: `VALIDATOR_NOT_FOUND`, `VALIDATOR_INACTIVE`
99
+ - **Delegator**: `DELEGATOR_NOT_FOUND`, `NOT_WHITELISTED`
100
+ - **Referral**: `REFERRAL_KEY_INVALID`, `REFERRAL_KEY_EXPIRED`, `REFERRAL_KEY_USED`
101
+ - **Auth**: `INVALID_SIGNATURE`, `NONCE_EXPIRED`, `UNAUTHORIZED`
102
+ - **Service**: `RPC_UNAVAILABLE`, `CACHE_UNAVAILABLE`, `DATABASE_UNAVAILABLE`
103
+ - **General**: `BAD_REQUEST`, `INTERNAL_ERROR`, `RATE_LIMITED`
170
104
 
171
- // Get validator referral information
172
- const validatorRef = await sdk.referrals.getValidatorReferral('0x1234...');
173
- ```
174
-
175
- ### Slashing
105
+ ## Architecture
176
106
 
177
- ```typescript
178
- // Get all slashing events
179
- const allEvents = await sdk.slashing.getEvents();
107
+ ### Caching
180
108
 
181
- // Get slashing events for a specific validator
182
- const validatorEvents = await sdk.slashing.getEvents('0x1234...', 50, 0);
183
- ```
109
+ The Resonance API implements **server-side Redis caching** with graceful degradation. The SDK does not implement client-side caching as all caching is handled by the API layer. This ensures:
184
110
 
185
- ### Analytics (Subgraph Data)
186
-
187
- The Analytics API provides access to aggregated and historical data indexed from the blockchain via The Graph subgraph. This data may have slight delays compared to real-time blockchain queries.
188
-
189
- ```typescript
190
- // Get protocol-level statistics
191
- const protocolStats = await sdk.analytics.getProtocolStats();
192
- console.log('Total Staking:', protocolStats.TotalStaking);
193
- console.log('Active Validators:', protocolStats.ActiveValidators);
194
-
195
- // Check sync status of analytics workers
196
- const syncStatus = await sdk.analytics.getSyncStatus();
197
- console.log('Protocol Sync Status:', syncStatus.protocol_sync.status);
198
- console.log('Last Synced Block:', syncStatus.protocol_sync.last_block);
199
-
200
- // Get all validators with analytics data (paginated)
201
- const validators = await sdk.analytics.getAllValidators({
202
- limit: 20,
203
- offset: 0,
204
- status: 'active',
205
- });
111
+ - Consistent data across all API consumers
112
+ - Reduced load on blockchain RPC nodes
113
+ - Automatic cache invalidation on chain state changes
114
+ - Cache TTLs optimized per endpoint (10s to 5min)
206
115
 
207
- // Get top validators by uptime
208
- const topValidators = await sdk.analytics.getTopValidators(10);
209
- topValidators.data.forEach((v, i) => {
210
- console.log(`#${i + 1}: ${v.moniker} - ${v.uptime}% uptime`);
211
- });
116
+ ### Authentication
212
117
 
213
- // Get specific validator analytics
214
- const validatorAnalytics = await sdk.analytics.getValidatorAnalytics('0x1234...');
215
- console.log('Uptime:', validatorAnalytics.uptime);
216
- console.log('Signed Blocks:', validatorAnalytics.signed_blocks);
217
- console.log('Total Stakers:', validatorAnalytics.total_stakers);
118
+ The SDK uses a standard Web3 authentication flow:
218
119
 
219
- // Get validator rewards with manual pagination (REQUIRED for this endpoint)
220
- const rewardsPage1 = await sdk.analytics.getValidatorRewards('0x1234...', {
221
- limit: 50,
222
- offset: 0,
223
- });
120
+ 1. Request a nonce from the API (`getNonce`)
121
+ 2. Sign the message with your wallet (using viem, wagmi, etc.)
122
+ 3. Submit signature for verification (`verify`)
123
+ 4. Receive JWT token for authenticated requests
224
124
 
225
- console.log('Total Rewards:', rewardsPage1.summary.total_rewards);
226
- console.log('Total Stakers:', rewardsPage1.summary.total_stakers);
227
- console.log('Has More Data:', rewardsPage1.metadata.has_more);
125
+ The token is automatically included in all subsequent requests and managed by the client.
228
126
 
229
- // Fetch next page if available
230
- if (rewardsPage1.metadata.has_more) {
231
- const rewardsPage2 = await sdk.analytics.getValidatorRewards('0x1234...', {
232
- limit: 50,
233
- offset: 50,
234
- });
235
- }
127
+ ## API Reference
236
128
 
237
- // Auto-pagination helper (use with caution - makes multiple API calls)
238
- const allRewards = await sdk.analytics.getAllValidatorRewards('0x1234...', {
239
- batchSize: 50,
240
- maxPages: 10, // Safety limit
241
- });
129
+ ### Auth
242
130
 
243
- console.log('Total Stakes Fetched:', allRewards.stakes.length);
244
- ```
131
+ - `getNonce(address)` - Get authentication nonce
132
+ - `verify(address, signature)` - Verify signature and get JWT
245
133
 
246
- **Important Notes:**
247
- - Analytics data is sourced from subgraph indexing and may lag behind real-time blockchain state
248
- - Always check `metadata.cached` and `metadata.stale` flags in responses
249
- - The rewards endpoint is heavy and **requires pagination** - never fetch without limit/offset
250
- - Use `getSyncStatus()` to verify data freshness before making critical decisions
134
+ ### Validators
251
135
 
252
- ### Analytics Helper Utilities
136
+ - `getValidators()` - Get all validators
137
+ - `getActiveValidators()` - Get active validators
138
+ - `getCandidates()` - Get validator candidates
139
+ - `getValidator(address)` - Get validator details
140
+ - `getValidatorDelegators(address)` - Get validator's delegators
253
141
 
254
- The SDK provides utility functions for working with analytics data:
142
+ ### Delegators
255
143
 
256
- ```typescript
257
- import {
258
- isValidatorNotFound,
259
- isStaleData,
260
- isCachedData,
261
- isSyncHealthy,
262
- getSyncLag,
263
- getDataFreshness,
264
- formatNumber,
265
- weiToEther,
266
- withRetry,
267
- } from '@avenbreaks/resonance-sdk';
268
-
269
- // Error handling
270
- try {
271
- const validator = await sdk.analytics.getValidatorAnalytics(address);
272
- } catch (error) {
273
- if (isValidatorNotFound(error)) {
274
- console.log('Validator does not exist');
275
- }
276
- }
144
+ - `getDelegator(address)` - Get delegator info
145
+ - `getDelegatorStakes(address)` - Get delegator stakes
146
+ - `getDelegatorRewards(address)` - Get delegator rewards
277
147
 
278
- // Data freshness validation
279
- const rewards = await sdk.analytics.getValidatorRewards(address, { limit: 50 });
280
- if (isStaleData(rewards)) {
281
- console.warn('Data may be outdated');
282
- }
148
+ ### Referral
283
149
 
284
- // Sync health monitoring
285
- const syncStatus = await sdk.analytics.getSyncStatus();
286
- if (isSyncHealthy(syncStatus, 'protocol_sync')) {
287
- console.log('Sync is healthy');
288
- }
150
+ - `getReferralKey(key)` - Get referral key info
151
+ - `getValidatorKeys(address)` - Get validator's referral keys
152
+ - `checkWhitelist(data)` - Check if whitelisted (requires auth)
289
153
 
290
- // Retry logic for heavy queries
291
- const rewardsWithRetry = await withRetry(
292
- () => sdk.analytics.getValidatorRewards(address, { limit: 100 }),
293
- {
294
- maxRetries: 3,
295
- initialDelay: 1000,
296
- onRetry: (error, attempt, delay) => {
297
- console.log(`Retry ${attempt} after ${delay}ms`);
298
- }
299
- }
300
- );
154
+ ### Geo
301
155
 
302
- // Number formatting
303
- const stats = await sdk.analytics.getProtocolStats();
304
- console.log(formatNumber(stats.TotalStaking)); // "26,883,345,073,055,930,973,683,712"
305
- console.log(weiToEther(stats.TotalStaking)); // "26883345.0730"
306
- ```
156
+ - `getGeoNodes()` - Get all geo nodes
157
+ - `getGeoValidators()` - Get validator locations
158
+ - `getGeoStats()` - Get geo statistics
159
+ - `updateGeoLocation(data)` - Update geo location (requires auth)
307
160
 
308
- ## Advanced Usage
161
+ ### Stats
309
162
 
310
- ### Custom Headers
163
+ - `getNetworkStats()` - Get network statistics
164
+ - `getCurrentEpoch()` - Get current epoch info
311
165
 
312
- ```typescript
313
- const sdk = new ResonanceSDK({
314
- apiUrl: 'https://api.fene.network',
315
- headers: {
316
- 'X-Custom-Header': 'value',
317
- },
318
- });
166
+ ### APR
319
167
 
320
- // Or set headers after initialization
321
- sdk.setHeader('X-API-Key', 'your-api-key');
322
- ```
168
+ - `getNetworkAPR()` - Get network-wide APR
169
+ - `getValidatorAPR(address)` - Get validator APR breakdown
323
170
 
324
- ### Error Handling
171
+ ### Storage
325
172
 
326
- ```typescript
327
- try {
328
- const validator = await sdk.validators.get('0x1234...');
329
- } catch (error) {
330
- if (error instanceof Error) {
331
- console.error('API Error:', error.message);
332
- }
333
- }
334
- ```
173
+ - `uploadAvatar(file)` - Upload avatar (requires auth)
174
+ - `getAvatar(address)` - Get avatar URL
335
175
 
336
- ### Timeout Configuration
176
+ ### Analytics
337
177
 
338
- ```typescript
339
- const sdk = new ResonanceSDK({
340
- apiUrl: 'https://api.fene.network',
341
- timeout: 60000, // 60 seconds
342
- });
343
- ```
178
+ - `getDailyBlockStats(days?)` - Get daily block stats
179
+ - `getValidatorRewardHistory(address, limit?)` - Get reward history
344
180
 
345
- ## TypeScript Support
181
+ ## Types
346
182
 
347
- The SDK is written in TypeScript and provides full type definitions:
183
+ All types are exported for TypeScript users:
348
184
 
349
185
  ```typescript
350
186
  import type {
351
- ValidatorDetailResponse,
352
- DelegatorDetailResponse,
353
- GlobalNetworkResponse,
354
- } from '@fenelabs/fene-sdk';
355
-
356
- const processValidator = (validator: ValidatorDetailResponse) => {
357
- console.log(validator.validator_address);
358
- console.log(validator.total_stake);
359
- };
360
- ```
361
-
362
- ## React Example
363
-
364
- ```typescript
365
- import { useEffect, useState } from 'react';
366
- import { ResonanceSDK } from '@fenelabs/fene-sdk';
367
-
368
- const sdk = new ResonanceSDK({
369
- apiUrl: 'https://api.fene.network',
370
- });
371
-
372
- function ValidatorList() {
373
- const [validators, setValidators] = useState([]);
374
- const [loading, setLoading] = useState(true);
375
-
376
- useEffect(() => {
377
- const fetchValidators = async () => {
378
- try {
379
- const data = await sdk.validators.getAll();
380
- setValidators(data);
381
- } catch (error) {
382
- console.error('Failed to fetch validators:', error);
383
- } finally {
384
- setLoading(false);
385
- }
386
- };
387
-
388
- fetchValidators();
389
- }, []);
390
-
391
- if (loading) return <div>Loading...</div>;
392
-
393
- return (
394
- <div>
395
- {validators.map((validator) => (
396
- <div key={validator.address}>{validator.address}</div>
397
- ))}
398
- </div>
399
- );
400
- }
401
- ```
402
-
403
- ## Next.js Example
404
-
405
- ```typescript
406
- // app/page.tsx
407
- import { ResonanceSDK } from '@fenelabs/fene-sdk';
408
-
409
- const sdk = new ResonanceSDK({
410
- apiUrl: process.env.NEXT_PUBLIC_API_URL || 'https://api.fene.network',
411
- });
412
-
413
- export default async function HomePage() {
414
- const stats = await sdk.global.getStats();
415
-
416
- return (
417
- <div>
418
- <h1>Network Stats</h1>
419
- <p>Total Validators: {stats.total_validators}</p>
420
- <p>Total Delegators: {stats.total_delegators}</p>
421
- <p>Total Stake: {stats.total_network_stake}</p>
422
- </div>
423
- );
424
- }
187
+ Validator,
188
+ Delegator,
189
+ NetworkStats,
190
+ ValidatorAPR,
191
+ // Error types
192
+ ErrorCodeType,
193
+ APIErrorResponse,
194
+ } from "@resonance/sdk";
195
+
196
+ // Error handling utilities
197
+ import {
198
+ ResonanceError,
199
+ ErrorCode,
200
+ isResonanceError,
201
+ hasErrorCode,
202
+ isAuthError,
203
+ isNetworkError,
204
+ isNotFoundError,
205
+ } from "@resonance/sdk";
425
206
  ```
426
207
 
427
- ## Node.js Example
208
+ ## Development
428
209
 
429
- ```typescript
430
- import { ResonanceSDK } from '@fenelabs/fene-sdk';
210
+ ### Running Tests
431
211
 
432
- const sdk = new ResonanceSDK({
433
- apiUrl: 'https://api.fene.network',
434
- });
435
-
436
- async function main() {
437
- // Get network statistics
438
- const stats = await sdk.global.getStats();
439
- console.log('Network Stats:', stats);
212
+ ```bash
213
+ # Run all tests
214
+ pnpm test
440
215
 
441
- // Get validator leaderboard
442
- const leaderboard = await sdk.global.getLeaderboardValidators(10);
443
- console.log('Top 10 Validators:', leaderboard);
444
- }
216
+ # Run tests in watch mode
217
+ pnpm test -- --watch
445
218
 
446
- main().catch(console.error);
219
+ # Run tests with coverage
220
+ pnpm test -- --coverage
447
221
  ```
448
222
 
449
- ## API Endpoints
450
-
451
- All API endpoints are available under the `/eth/v1` prefix. The SDK handles this automatically.
452
-
453
- | Module | Endpoint Pattern | Description |
454
- |--------|-----------------|-------------|
455
- | Global | `/eth/v1/global` | Network statistics and leaderboards |
456
- | Validators | `/eth/v1/validators/:address` | Validator information and history |
457
- | Delegators | `/eth/v1/delegators/:address` | Delegator information and history |
458
- | Referrals | `/eth/v1/referrals` | Referral code management |
459
- | Slashing | `/eth/v1/slashing/events` | Slashing events |
460
-
461
- ## Development
223
+ ### Building
462
224
 
463
225
  ```bash
464
- # Install dependencies
465
- pnpm install
466
-
467
226
  # Build the SDK
468
- pnpm build
227
+ pnpm run build
469
228
 
470
- # Run type checking
471
- pnpm type-check
229
+ # Watch mode for development
230
+ pnpm run dev
472
231
 
473
- # Watch mode (for development)
474
- pnpm dev
232
+ # Type checking
233
+ pnpm run lint
475
234
  ```
476
235
 
477
236
  ## License
478
237
 
479
238
  MIT
480
-
481
- ## Support
482
-
483
- For issues and questions, please visit:
484
- - GitHub Issues: https://github.com/fenelabs/fene-sdk/issues
485
- - Documentation: https://docs.fene.network