@fenelabs/fene-sdk 0.3.8 → 0.5.0

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,7 +19,7 @@ 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
25
  declare enum ValidatorStatus {
@@ -102,7 +102,7 @@ interface GeoNode {
102
102
  country: string;
103
103
  country_code: string;
104
104
  last_seen: string;
105
- node_type: 'validator' | 'rpc' | 'bootstrap';
105
+ node_type: "validator" | "rpc" | "bootstrap";
106
106
  online: boolean;
107
107
  }
108
108
  interface GeoStats {
@@ -124,6 +124,8 @@ interface NetworkStats {
124
124
  current_block: number;
125
125
  epoch: number;
126
126
  block_time: number;
127
+ min_stake_delegator: string;
128
+ min_stake_validator: string;
127
129
  }
128
130
  interface EpochInfo {
129
131
  number: number;
@@ -162,6 +164,42 @@ interface RewardHistory {
162
164
  amount: string;
163
165
  timestamp: string;
164
166
  }
167
+ interface Transaction {
168
+ id: number;
169
+ tx_hash: string;
170
+ block_number: number;
171
+ from_address: string;
172
+ to_address: string;
173
+ method_name: string;
174
+ method_selector: string;
175
+ value: string;
176
+ gas_used: number;
177
+ timestamp: number;
178
+ status: string;
179
+ }
180
+ interface TransactionsList {
181
+ transactions: Transaction[];
182
+ total: number;
183
+ page: number;
184
+ limit: number;
185
+ }
186
+ interface TransactionStats {
187
+ total_24h: number;
188
+ gas_used_24h: number;
189
+ }
190
+ interface TransactionsParams {
191
+ page?: number;
192
+ limit?: number;
193
+ method?: string;
194
+ address?: string;
195
+ sort?: "asc" | "desc";
196
+ }
197
+ interface PriceResponse {
198
+ price: number;
199
+ currency: string;
200
+ provider: string;
201
+ updated_at: number;
202
+ }
165
203
 
166
204
  interface RequestContext {
167
205
  method: string;
@@ -207,6 +245,7 @@ declare class ResonanceClient {
207
245
  private onRequest?;
208
246
  private onResponse?;
209
247
  private onError?;
248
+ private isRefreshing;
210
249
  constructor(config?: ResonanceClientConfig);
211
250
  setToken(token: string): void;
212
251
  clearToken(): void;
@@ -214,6 +253,19 @@ declare class ResonanceClient {
214
253
  private executeRequest;
215
254
  getNonce(address: Address): Promise<NonceResponse>;
216
255
  verify(params: AuthVerifyRequest): Promise<AuthResponse>;
256
+ /**
257
+ * Refresh the access token using the refresh token cookie.
258
+ * Returns true if refresh was successful.
259
+ */
260
+ refresh(): Promise<boolean>;
261
+ /**
262
+ * Logout and revoke current session.
263
+ */
264
+ logout(): Promise<void>;
265
+ /**
266
+ * Logout from all devices.
267
+ */
268
+ logoutAll(): Promise<void>;
217
269
  getValidators(): Promise<ValidatorSummary[]>;
218
270
  getActiveValidators(): Promise<ValidatorSummary[]>;
219
271
  getCandidates(): Promise<ValidatorSummary[]>;
@@ -237,6 +289,9 @@ declare class ResonanceClient {
237
289
  getAvatar(address: Address): Promise<AvatarResponse>;
238
290
  getDailyBlockStats(days?: number): Promise<DailyBlockStats[]>;
239
291
  getValidatorRewardHistory(address: Address, limit?: number): Promise<RewardHistory[]>;
292
+ getTransactions(params?: TransactionsParams): Promise<TransactionsList>;
293
+ getTransactionStats(): Promise<TransactionStats>;
294
+ getCoinPrice(): Promise<PriceResponse>;
240
295
  }
241
296
  declare function createResonanceClient(config: ResonanceClientConfig): ResonanceClient;
242
297
 
@@ -320,4 +375,4 @@ declare class EventBus {
320
375
  }
321
376
  declare const eventBus: EventBus;
322
377
 
323
- 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 };
378
+ 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 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,7 +19,7 @@ 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
25
  declare enum ValidatorStatus {
@@ -102,7 +102,7 @@ interface GeoNode {
102
102
  country: string;
103
103
  country_code: string;
104
104
  last_seen: string;
105
- node_type: 'validator' | 'rpc' | 'bootstrap';
105
+ node_type: "validator" | "rpc" | "bootstrap";
106
106
  online: boolean;
107
107
  }
108
108
  interface GeoStats {
@@ -124,6 +124,8 @@ interface NetworkStats {
124
124
  current_block: number;
125
125
  epoch: number;
126
126
  block_time: number;
127
+ min_stake_delegator: string;
128
+ min_stake_validator: string;
127
129
  }
128
130
  interface EpochInfo {
129
131
  number: number;
@@ -162,6 +164,42 @@ interface RewardHistory {
162
164
  amount: string;
163
165
  timestamp: string;
164
166
  }
167
+ interface Transaction {
168
+ id: number;
169
+ tx_hash: string;
170
+ block_number: number;
171
+ from_address: string;
172
+ to_address: string;
173
+ method_name: string;
174
+ method_selector: string;
175
+ value: string;
176
+ gas_used: number;
177
+ timestamp: number;
178
+ status: string;
179
+ }
180
+ interface TransactionsList {
181
+ transactions: Transaction[];
182
+ total: number;
183
+ page: number;
184
+ limit: number;
185
+ }
186
+ interface TransactionStats {
187
+ total_24h: number;
188
+ gas_used_24h: number;
189
+ }
190
+ interface TransactionsParams {
191
+ page?: number;
192
+ limit?: number;
193
+ method?: string;
194
+ address?: string;
195
+ sort?: "asc" | "desc";
196
+ }
197
+ interface PriceResponse {
198
+ price: number;
199
+ currency: string;
200
+ provider: string;
201
+ updated_at: number;
202
+ }
165
203
 
166
204
  interface RequestContext {
167
205
  method: string;
@@ -207,6 +245,7 @@ declare class ResonanceClient {
207
245
  private onRequest?;
208
246
  private onResponse?;
209
247
  private onError?;
248
+ private isRefreshing;
210
249
  constructor(config?: ResonanceClientConfig);
211
250
  setToken(token: string): void;
212
251
  clearToken(): void;
@@ -214,6 +253,19 @@ declare class ResonanceClient {
214
253
  private executeRequest;
215
254
  getNonce(address: Address): Promise<NonceResponse>;
216
255
  verify(params: AuthVerifyRequest): Promise<AuthResponse>;
256
+ /**
257
+ * Refresh the access token using the refresh token cookie.
258
+ * Returns true if refresh was successful.
259
+ */
260
+ refresh(): Promise<boolean>;
261
+ /**
262
+ * Logout and revoke current session.
263
+ */
264
+ logout(): Promise<void>;
265
+ /**
266
+ * Logout from all devices.
267
+ */
268
+ logoutAll(): Promise<void>;
217
269
  getValidators(): Promise<ValidatorSummary[]>;
218
270
  getActiveValidators(): Promise<ValidatorSummary[]>;
219
271
  getCandidates(): Promise<ValidatorSummary[]>;
@@ -237,6 +289,9 @@ declare class ResonanceClient {
237
289
  getAvatar(address: Address): Promise<AvatarResponse>;
238
290
  getDailyBlockStats(days?: number): Promise<DailyBlockStats[]>;
239
291
  getValidatorRewardHistory(address: Address, limit?: number): Promise<RewardHistory[]>;
292
+ getTransactions(params?: TransactionsParams): Promise<TransactionsList>;
293
+ getTransactionStats(): Promise<TransactionStats>;
294
+ getCoinPrice(): Promise<PriceResponse>;
240
295
  }
241
296
  declare function createResonanceClient(config: ResonanceClientConfig): ResonanceClient;
242
297
 
@@ -320,4 +375,4 @@ declare class EventBus {
320
375
  }
321
376
  declare const eventBus: EventBus;
322
377
 
323
- 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 };
378
+ 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 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
@@ -176,6 +176,7 @@ function getEnv(key) {
176
176
  }
177
177
  var ResonanceClient = class {
178
178
  constructor(config = {}) {
179
+ this.isRefreshing = false;
179
180
  validateConfig(config);
180
181
  const defaultUrl = "http://localhost:8080";
181
182
  const envUrl = getEnv(ENV_API_URL);
@@ -255,8 +256,17 @@ var ResonanceClient = class {
255
256
  });
256
257
  clearTimeout(timeoutId);
257
258
  const duration = Date.now() - startTime;
258
- if (response.status === 401) {
259
- eventBus.emit("api:unauthorized", { url, method: options.method || "GET" });
259
+ if (response.status === 401 && !this.isRefreshing) {
260
+ this.isRefreshing = true;
261
+ const refreshed = await this.refresh();
262
+ this.isRefreshing = false;
263
+ if (refreshed) {
264
+ return this.executeRequest(path, options, attemptNumber);
265
+ }
266
+ eventBus.emit("api:unauthorized", {
267
+ url,
268
+ method: options.method || "GET"
269
+ });
260
270
  this.onTokenExpired?.();
261
271
  }
262
272
  if (!response.ok) {
@@ -328,7 +338,7 @@ var ResonanceClient = class {
328
338
  return this.request(`/eth/v1/auth/nonce?address=${address}`);
329
339
  }
330
340
  async verify(params) {
331
- const result = await this.request("/eth/v1/auth/verify", {
341
+ return this.request("/eth/v1/auth/verify", {
332
342
  method: "POST",
333
343
  body: JSON.stringify({
334
344
  address: params.address,
@@ -336,8 +346,55 @@ var ResonanceClient = class {
336
346
  nonce: params.nonce
337
347
  })
338
348
  });
339
- this.token = result.token;
340
- return result;
349
+ }
350
+ /**
351
+ * Refresh the access token using the refresh token cookie.
352
+ * Returns true if refresh was successful.
353
+ */
354
+ async refresh() {
355
+ try {
356
+ const response = await fetch(`${this.baseUrl}/eth/v1/auth/refresh`, {
357
+ method: "POST",
358
+ credentials: "include",
359
+ // Send refresh_token cookie
360
+ headers: { "Content-Type": "application/json" }
361
+ });
362
+ if (response.ok) {
363
+ const data = await response.json();
364
+ return data.success === true;
365
+ }
366
+ return false;
367
+ } catch {
368
+ return false;
369
+ }
370
+ }
371
+ /**
372
+ * Logout and revoke current session.
373
+ */
374
+ async logout() {
375
+ try {
376
+ await fetch(`${this.baseUrl}/eth/v1/auth/logout`, {
377
+ method: "POST",
378
+ credentials: "include",
379
+ headers: { "Content-Type": "application/json" }
380
+ });
381
+ } catch {
382
+ }
383
+ this.token = void 0;
384
+ }
385
+ /**
386
+ * Logout from all devices.
387
+ */
388
+ async logoutAll() {
389
+ try {
390
+ await fetch(`${this.baseUrl}/eth/v1/auth/logout-all`, {
391
+ method: "POST",
392
+ credentials: "include",
393
+ headers: { "Content-Type": "application/json" }
394
+ });
395
+ } catch {
396
+ }
397
+ this.token = void 0;
341
398
  }
342
399
  // ============================================
343
400
  // Validators
@@ -453,6 +510,28 @@ var ResonanceClient = class {
453
510
  async getValidatorRewardHistory(address, limit = 100) {
454
511
  return this.request(`/eth/v1/analytics/rewards/${address}?limit=${limit}`);
455
512
  }
513
+ // ============================================
514
+ // Transactions (NEW)
515
+ // ============================================
516
+ async getTransactions(params = {}) {
517
+ const queryParams = new URLSearchParams();
518
+ if (params.page) queryParams.set("page", params.page.toString());
519
+ if (params.limit) queryParams.set("limit", params.limit.toString());
520
+ if (params.method) queryParams.set("method", params.method);
521
+ if (params.address) queryParams.set("address", params.address);
522
+ if (params.sort) queryParams.set("sort", params.sort);
523
+ const query = queryParams.toString();
524
+ return this.request(`/eth/v1/transactions${query ? `?${query}` : ""}`);
525
+ }
526
+ async getTransactionStats() {
527
+ return this.request("/eth/v1/transactions/stats");
528
+ }
529
+ // ============================================
530
+ // Price (NEW)
531
+ // ============================================
532
+ async getCoinPrice() {
533
+ return this.request("/eth/v1/price");
534
+ }
456
535
  };
457
536
  function createResonanceClient(config) {
458
537
  return new ResonanceClient(config);
package/dist/index.mjs CHANGED
@@ -140,6 +140,7 @@ function getEnv(key) {
140
140
  }
141
141
  var ResonanceClient = class {
142
142
  constructor(config = {}) {
143
+ this.isRefreshing = false;
143
144
  validateConfig(config);
144
145
  const defaultUrl = "http://localhost:8080";
145
146
  const envUrl = getEnv(ENV_API_URL);
@@ -219,8 +220,17 @@ var ResonanceClient = class {
219
220
  });
220
221
  clearTimeout(timeoutId);
221
222
  const duration = Date.now() - startTime;
222
- if (response.status === 401) {
223
- eventBus.emit("api:unauthorized", { url, method: options.method || "GET" });
223
+ if (response.status === 401 && !this.isRefreshing) {
224
+ this.isRefreshing = true;
225
+ const refreshed = await this.refresh();
226
+ this.isRefreshing = false;
227
+ if (refreshed) {
228
+ return this.executeRequest(path, options, attemptNumber);
229
+ }
230
+ eventBus.emit("api:unauthorized", {
231
+ url,
232
+ method: options.method || "GET"
233
+ });
224
234
  this.onTokenExpired?.();
225
235
  }
226
236
  if (!response.ok) {
@@ -292,7 +302,7 @@ var ResonanceClient = class {
292
302
  return this.request(`/eth/v1/auth/nonce?address=${address}`);
293
303
  }
294
304
  async verify(params) {
295
- const result = await this.request("/eth/v1/auth/verify", {
305
+ return this.request("/eth/v1/auth/verify", {
296
306
  method: "POST",
297
307
  body: JSON.stringify({
298
308
  address: params.address,
@@ -300,8 +310,55 @@ var ResonanceClient = class {
300
310
  nonce: params.nonce
301
311
  })
302
312
  });
303
- this.token = result.token;
304
- return result;
313
+ }
314
+ /**
315
+ * Refresh the access token using the refresh token cookie.
316
+ * Returns true if refresh was successful.
317
+ */
318
+ async refresh() {
319
+ try {
320
+ const response = await fetch(`${this.baseUrl}/eth/v1/auth/refresh`, {
321
+ method: "POST",
322
+ credentials: "include",
323
+ // Send refresh_token cookie
324
+ headers: { "Content-Type": "application/json" }
325
+ });
326
+ if (response.ok) {
327
+ const data = await response.json();
328
+ return data.success === true;
329
+ }
330
+ return false;
331
+ } catch {
332
+ return false;
333
+ }
334
+ }
335
+ /**
336
+ * Logout and revoke current session.
337
+ */
338
+ async logout() {
339
+ try {
340
+ await fetch(`${this.baseUrl}/eth/v1/auth/logout`, {
341
+ method: "POST",
342
+ credentials: "include",
343
+ headers: { "Content-Type": "application/json" }
344
+ });
345
+ } catch {
346
+ }
347
+ this.token = void 0;
348
+ }
349
+ /**
350
+ * Logout from all devices.
351
+ */
352
+ async logoutAll() {
353
+ try {
354
+ await fetch(`${this.baseUrl}/eth/v1/auth/logout-all`, {
355
+ method: "POST",
356
+ credentials: "include",
357
+ headers: { "Content-Type": "application/json" }
358
+ });
359
+ } catch {
360
+ }
361
+ this.token = void 0;
305
362
  }
306
363
  // ============================================
307
364
  // Validators
@@ -417,6 +474,28 @@ var ResonanceClient = class {
417
474
  async getValidatorRewardHistory(address, limit = 100) {
418
475
  return this.request(`/eth/v1/analytics/rewards/${address}?limit=${limit}`);
419
476
  }
477
+ // ============================================
478
+ // Transactions (NEW)
479
+ // ============================================
480
+ async getTransactions(params = {}) {
481
+ const queryParams = new URLSearchParams();
482
+ if (params.page) queryParams.set("page", params.page.toString());
483
+ if (params.limit) queryParams.set("limit", params.limit.toString());
484
+ if (params.method) queryParams.set("method", params.method);
485
+ if (params.address) queryParams.set("address", params.address);
486
+ if (params.sort) queryParams.set("sort", params.sort);
487
+ const query = queryParams.toString();
488
+ return this.request(`/eth/v1/transactions${query ? `?${query}` : ""}`);
489
+ }
490
+ async getTransactionStats() {
491
+ return this.request("/eth/v1/transactions/stats");
492
+ }
493
+ // ============================================
494
+ // Price (NEW)
495
+ // ============================================
496
+ async getCoinPrice() {
497
+ return this.request("/eth/v1/price");
498
+ }
420
499
  };
421
500
  function createResonanceClient(config) {
422
501
  return new ResonanceClient(config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenelabs/fene-sdk",
3
- "version": "0.3.8",
3
+ "version": "0.5.0",
4
4
  "description": "TypeScript SDK for Fene API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",