@fenelabs/fene-sdk 0.4.0 → 0.7.1

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/dist/index.d.mts CHANGED
@@ -19,9 +19,13 @@ interface AuthVerifyRequest {
19
19
  }
20
20
  interface AuthResponse {
21
21
  token: string;
22
- role: 'validator' | 'delegator';
22
+ role: "validator" | "delegator";
23
23
  expires_at: number;
24
24
  }
25
+ interface RefreshResponse {
26
+ success: boolean;
27
+ expires_at?: number;
28
+ }
25
29
  declare enum ValidatorStatus {
26
30
  NOT_EXIST = 0,
27
31
  CREATED = 1,
@@ -95,15 +99,13 @@ interface WhitelistCheckResponse {
95
99
  }
96
100
  interface GeoNode {
97
101
  address: string;
98
- ip: string;
99
- latitude: number;
100
- longitude: number;
101
- city: string;
102
+ role: "validator" | "delegator";
103
+ lat: number;
104
+ lng: number;
102
105
  country: string;
103
- country_code: string;
104
- last_seen: string;
105
- node_type: 'validator' | 'rpc' | 'bootstrap';
106
+ city?: string;
106
107
  online: boolean;
108
+ last_seen: number;
107
109
  }
108
110
  interface GeoStats {
109
111
  total_nodes: number;
@@ -112,9 +114,51 @@ interface GeoStats {
112
114
  cities: number;
113
115
  }
114
116
  interface GeoUpdateRequest {
117
+ lat: number;
118
+ lng: number;
119
+ }
120
+ interface GeoAutoDetectResponse {
121
+ success: boolean;
122
+ address: string;
123
+ role: "validator" | "delegator";
115
124
  latitude: number;
116
125
  longitude: number;
117
- node_type: string;
126
+ country: string;
127
+ city: string;
128
+ is_online: boolean;
129
+ }
130
+ interface UserProfile {
131
+ address: string;
132
+ roles: ("validator" | "delegator")[];
133
+ validator?: ValidatorProfileInfo;
134
+ delegations?: DelegationInfo[];
135
+ total_delegation_stake: string;
136
+ total_pending_rewards: string;
137
+ avatar_url?: string;
138
+ geo?: GeoLocation;
139
+ }
140
+ interface ValidatorProfileInfo {
141
+ address: string;
142
+ moniker: string;
143
+ self_stake: string;
144
+ total_stake: string;
145
+ commission_rate: number;
146
+ delegator_count: number;
147
+ claimable_reward: string;
148
+ apr: number;
149
+ }
150
+ interface DelegationInfo {
151
+ validator_address: string;
152
+ validator_moniker: string;
153
+ stake_amount: string;
154
+ pending_rewards: string;
155
+ apr: number;
156
+ }
157
+ interface GeoLocation {
158
+ lat: number;
159
+ lng: number;
160
+ country: string;
161
+ city?: string;
118
162
  }
119
163
  interface NetworkStats {
120
164
  total_validators: number;
@@ -124,6 +168,8 @@ interface NetworkStats {
124
168
  current_block: number;
125
169
  epoch: number;
126
170
  block_time: number;
171
+ min_stake_delegator: string;
172
+ min_stake_validator: string;
127
173
  }
128
174
  interface EpochInfo {
129
175
  number: number;
@@ -162,6 +208,42 @@ interface RewardHistory {
162
208
  amount: string;
163
209
  timestamp: string;
164
210
  }
211
+ interface Transaction {
212
+ id: number;
213
+ tx_hash: string;
214
+ block_number: number;
215
+ from_address: string;
216
+ to_address: string;
217
+ method_name: string;
218
+ method_selector: string;
219
+ value: string;
220
+ gas_used: number;
221
+ timestamp: number;
222
+ status: string;
223
+ }
224
+ interface TransactionsList {
225
+ transactions: Transaction[];
226
+ total: number;
227
+ page: number;
228
+ limit: number;
229
+ }
230
+ interface TransactionStats {
231
+ total_24h: number;
232
+ gas_used_24h: number;
233
+ }
234
+ interface TransactionsParams {
235
+ page?: number;
236
+ limit?: number;
237
+ method?: string;
238
+ address?: string;
239
+ sort?: "asc" | "desc";
240
+ }
241
+ interface PriceResponse {
242
+ price: number;
243
+ currency: string;
244
+ provider: string;
245
+ updated_at: number;
246
+ }
165
247
 
166
248
  interface RequestContext {
167
249
  method: string;
@@ -217,9 +299,9 @@ declare class ResonanceClient {
217
299
  verify(params: AuthVerifyRequest): Promise<AuthResponse>;
218
300
  /**
219
301
  * Refresh the access token using the refresh token cookie.
220
- * Returns true if refresh was successful.
302
+ * Returns { success: boolean, expires_at?: number }
221
303
  */
222
- refresh(): Promise<boolean>;
304
+ refresh(): Promise<RefreshResponse>;
223
305
  /**
224
306
  * Logout and revoke current session.
225
307
  */
@@ -239,10 +321,30 @@ declare class ResonanceClient {
239
321
  getReferralKey(key: string): Promise<ReferralKey>;
240
322
  getValidatorKeys(address: Address): Promise<ReferralKey[]>;
241
323
  checkWhitelist(data: WhitelistCheckRequest): Promise<WhitelistCheckResponse>;
242
- getGeoNodes(): Promise<GeoNode[]>;
243
- getGeoValidators(): Promise<GeoNode[]>;
324
+ /**
325
+ * Get user profile with roles, validator info, delegations, avatar, and geo
326
+ * @param address The user wallet address
327
+ */
328
+ getUserProfile(address: Address): Promise<UserProfile>;
329
+ /**
330
+ * Get user avatar URL
331
+ * @param address The user wallet address
332
+ */
333
+ getUserAvatar(address: Address): Promise<{
334
+ url: string;
335
+ }>;
336
+ /**
337
+ * Get all geo nodes, optionally filtered by role
338
+ * @param role Optional filter: "validator" or "delegator"
339
+ */
340
+ getGeoNodes(role?: "validator" | "delegator"): Promise<GeoNode[]>;
244
341
  getGeoStats(): Promise<GeoStats>;
245
342
  updateGeoLocation(data: GeoUpdateRequest): Promise<void>;
343
+ /**
344
+ * Auto-detect user geo location from IP and save to server.
345
+ * Should be called after successful login.
346
+ */
347
+ autoDetectGeo(): Promise<GeoAutoDetectResponse>;
246
348
  getNetworkStats(): Promise<NetworkStats>;
247
349
  getCurrentEpoch(): Promise<EpochInfo>;
248
350
  getNetworkAPR(): Promise<NetworkAPR>;
@@ -251,6 +353,9 @@ declare class ResonanceClient {
251
353
  getAvatar(address: Address): Promise<AvatarResponse>;
252
354
  getDailyBlockStats(days?: number): Promise<DailyBlockStats[]>;
253
355
  getValidatorRewardHistory(address: Address, limit?: number): Promise<RewardHistory[]>;
356
+ getTransactions(params?: TransactionsParams): Promise<TransactionsList>;
357
+ getTransactionStats(): Promise<TransactionStats>;
358
+ getCoinPrice(): Promise<PriceResponse>;
254
359
  }
255
360
  declare function createResonanceClient(config: ResonanceClientConfig): ResonanceClient;
256
361
 
@@ -334,4 +439,4 @@ declare class EventBus {
334
439
  }
335
440
  declare const eventBus: EventBus;
336
441
 
337
- export { type APIErrorResponse, type Address, type AuthResponse, type AuthVerifyRequest, type AvatarResponse, type DailyBlockStats, type Delegator, type DelegatorRewards, type DelegatorStake, DelegatorStatus, type EpochInfo, ErrorCode, type ErrorCodeType, type GeoNode, type GeoStats, type GeoUpdateRequest, type NetworkAPR, type NetworkStats, type NonceResponse, type PaginatedResponse, type ReferralKey, type RequestContext, ResonanceClient, type ResonanceClientConfig, ResonanceError, type ResponseContext, type RewardHistory, type UploadResponse, type Validator, type ValidatorAPR, ValidatorStatus, type ValidatorSummary, type WhitelistCheckRequest, type WhitelistCheckResponse, createResonanceClient, eventBus, hasErrorCode, isAuthError, isNetworkError, isNotFoundError, isResonanceError };
442
+ export { type APIErrorResponse, type Address, type AuthResponse, type AuthVerifyRequest, type AvatarResponse, type DailyBlockStats, type Delegator, type DelegatorRewards, type DelegatorStake, DelegatorStatus, type EpochInfo, ErrorCode, type ErrorCodeType, type GeoNode, type GeoStats, type GeoUpdateRequest, type NetworkAPR, type NetworkStats, type NonceResponse, type PaginatedResponse, type PriceResponse, type ReferralKey, type RefreshResponse, type RequestContext, ResonanceClient, type ResonanceClientConfig, ResonanceError, type ResponseContext, type RewardHistory, type Transaction, type TransactionStats, type TransactionsList, type TransactionsParams, type UploadResponse, type Validator, type ValidatorAPR, ValidatorStatus, type ValidatorSummary, type WhitelistCheckRequest, type WhitelistCheckResponse, createResonanceClient, eventBus, hasErrorCode, isAuthError, isNetworkError, isNotFoundError, isResonanceError };
package/dist/index.d.ts CHANGED
@@ -19,9 +19,13 @@ interface AuthVerifyRequest {
19
19
  }
20
20
  interface AuthResponse {
21
21
  token: string;
22
- role: 'validator' | 'delegator';
22
+ role: "validator" | "delegator";
23
23
  expires_at: number;
24
24
  }
25
+ interface RefreshResponse {
26
+ success: boolean;
27
+ expires_at?: number;
28
+ }
25
29
  declare enum ValidatorStatus {
26
30
  NOT_EXIST = 0,
27
31
  CREATED = 1,
@@ -95,15 +99,13 @@ interface WhitelistCheckResponse {
95
99
  }
96
100
  interface GeoNode {
97
101
  address: string;
98
- ip: string;
99
- latitude: number;
100
- longitude: number;
101
- city: string;
102
+ role: "validator" | "delegator";
103
+ lat: number;
104
+ lng: number;
102
105
  country: string;
103
- country_code: string;
104
- last_seen: string;
105
- node_type: 'validator' | 'rpc' | 'bootstrap';
106
+ city?: string;
106
107
  online: boolean;
108
+ last_seen: number;
107
109
  }
108
110
  interface GeoStats {
109
111
  total_nodes: number;
@@ -112,9 +114,51 @@ interface GeoStats {
112
114
  cities: number;
113
115
  }
114
116
  interface GeoUpdateRequest {
117
+ lat: number;
118
+ lng: number;
119
+ }
120
+ interface GeoAutoDetectResponse {
121
+ success: boolean;
122
+ address: string;
123
+ role: "validator" | "delegator";
115
124
  latitude: number;
116
125
  longitude: number;
117
- node_type: string;
126
+ country: string;
127
+ city: string;
128
+ is_online: boolean;
129
+ }
130
+ interface UserProfile {
131
+ address: string;
132
+ roles: ("validator" | "delegator")[];
133
+ validator?: ValidatorProfileInfo;
134
+ delegations?: DelegationInfo[];
135
+ total_delegation_stake: string;
136
+ total_pending_rewards: string;
137
+ avatar_url?: string;
138
+ geo?: GeoLocation;
139
+ }
140
+ interface ValidatorProfileInfo {
141
+ address: string;
142
+ moniker: string;
143
+ self_stake: string;
144
+ total_stake: string;
145
+ commission_rate: number;
146
+ delegator_count: number;
147
+ claimable_reward: string;
148
+ apr: number;
149
+ }
150
+ interface DelegationInfo {
151
+ validator_address: string;
152
+ validator_moniker: string;
153
+ stake_amount: string;
154
+ pending_rewards: string;
155
+ apr: number;
156
+ }
157
+ interface GeoLocation {
158
+ lat: number;
159
+ lng: number;
160
+ country: string;
161
+ city?: string;
118
162
  }
119
163
  interface NetworkStats {
120
164
  total_validators: number;
@@ -124,6 +168,8 @@ interface NetworkStats {
124
168
  current_block: number;
125
169
  epoch: number;
126
170
  block_time: number;
171
+ min_stake_delegator: string;
172
+ min_stake_validator: string;
127
173
  }
128
174
  interface EpochInfo {
129
175
  number: number;
@@ -162,6 +208,42 @@ interface RewardHistory {
162
208
  amount: string;
163
209
  timestamp: string;
164
210
  }
211
+ interface Transaction {
212
+ id: number;
213
+ tx_hash: string;
214
+ block_number: number;
215
+ from_address: string;
216
+ to_address: string;
217
+ method_name: string;
218
+ method_selector: string;
219
+ value: string;
220
+ gas_used: number;
221
+ timestamp: number;
222
+ status: string;
223
+ }
224
+ interface TransactionsList {
225
+ transactions: Transaction[];
226
+ total: number;
227
+ page: number;
228
+ limit: number;
229
+ }
230
+ interface TransactionStats {
231
+ total_24h: number;
232
+ gas_used_24h: number;
233
+ }
234
+ interface TransactionsParams {
235
+ page?: number;
236
+ limit?: number;
237
+ method?: string;
238
+ address?: string;
239
+ sort?: "asc" | "desc";
240
+ }
241
+ interface PriceResponse {
242
+ price: number;
243
+ currency: string;
244
+ provider: string;
245
+ updated_at: number;
246
+ }
165
247
 
166
248
  interface RequestContext {
167
249
  method: string;
@@ -217,9 +299,9 @@ declare class ResonanceClient {
217
299
  verify(params: AuthVerifyRequest): Promise<AuthResponse>;
218
300
  /**
219
301
  * Refresh the access token using the refresh token cookie.
220
- * Returns true if refresh was successful.
302
+ * Returns { success: boolean, expires_at?: number }
221
303
  */
222
- refresh(): Promise<boolean>;
304
+ refresh(): Promise<RefreshResponse>;
223
305
  /**
224
306
  * Logout and revoke current session.
225
307
  */
@@ -239,10 +321,30 @@ declare class ResonanceClient {
239
321
  getReferralKey(key: string): Promise<ReferralKey>;
240
322
  getValidatorKeys(address: Address): Promise<ReferralKey[]>;
241
323
  checkWhitelist(data: WhitelistCheckRequest): Promise<WhitelistCheckResponse>;
242
- getGeoNodes(): Promise<GeoNode[]>;
243
- getGeoValidators(): Promise<GeoNode[]>;
324
+ /**
325
+ * Get user profile with roles, validator info, delegations, avatar, and geo
326
+ * @param address The user wallet address
327
+ */
328
+ getUserProfile(address: Address): Promise<UserProfile>;
329
+ /**
330
+ * Get user avatar URL
331
+ * @param address The user wallet address
332
+ */
333
+ getUserAvatar(address: Address): Promise<{
334
+ url: string;
335
+ }>;
336
+ /**
337
+ * Get all geo nodes, optionally filtered by role
338
+ * @param role Optional filter: "validator" or "delegator"
339
+ */
340
+ getGeoNodes(role?: "validator" | "delegator"): Promise<GeoNode[]>;
244
341
  getGeoStats(): Promise<GeoStats>;
245
342
  updateGeoLocation(data: GeoUpdateRequest): Promise<void>;
343
+ /**
344
+ * Auto-detect user geo location from IP and save to server.
345
+ * Should be called after successful login.
346
+ */
347
+ autoDetectGeo(): Promise<GeoAutoDetectResponse>;
246
348
  getNetworkStats(): Promise<NetworkStats>;
247
349
  getCurrentEpoch(): Promise<EpochInfo>;
248
350
  getNetworkAPR(): Promise<NetworkAPR>;
@@ -251,6 +353,9 @@ declare class ResonanceClient {
251
353
  getAvatar(address: Address): Promise<AvatarResponse>;
252
354
  getDailyBlockStats(days?: number): Promise<DailyBlockStats[]>;
253
355
  getValidatorRewardHistory(address: Address, limit?: number): Promise<RewardHistory[]>;
356
+ getTransactions(params?: TransactionsParams): Promise<TransactionsList>;
357
+ getTransactionStats(): Promise<TransactionStats>;
358
+ getCoinPrice(): Promise<PriceResponse>;
254
359
  }
255
360
  declare function createResonanceClient(config: ResonanceClientConfig): ResonanceClient;
256
361
 
@@ -334,4 +439,4 @@ declare class EventBus {
334
439
  }
335
440
  declare const eventBus: EventBus;
336
441
 
337
- export { type APIErrorResponse, type Address, type AuthResponse, type AuthVerifyRequest, type AvatarResponse, type DailyBlockStats, type Delegator, type DelegatorRewards, type DelegatorStake, DelegatorStatus, type EpochInfo, ErrorCode, type ErrorCodeType, type GeoNode, type GeoStats, type GeoUpdateRequest, type NetworkAPR, type NetworkStats, type NonceResponse, type PaginatedResponse, type ReferralKey, type RequestContext, ResonanceClient, type ResonanceClientConfig, ResonanceError, type ResponseContext, type RewardHistory, type UploadResponse, type Validator, type ValidatorAPR, ValidatorStatus, type ValidatorSummary, type WhitelistCheckRequest, type WhitelistCheckResponse, createResonanceClient, eventBus, hasErrorCode, isAuthError, isNetworkError, isNotFoundError, isResonanceError };
442
+ export { type APIErrorResponse, type Address, type AuthResponse, type AuthVerifyRequest, type AvatarResponse, type DailyBlockStats, type Delegator, type DelegatorRewards, type DelegatorStake, DelegatorStatus, type EpochInfo, ErrorCode, type ErrorCodeType, type GeoNode, type GeoStats, type GeoUpdateRequest, type NetworkAPR, type NetworkStats, type NonceResponse, type PaginatedResponse, type PriceResponse, type ReferralKey, type RefreshResponse, type RequestContext, ResonanceClient, type ResonanceClientConfig, ResonanceError, type ResponseContext, type RewardHistory, type Transaction, type TransactionStats, type TransactionsList, type TransactionsParams, type UploadResponse, type Validator, type ValidatorAPR, ValidatorStatus, type ValidatorSummary, type WhitelistCheckRequest, type WhitelistCheckResponse, createResonanceClient, eventBus, hasErrorCode, isAuthError, isNetworkError, isNotFoundError, isResonanceError };
package/dist/index.js CHANGED
@@ -263,7 +263,10 @@ var ResonanceClient = class {
263
263
  if (refreshed) {
264
264
  return this.executeRequest(path, options, attemptNumber);
265
265
  }
266
- eventBus.emit("api:unauthorized", { url, method: options.method || "GET" });
266
+ eventBus.emit("api:unauthorized", {
267
+ url,
268
+ method: options.method || "GET"
269
+ });
267
270
  this.onTokenExpired?.();
268
271
  }
269
272
  if (!response.ok) {
@@ -346,7 +349,7 @@ var ResonanceClient = class {
346
349
  }
347
350
  /**
348
351
  * Refresh the access token using the refresh token cookie.
349
- * Returns true if refresh was successful.
352
+ * Returns { success: boolean, expires_at?: number }
350
353
  */
351
354
  async refresh() {
352
355
  try {
@@ -358,11 +361,14 @@ var ResonanceClient = class {
358
361
  });
359
362
  if (response.ok) {
360
363
  const data = await response.json();
361
- return data.success === true;
364
+ return {
365
+ success: data.success === true,
366
+ expires_at: data.expires_at
367
+ };
362
368
  }
363
- return false;
369
+ return { success: false };
364
370
  } catch {
365
- return false;
371
+ return { success: false };
366
372
  }
367
373
  }
368
374
  /**
@@ -439,13 +445,32 @@ var ResonanceClient = class {
439
445
  });
440
446
  }
441
447
  // ============================================
442
- // Geo
448
+ // User Profile
443
449
  // ============================================
444
- async getGeoNodes() {
445
- return this.request("/eth/v1/geo/nodes");
450
+ /**
451
+ * Get user profile with roles, validator info, delegations, avatar, and geo
452
+ * @param address The user wallet address
453
+ */
454
+ async getUserProfile(address) {
455
+ return this.request(`/eth/v1/user/${address}/profile`);
456
+ }
457
+ /**
458
+ * Get user avatar URL
459
+ * @param address The user wallet address
460
+ */
461
+ async getUserAvatar(address) {
462
+ return this.request(`/eth/v1/user/${address}/avatar`);
446
463
  }
447
- async getGeoValidators() {
448
- return this.request("/eth/v1/geo/validators");
464
+ // ============================================
465
+ // Geo
466
+ // ============================================
467
+ /**
468
+ * Get all geo nodes, optionally filtered by role
469
+ * @param role Optional filter: "validator" or "delegator"
470
+ */
471
+ async getGeoNodes(role) {
472
+ const params = role ? `?role=${role}` : "";
473
+ return this.request(`/eth/v1/geo/nodes${params}`);
449
474
  }
450
475
  async getGeoStats() {
451
476
  return this.request("/eth/v1/geo/stats");
@@ -456,6 +481,15 @@ var ResonanceClient = class {
456
481
  body: JSON.stringify(data)
457
482
  });
458
483
  }
484
+ /**
485
+ * Auto-detect user geo location from IP and save to server.
486
+ * Should be called after successful login.
487
+ */
488
+ async autoDetectGeo() {
489
+ return this.request("/eth/v1/geo/auto-detect", {
490
+ method: "POST"
491
+ });
492
+ }
459
493
  // ============================================
460
494
  // Stats
461
495
  // ============================================
@@ -507,6 +541,28 @@ var ResonanceClient = class {
507
541
  async getValidatorRewardHistory(address, limit = 100) {
508
542
  return this.request(`/eth/v1/analytics/rewards/${address}?limit=${limit}`);
509
543
  }
544
+ // ============================================
545
+ // Transactions (NEW)
546
+ // ============================================
547
+ async getTransactions(params = {}) {
548
+ const queryParams = new URLSearchParams();
549
+ if (params.page) queryParams.set("page", params.page.toString());
550
+ if (params.limit) queryParams.set("limit", params.limit.toString());
551
+ if (params.method) queryParams.set("method", params.method);
552
+ if (params.address) queryParams.set("address", params.address);
553
+ if (params.sort) queryParams.set("sort", params.sort);
554
+ const query = queryParams.toString();
555
+ return this.request(`/eth/v1/transactions${query ? `?${query}` : ""}`);
556
+ }
557
+ async getTransactionStats() {
558
+ return this.request("/eth/v1/transactions/stats");
559
+ }
560
+ // ============================================
561
+ // Price (NEW)
562
+ // ============================================
563
+ async getCoinPrice() {
564
+ return this.request("/eth/v1/price");
565
+ }
510
566
  };
511
567
  function createResonanceClient(config) {
512
568
  return new ResonanceClient(config);
package/dist/index.mjs CHANGED
@@ -227,7 +227,10 @@ var ResonanceClient = class {
227
227
  if (refreshed) {
228
228
  return this.executeRequest(path, options, attemptNumber);
229
229
  }
230
- eventBus.emit("api:unauthorized", { url, method: options.method || "GET" });
230
+ eventBus.emit("api:unauthorized", {
231
+ url,
232
+ method: options.method || "GET"
233
+ });
231
234
  this.onTokenExpired?.();
232
235
  }
233
236
  if (!response.ok) {
@@ -310,7 +313,7 @@ var ResonanceClient = class {
310
313
  }
311
314
  /**
312
315
  * Refresh the access token using the refresh token cookie.
313
- * Returns true if refresh was successful.
316
+ * Returns { success: boolean, expires_at?: number }
314
317
  */
315
318
  async refresh() {
316
319
  try {
@@ -322,11 +325,14 @@ var ResonanceClient = class {
322
325
  });
323
326
  if (response.ok) {
324
327
  const data = await response.json();
325
- return data.success === true;
328
+ return {
329
+ success: data.success === true,
330
+ expires_at: data.expires_at
331
+ };
326
332
  }
327
- return false;
333
+ return { success: false };
328
334
  } catch {
329
- return false;
335
+ return { success: false };
330
336
  }
331
337
  }
332
338
  /**
@@ -403,13 +409,32 @@ var ResonanceClient = class {
403
409
  });
404
410
  }
405
411
  // ============================================
406
- // Geo
412
+ // User Profile
407
413
  // ============================================
408
- async getGeoNodes() {
409
- return this.request("/eth/v1/geo/nodes");
414
+ /**
415
+ * Get user profile with roles, validator info, delegations, avatar, and geo
416
+ * @param address The user wallet address
417
+ */
418
+ async getUserProfile(address) {
419
+ return this.request(`/eth/v1/user/${address}/profile`);
420
+ }
421
+ /**
422
+ * Get user avatar URL
423
+ * @param address The user wallet address
424
+ */
425
+ async getUserAvatar(address) {
426
+ return this.request(`/eth/v1/user/${address}/avatar`);
410
427
  }
411
- async getGeoValidators() {
412
- return this.request("/eth/v1/geo/validators");
428
+ // ============================================
429
+ // Geo
430
+ // ============================================
431
+ /**
432
+ * Get all geo nodes, optionally filtered by role
433
+ * @param role Optional filter: "validator" or "delegator"
434
+ */
435
+ async getGeoNodes(role) {
436
+ const params = role ? `?role=${role}` : "";
437
+ return this.request(`/eth/v1/geo/nodes${params}`);
413
438
  }
414
439
  async getGeoStats() {
415
440
  return this.request("/eth/v1/geo/stats");
@@ -420,6 +445,15 @@ var ResonanceClient = class {
420
445
  body: JSON.stringify(data)
421
446
  });
422
447
  }
448
+ /**
449
+ * Auto-detect user geo location from IP and save to server.
450
+ * Should be called after successful login.
451
+ */
452
+ async autoDetectGeo() {
453
+ return this.request("/eth/v1/geo/auto-detect", {
454
+ method: "POST"
455
+ });
456
+ }
423
457
  // ============================================
424
458
  // Stats
425
459
  // ============================================
@@ -471,6 +505,28 @@ var ResonanceClient = class {
471
505
  async getValidatorRewardHistory(address, limit = 100) {
472
506
  return this.request(`/eth/v1/analytics/rewards/${address}?limit=${limit}`);
473
507
  }
508
+ // ============================================
509
+ // Transactions (NEW)
510
+ // ============================================
511
+ async getTransactions(params = {}) {
512
+ const queryParams = new URLSearchParams();
513
+ if (params.page) queryParams.set("page", params.page.toString());
514
+ if (params.limit) queryParams.set("limit", params.limit.toString());
515
+ if (params.method) queryParams.set("method", params.method);
516
+ if (params.address) queryParams.set("address", params.address);
517
+ if (params.sort) queryParams.set("sort", params.sort);
518
+ const query = queryParams.toString();
519
+ return this.request(`/eth/v1/transactions${query ? `?${query}` : ""}`);
520
+ }
521
+ async getTransactionStats() {
522
+ return this.request("/eth/v1/transactions/stats");
523
+ }
524
+ // ============================================
525
+ // Price (NEW)
526
+ // ============================================
527
+ async getCoinPrice() {
528
+ return this.request("/eth/v1/price");
529
+ }
474
530
  };
475
531
  function createResonanceClient(config) {
476
532
  return new ResonanceClient(config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenelabs/fene-sdk",
3
- "version": "0.4.0",
3
+ "version": "0.7.1",
4
4
  "description": "TypeScript SDK for Fene API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -20,6 +20,7 @@
20
20
  "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
21
21
  "lint": "tsc --noEmit",
22
22
  "test": "vitest run",
23
+ "watch": "esbuild src/app.ts --bundle --sourcemap --outdir=www --servedir=www --watch",
23
24
  "prepublishOnly": "pnpm run build"
24
25
  },
25
26
  "keywords": [
@@ -33,9 +34,17 @@
33
34
  "license": "MIT",
34
35
  "repository": {
35
36
  "type": "git",
36
- "url": "https://github.com/fenelabs/fene-sdk"
37
+ "url": "https://github.com/fenelabs/fene-sdk.git"
38
+ },
39
+ "publishConfig": {
40
+ "registry": "https://registry.npmjs.org/",
41
+ "access": "public"
42
+ },
43
+ "dependencies": {
44
+ "esbuild": ">=0.25.0"
37
45
  },
38
46
  "devDependencies": {
47
+ "esbuild": "^0.25.2",
39
48
  "@types/node": "^25.0.3",
40
49
  "tsup": "^8.0.0",
41
50
  "typescript": "^5.3.0",