@fenelabs/fene-sdk 0.3.0 → 0.3.3

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,429 +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();
61
+ import {
62
+ createResonanceClient,
63
+ ResonanceError,
64
+ ErrorCode,
65
+ isAuthError,
66
+ isNotFoundError,
67
+ } from "@resonance/sdk";
76
68
 
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();
69
+ const client = createResonanceClient({ baseUrl: "https://api.fene.network" });
89
70
 
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...');
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
+ }
83
+
84
+ // Or use helper functions
85
+ if (isAuthError(error)) {
86
+ // Re-authenticate
87
+ } else if (isNotFoundError(error)) {
88
+ // Handle not found
89
+ }
90
+ }
91
+ }
116
92
  ```
117
93
 
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...');
94
+ ### Error Codes
129
95
 
130
- // Get delegator rewards history
131
- const rewards = await sdk.delegators.getRewards('0xabcd...', 50, 0);
96
+ The SDK recognizes these error codes from the API:
132
97
 
133
- // Get delegator withdrawals
134
- const withdrawals = await sdk.delegators.getWithdrawals('0xabcd...', 50, 0);
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`
135
104
 
136
- // Get delegator unbonding status
137
- const unbonding = await sdk.delegators.getUnbonding('0xabcd...');
105
+ ## Architecture
138
106
 
139
- // Get delegator active validators
140
- const validators = await sdk.delegators.getValidators('0xabcd...');
141
- ```
142
-
143
- ### Referrals
107
+ ### Caching
144
108
 
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
- });
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:
155
110
 
156
- // Apply a referral code
157
- await sdk.referrals.apply({
158
- referral_code: 'REF123',
159
- delegator_address: '0xabcd...',
160
- });
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)
161
115
 
162
- // Delete a referral code (requires authentication)
163
- await sdk.referrals.delete('REF123');
116
+ ### Authentication
164
117
 
165
- // Unlink a delegator from referral (requires authentication)
166
- await sdk.referrals.unlink('0xabcd...');
118
+ The SDK uses a standard Web3 authentication flow:
167
119
 
168
- // Get delegator referral information
169
- const delegatorRef = await sdk.referrals.getDelegatorReferral('0xabcd...');
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
170
124
 
171
- // Get validator referral information
172
- const validatorRef = await sdk.referrals.getValidatorReferral('0x1234...');
173
- ```
125
+ The token is automatically included in all subsequent requests and managed by the client.
174
126
 
175
- ### Slashing
176
-
177
- ```typescript
178
- // Get all slashing events
179
- const allEvents = await sdk.slashing.getEvents();
180
-
181
- // Get slashing events for a specific validator
182
- const validatorEvents = await sdk.slashing.getEvents('0x1234...', 50, 0);
183
- ```
127
+ ## API Reference
184
128
 
185
- ### Analytics (Subgraph Data)
129
+ ### Auth
186
130
 
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.
131
+ - `getNonce(address)` - Get authentication nonce
132
+ - `verify(address, signature)` - Verify signature and get JWT
188
133
 
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
- });
206
-
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
- });
134
+ ### Validators
212
135
 
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);
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
218
141
 
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
- });
142
+ ### Delegators
224
143
 
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);
144
+ - `getDelegator(address)` - Get delegator info
145
+ - `getDelegatorStakes(address)` - Get delegator stakes
146
+ - `getDelegatorRewards(address)` - Get delegator rewards
228
147
 
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
- }
148
+ ### Referral
236
149
 
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
- });
150
+ - `getReferralKey(key)` - Get referral key info
151
+ - `getValidatorKeys(address)` - Get validator's referral keys
152
+ - `checkWhitelist(data)` - Check if whitelisted (requires auth)
242
153
 
243
- console.log('Total Stakes Fetched:', allRewards.stakes.length);
244
- ```
154
+ ### Geo
245
155
 
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
156
+ - `getGeoNodes()` - Get all geo nodes
157
+ - `getGeoValidators()` - Get validator locations
158
+ - `getGeoStats()` - Get geo statistics
159
+ - `updateGeoLocation(data)` - Update geo location (requires auth)
251
160
 
252
- ## Advanced Usage
161
+ ### Stats
253
162
 
254
- ### Custom Headers
163
+ - `getNetworkStats()` - Get network statistics
164
+ - `getCurrentEpoch()` - Get current epoch info
255
165
 
256
- ```typescript
257
- const sdk = new ResonanceSDK({
258
- apiUrl: 'https://api.fene.network',
259
- headers: {
260
- 'X-Custom-Header': 'value',
261
- },
262
- });
166
+ ### APR
263
167
 
264
- // Or set headers after initialization
265
- sdk.setHeader('X-API-Key', 'your-api-key');
266
- ```
168
+ - `getNetworkAPR()` - Get network-wide APR
169
+ - `getValidatorAPR(address)` - Get validator APR breakdown
267
170
 
268
- ### Error Handling
171
+ ### Storage
269
172
 
270
- ```typescript
271
- try {
272
- const validator = await sdk.validators.get('0x1234...');
273
- } catch (error) {
274
- if (error instanceof Error) {
275
- console.error('API Error:', error.message);
276
- }
277
- }
278
- ```
173
+ - `uploadAvatar(file)` - Upload avatar (requires auth)
174
+ - `getAvatar(address)` - Get avatar URL
279
175
 
280
- ### Timeout Configuration
176
+ ### Analytics
281
177
 
282
- ```typescript
283
- const sdk = new ResonanceSDK({
284
- apiUrl: 'https://api.fene.network',
285
- timeout: 60000, // 60 seconds
286
- });
287
- ```
178
+ - `getDailyBlockStats(days?)` - Get daily block stats
179
+ - `getValidatorRewardHistory(address, limit?)` - Get reward history
288
180
 
289
- ## TypeScript Support
181
+ ## Types
290
182
 
291
- The SDK is written in TypeScript and provides full type definitions:
183
+ All types are exported for TypeScript users:
292
184
 
293
185
  ```typescript
