@fenelabs/fene-sdk 0.3.8 → 0.4.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
@@ -207,6 +207,7 @@ declare class ResonanceClient {
207
207
  private onRequest?;
208
208
  private onResponse?;
209
209
  private onError?;
210
+ private isRefreshing;
210
211
  constructor(config?: ResonanceClientConfig);
211
212
  setToken(token: string): void;
212
213
  clearToken(): void;
@@ -214,6 +215,19 @@ declare class ResonanceClient {
214
215
  private executeRequest;
215
216
  getNonce(address: Address): Promise<NonceResponse>;
216
217
  verify(params: AuthVerifyRequest): Promise<AuthResponse>;
218
+ /**
219
+ * Refresh the access token using the refresh token cookie.
220
+ * Returns true if refresh was successful.
221
+ */
222
+ refresh(): Promise<boolean>;
223
+ /**
224
+ * Logout and revoke current session.
225
+ */
226
+ logout(): Promise<void>;
227
+ /**
228
+ * Logout from all devices.
229
+ */
230
+ logoutAll(): Promise<void>;
217
231
  getValidators(): Promise<ValidatorSummary[]>;
218
232
  getActiveValidators(): Promise<ValidatorSummary[]>;
219
233
  getCandidates(): Promise<ValidatorSummary[]>;
package/dist/index.d.ts CHANGED
@@ -207,6 +207,7 @@ declare class ResonanceClient {
207
207
  private onRequest?;
208
208
  private onResponse?;
209
209
  private onError?;
210
+ private isRefreshing;
210
211
  constructor(config?: ResonanceClientConfig);
211
212
  setToken(token: string): void;
212
213
  clearToken(): void;
@@ -214,6 +215,19 @@ declare class ResonanceClient {
214
215
  private executeRequest;
215
216
  getNonce(address: Address): Promise<NonceResponse>;
216
217
  verify(params: AuthVerifyRequest): Promise<AuthResponse>;
218
+ /**
219
+ * Refresh the access token using the refresh token cookie.
220
+ * Returns true if refresh was successful.
221
+ */
222
+ refresh(): Promise<boolean>;
223
+ /**
224
+ * Logout and revoke current session.
225
+ */
226
+ logout(): Promise<void>;
227
+ /**
228
+ * Logout from all devices.
229
+ */
230
+ logoutAll(): Promise<void>;
217
231
  getValidators(): Promise<ValidatorSummary[]>;
218
232
  getActiveValidators(): Promise<ValidatorSummary[]>;
219
233
  getCandidates(): Promise<ValidatorSummary[]>;
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,7 +256,13 @@ var ResonanceClient = class {
255
256
  });
256
257
  clearTimeout(timeoutId);
257
258
  const duration = Date.now() - startTime;
258
- if (response.status === 401) {
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
+ }
259
266
  eventBus.emit("api:unauthorized", { url, method: options.method || "GET" });
260
267
  this.onTokenExpired?.();
261
268
  }
@@ -328,7 +335,7 @@ var ResonanceClient = class {
328
335
  return this.request(`/eth/v1/auth/nonce?address=${address}`);
329
336
  }
330
337
  async verify(params) {
331
- const result = await this.request("/eth/v1/auth/verify", {
338
+ return this.request("/eth/v1/auth/verify", {
332
339
  method: "POST",
333
340
  body: JSON.stringify({
334
341
  address: params.address,
@@ -336,8 +343,55 @@ var ResonanceClient = class {
336
343
  nonce: params.nonce
337
344
  })
338
345
  });
339
- this.token = result.token;
340
- return result;
346
+ }
347
+ /**
348
+ * Refresh the access token using the refresh token cookie.
349
+ * Returns true if refresh was successful.
350
+ */
351
+ async refresh() {
352
+ try {
353
+ const response = await fetch(`${this.baseUrl}/eth/v1/auth/refresh`, {
354
+ method: "POST",
355
+ credentials: "include",
356
+ // Send refresh_token cookie
357
+ headers: { "Content-Type": "application/json" }
358
+ });
359
+ if (response.ok) {
360
+ const data = await response.json();
361
+ return data.success === true;
362
+ }
363
+ return false;
364
+ } catch {
365
+ return false;
366
+ }
367
+ }
368
+ /**
369
+ * Logout and revoke current session.
370
+ */
371
+ async logout() {
372
+ try {
373
+ await fetch(`${this.baseUrl}/eth/v1/auth/logout`, {
374
+ method: "POST",
375
+ credentials: "include",
376
+ headers: { "Content-Type": "application/json" }
377
+ });
378
+ } catch {
379
+ }
380
+ this.token = void 0;
381
+ }
382
+ /**
383
+ * Logout from all devices.
384
+ */
385
+ async logoutAll() {
386
+ try {
387
+ await fetch(`${this.baseUrl}/eth/v1/auth/logout-all`, {
388
+ method: "POST",
389
+ credentials: "include",
390
+ headers: { "Content-Type": "application/json" }
391
+ });
392
+ } catch {
393
+ }
394
+ this.token = void 0;
341
395
  }
342
396
  // ============================================
343
397
  // Validators
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,7 +220,13 @@ var ResonanceClient = class {
219
220
  });
220
221
  clearTimeout(timeoutId);
221
222
  const duration = Date.now() - startTime;
222
- if (response.status === 401) {
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
+ }
223
230
  eventBus.emit("api:unauthorized", { url, method: options.method || "GET" });
224
231
  this.onTokenExpired?.();
225
232
  }
@@ -292,7 +299,7 @@ var ResonanceClient = class {
292
299
  return this.request(`/eth/v1/auth/nonce?address=${address}`);
293
300
  }
294
301
  async verify(params) {
295
- const result = await this.request("/eth/v1/auth/verify", {
302
+ return this.request("/eth/v1/auth/verify", {
296
303
  method: "POST",
297
304
  body: JSON.stringify({
298
305
  address: params.address,
@@ -300,8 +307,55 @@ var ResonanceClient = class {
300
307
  nonce: params.nonce
301
308
  })
302
309
  });
303
- this.token = result.token;
304
- return result;
310
+ }
311
+ /**
312
+ * Refresh the access token using the refresh token cookie.
313
+ * Returns true if refresh was successful.
314
+ */
315
+ async refresh() {
316
+ try {
317
+ const response = await fetch(`${this.baseUrl}/eth/v1/auth/refresh`, {
318
+ method: "POST",
319
+ credentials: "include",
320
+ // Send refresh_token cookie
321
+ headers: { "Content-Type": "application/json" }
322
+ });
323
+ if (response.ok) {
324
+ const data = await response.json();
325
+ return data.success === true;
326
+ }
327
+ return false;
328
+ } catch {
329
+ return false;
330
+ }
331
+ }
332
+ /**
333
+ * Logout and revoke current session.
334
+ */
335
+ async logout() {
336
+ try {
337
+ await fetch(`${this.baseUrl}/eth/v1/auth/logout`, {
338
+ method: "POST",
339
+ credentials: "include",
340
+ headers: { "Content-Type": "application/json" }
341
+ });
342
+ } catch {
343
+ }
344
+ this.token = void 0;
345
+ }
346
+ /**
347
+ * Logout from all devices.
348
+ */
349
+ async logoutAll() {
350
+ try {
351
+ await fetch(`${this.baseUrl}/eth/v1/auth/logout-all`, {
352
+ method: "POST",
353
+ credentials: "include",
354
+ headers: { "Content-Type": "application/json" }
355
+ });
356
+ } catch {
357
+ }
358
+ this.token = void 0;
305
359
  }
306
360
  // ============================================
307
361
  // Validators
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenelabs/fene-sdk",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "description": "TypeScript SDK for Fene API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",