294
186
  import type {
295
- ValidatorDetailResponse,
296
- DelegatorDetailResponse,
297
- GlobalNetworkResponse,
298
- } from '@fenelabs/fene-sdk';
299
-
300
- const processValidator = (validator: ValidatorDetailResponse) => {
301
- console.log(validator.validator_address);
302
- console.log(validator.total_stake);
303
- };
304
- ```
305
-
306
- ## React Example
307
-
308
- ```typescript
309
- import { useEffect, useState } from 'react';
310
- import { ResonanceSDK } from '@fenelabs/fene-sdk';
311
-
312
- const sdk = new ResonanceSDK({
313
- apiUrl: 'https://api.fene.network',
314
- });
315
-
316
- function ValidatorList() {
317
- const [validators, setValidators] = useState([]);
318
- const [loading, setLoading] = useState(true);
319
-
320
- useEffect(() => {
321
- const fetchValidators = async () => {
322
- try {
323
- const data = await sdk.validators.getAll();
324
- setValidators(data);
325
- } catch (error) {
326
- console.error('Failed to fetch validators:', error);
327
- } finally {
328
- setLoading(false);
329
- }
330
- };
331
-
332
- fetchValidators();
333
- }, []);
334
-
335
- if (loading) return <div>Loading...</div>;
336
-
337
- return (
338
- <div>
339
- {validators.map((validator) => (
340
- <div key={validator.address}>{validator.address}</div>
341
- ))}
342
- </div>
343
- );
344
- }
345
- ```
346
-
347
- ## Next.js Example
348
-
349
- ```typescript
350
- // app/page.tsx
351
- import { ResonanceSDK } from '@fenelabs/fene-sdk';
352
-
353
- const sdk = new ResonanceSDK({
354
- apiUrl: process.env.NEXT_PUBLIC_API_URL || 'https://api.fene.network',
355
- });
356
-
357
- export default async function HomePage() {
358
- const stats = await sdk.global.getStats();
359
-
360
- return (
361
- <div>
362
- <h1>Network Stats</h1>
363
- <p>Total Validators: {stats.total_validators}</p>
364
- <p>Total Delegators: {stats.total_delegators}</p>
365
- <p>Total Stake: {stats.total_network_stake}</p>
366
- </div>
367
- );
368
- }
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";
369
206
  ```
370
207
 
371
- ## Node.js Example
372
-
373
- ```typescript
374
- import { ResonanceSDK } from '@fenelabs/fene-sdk';
208
+ ## Development
375
209
 
376
- const sdk = new ResonanceSDK({
377
- apiUrl: 'https://api.fene.network',
378
- });
210
+ ### Running Tests
379
211
 
380
- async function main() {
381
- // Get network statistics
382
- const stats = await sdk.global.getStats();
383
- console.log('Network Stats:', stats);
212
+ ```bash
213
+ # Run all tests
214
+ pnpm test
384
215
 
385
- // Get validator leaderboard
386
- const leaderboard = await sdk.global.getLeaderboardValidators(10);
387
- console.log('Top 10 Validators:', leaderboard);
388
- }
216
+ # Run tests in watch mode
217
+ pnpm test -- --watch
389
218
 
390
- main().catch(console.error);
219
+ # Run tests with coverage
220
+ pnpm test -- --coverage
391
221
  ```
392
222
 
393
- ## API Endpoints
394
-
395
- All API endpoints are available under the `/eth/v1` prefix. The SDK handles this automatically.
396
-
397
- | Module | Endpoint Pattern | Description |
398
- |--------|-----------------|-------------|
399
- | Global | `/eth/v1/global` | Network statistics and leaderboards |
400
- | Validators | `/eth/v1/validators/:address` | Validator information and history |
401
- | Delegators | `/eth/v1/delegators/:address` | Delegator information and history |
402
- | Referrals | `/eth/v1/referrals` | Referral code management |
403
- | Slashing | `/eth/v1/slashing/events` | Slashing events |
404
-
405
- ## Development
223
+ ### Building
406
224
 
407
225
  ```bash
408
- # Install dependencies
409
- pnpm install
410
-
411
226
  # Build the SDK
412
- pnpm build
227
+ pnpm run build
413
228
 
414
- # Run type checking
415
- pnpm type-check
229
+ # Watch mode for development
230
+ pnpm run dev
416
231
 
417
- # Watch mode (for development)
418
- pnpm dev
232
+ # Type checking
233
+ pnpm run lint
419
234
  ```
420
235
 
421
236
  ## License
422
237
 
423
238
  MIT
424
-
425
- ## Support
426
-
427
- For issues and questions, please visit:
428
- - GitHub Issues: https://github.com/fenelabs/fene-sdk/issues
429
- - Documentation: https://docs.fene.network