@sogni-ai/sogni-client 0.4.3 → 0.5.0-alpha.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.
@@ -0,0 +1,51 @@
1
+ import { ApiErrorResponse } from '../ApiClient';
2
+ import { Logger } from './DefaultLogger';
3
+ import TypedEventEmitter from './TypedEventEmitter';
4
+ /**
5
+ * Tokens object, containing the token and refresh token
6
+ * @typedef {Object} Tokens
7
+ * @property {string} [token] - The JWT token. Optonal, if missing it will be retrieved from the server
8
+ * @property {string} refreshToken - The refresh token
9
+ */
10
+ export interface Tokens {
11
+ token?: string;
12
+ refreshToken: string;
13
+ }
14
+ export type AuthUpdatedEvent = {
15
+ token: string;
16
+ refreshToken: string;
17
+ walletAddress: string;
18
+ } | {
19
+ token: null;
20
+ refreshToken: null;
21
+ walletAddress: null;
22
+ };
23
+ interface AuthManagerEvents {
24
+ updated: AuthUpdatedEvent;
25
+ refreshFailed: ApiErrorResponse;
26
+ }
27
+ declare class AuthManager extends TypedEventEmitter<AuthManagerEvents> {
28
+ private _token?;
29
+ private _tokenExpiresAt;
30
+ private _refreshToken?;
31
+ private _refreshTokenExpiresAt;
32
+ private _logger;
33
+ private _baseUrl;
34
+ private _walletAddress?;
35
+ private _renewTokenPromise?;
36
+ constructor(baseUrl: string, logger: Logger);
37
+ get refreshToken(): string | undefined;
38
+ get walletAddress(): string | undefined;
39
+ get isAuthenticated(): boolean;
40
+ private _updateCookies;
41
+ setTokens({ refreshToken, token }: {
42
+ refreshToken: string;
43
+ token?: string;
44
+ }): Promise<void>;
45
+ getToken(): Promise<string | undefined>;
46
+ renewToken(): Promise<string>;
47
+ clear(): void;
48
+ private _updateTokens;
49
+ private _renewToken;
50
+ }
51
+ export default AuthManager;
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const utils_1 = require("./utils");
16
+ const ApiClient_1 = require("../ApiClient");
17
+ const isNodejs_1 = __importDefault(require("./isNodejs"));
18
+ const js_cookie_1 = __importDefault(require("js-cookie"));
19
+ const TypedEventEmitter_1 = __importDefault(require("./TypedEventEmitter"));
20
+ class AuthManager extends TypedEventEmitter_1.default {
21
+ constructor(baseUrl, logger) {
22
+ super();
23
+ this._tokenExpiresAt = new Date(0);
24
+ this._refreshTokenExpiresAt = new Date(0);
25
+ this._logger = logger;
26
+ this._baseUrl = baseUrl;
27
+ }
28
+ get refreshToken() {
29
+ return this._refreshToken;
30
+ }
31
+ get walletAddress() {
32
+ return this._walletAddress;
33
+ }
34
+ get isAuthenticated() {
35
+ return !!this._refreshToken && this._refreshTokenExpiresAt > new Date();
36
+ }
37
+ _updateCookies() {
38
+ if (isNodejs_1.default) {
39
+ return;
40
+ }
41
+ const token = this._token;
42
+ if (token) {
43
+ js_cookie_1.default.set('authorization', token, {
44
+ domain: '.sogni.ai',
45
+ expires: 1
46
+ });
47
+ }
48
+ else {
49
+ js_cookie_1.default.remove('authorization', {
50
+ domain: '.sogni.ai'
51
+ });
52
+ }
53
+ }
54
+ setTokens(_a) {
55
+ return __awaiter(this, arguments, void 0, function* ({ refreshToken, token }) {
56
+ if (token) {
57
+ this._updateTokens({ token, refreshToken });
58
+ return;
59
+ }
60
+ this._refreshToken = refreshToken;
61
+ const { expiresAt: refreshExpiresAt } = (0, utils_1.decodeRefreshToken)(refreshToken);
62
+ this._refreshTokenExpiresAt = refreshExpiresAt;
63
+ yield this.renewToken();
64
+ });
65
+ }
66
+ getToken() {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ //If there is a token, and it is not expired, return it
69
+ if (this._token && this._tokenExpiresAt > new Date()) {
70
+ return this._token;
71
+ }
72
+ //If there is no refresh token, return undefined, to make unauthorized requests
73
+ if (!this._refreshToken) {
74
+ return;
75
+ }
76
+ //If there is a refresh token, try to renew the token
77
+ return this.renewToken();
78
+ });
79
+ }
80
+ renewToken() {
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ if (this._renewTokenPromise) {
83
+ return this._renewTokenPromise;
84
+ }
85
+ this._renewTokenPromise = this._renewToken();
86
+ this._renewTokenPromise.finally(() => {
87
+ this._renewTokenPromise = undefined;
88
+ });
89
+ return this._renewTokenPromise;
90
+ });
91
+ }
92
+ clear() {
93
+ // Prevent duplicate events
94
+ if (!this._token && !this._refreshToken) {
95
+ return;
96
+ }
97
+ this._refreshToken = undefined;
98
+ this._refreshTokenExpiresAt = new Date(0);
99
+ this._token = undefined;
100
+ this._tokenExpiresAt = new Date(0);
101
+ this._walletAddress = undefined;
102
+ this.emit('updated', { token: null, refreshToken: null, walletAddress: null });
103
+ }
104
+ _updateTokens({ token, refreshToken }) {
105
+ // Prevent duplicate events
106
+ if (this._token === token && this._refreshToken === refreshToken) {
107
+ return;
108
+ }
109
+ this._token = token;
110
+ const { expiresAt, walletAddress } = (0, utils_1.decodeToken)(token);
111
+ this._walletAddress = walletAddress;
112
+ this._tokenExpiresAt = expiresAt;
113
+ this._refreshToken = refreshToken;
114
+ const { expiresAt: refreshExpiresAt } = (0, utils_1.decodeRefreshToken)(refreshToken);
115
+ this._refreshTokenExpiresAt = refreshExpiresAt;
116
+ this._updateCookies();
117
+ this.emit('updated', { token, refreshToken, walletAddress });
118
+ }
119
+ _renewToken() {
120
+ return __awaiter(this, void 0, void 0, function* () {
121
+ if (this._refreshTokenExpiresAt < new Date()) {
122
+ throw new Error('Refresh token expired');
123
+ }
124
+ const url = new URL('/v1/account/refresh-token', this._baseUrl).toString();
125
+ const response = yield fetch(url, {
126
+ method: 'POST',
127
+ headers: {
128
+ 'Content-Type': 'application/json'
129
+ },
130
+ body: JSON.stringify({ refreshToken: this._refreshToken })
131
+ });
132
+ let responseData;
133
+ try {
134
+ responseData = yield response.json();
135
+ }
136
+ catch (e) {
137
+ this.emit('refreshFailed', {
138
+ status: 'error',
139
+ errorCode: 0,
140
+ message: 'Failed to parse response'
141
+ });
142
+ this._logger.error('Failed to parse response:', e);
143
+ throw new Error('Failed to parse response');
144
+ }
145
+ if (!response.ok) {
146
+ this.emit('refreshFailed', responseData);
147
+ this.clear();
148
+ throw new ApiClient_1.ApiError(response.status, responseData);
149
+ }
150
+ const { token, refreshToken } = responseData.data;
151
+ this._updateTokens({ token, refreshToken });
152
+ return this._token;
153
+ });
154
+ }
155
+ }
156
+ exports.default = AuthManager;
157
+ //# sourceMappingURL=AuthManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthManager.js","sourceRoot":"","sources":["../../src/lib/AuthManager.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,13 @@
1
1
  import TypedEventEmitter, { EventMap } from './TypedEventEmitter';
2
2
  import { JSONValue } from '../types/json';
3
3
  import { Logger } from './DefaultLogger';
4
- export interface AuthData {
5
- token: string;
6
- }
4
+ import AuthManager from './AuthManager';
7
5
  declare class RestClient<E extends EventMap = never> extends TypedEventEmitter<E> {
8
6
  readonly baseUrl: string;
9
- protected _auth: AuthData | null;
7
+ protected _auth: AuthManager;
10
8
  protected _logger: Logger;
11
- constructor(baseUrl: string, logger: Logger);
12
- get auth(): AuthData | null;
13
- set auth(auth: AuthData | null);
9
+ constructor(baseUrl: string, auth: AuthManager, logger: Logger);
10
+ get auth(): AuthManager;
14
11
  private formatUrl;
15
12
  private request;
16
13
  private processResponse;
@@ -15,18 +15,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  const ApiClient_1 = require("../ApiClient");
16
16
  const TypedEventEmitter_1 = __importDefault(require("./TypedEventEmitter"));
17
17
  class RestClient extends TypedEventEmitter_1.default {
18
- constructor(baseUrl, logger) {
18
+ constructor(baseUrl, auth, logger) {
19
19
  super();
20
- this._auth = null;
21
20
  this.baseUrl = baseUrl;
21
+ this._auth = auth;
22
22
  this._logger = logger;
23
23
  }
24
24
  get auth() {
25
25
  return this._auth;
26
26
  }
27
- set auth(auth) {
28
- this._auth = auth;
29
- }
30
27
  formatUrl(relativeUrl, query = {}) {
31
28
  const url = new URL(relativeUrl, this.baseUrl);
32
29
  Object.keys(query).forEach((key) => {
@@ -34,8 +31,11 @@ class RestClient extends TypedEventEmitter_1.default {
34
31
  });
35
32
  return url.toString();
36
33
  }
37
- request(url, options = {}) {
38
- return fetch(url, Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, (options.headers || {})), (this.auth ? { Authorization: this.auth.token } : {})) })).then((r) => this.processResponse(r));
34
+ request(url_1) {
35
+ return __awaiter(this, arguments, void 0, function* (url, options = {}) {
36
+ const token = yield this.auth.getToken();
37
+ return fetch(url, Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, (options.headers || {})), (token ? { Authorization: token } : {})) })).then((r) => this.processResponse(r));
38
+ });
39
39
  }
40
40
  processResponse(response) {
41
41
  return __awaiter(this, void 0, void 0, function* () {
@@ -1 +1 @@
1
- {"version":3,"file":"RestClient.js","sourceRoot":"","sources":["../../src/lib/RestClient.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,4CAA0D;AAC1D,4EAAkE;AAQlE,MAAM,UAAuC,SAAQ,2BAAoB;IAKvE,YAAY,OAAe,EAAE,MAAc;QACzC,KAAK,EAAE,CAAC;QAJA,UAAK,GAAoB,IAAI,CAAC;QAKtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,IAAI,CAAC,IAAqB;QAC5B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAEO,SAAS,CAAC,WAAmB,EAAE,QAAgC,EAAE;QACvE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACjC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAEO,OAAO,CAAgB,GAAW,EAAE,UAAuB,EAAE;QACnE,OAAO,KAAK,CAAC,GAAG,kCACX,OAAO,KACV,OAAO,kCACF,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,GACvB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAE1D,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAM,CAAC,CAAC;IAC/C,CAAC;IAEa,eAAe,CAAC,QAAkB;;YAC9C,IAAI,YAAY,CAAC;YACjB,IAAI,CAAC;gBACH,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACvC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,CAAC,CAAC,CAAC;gBACnD,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAC9C,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,oBAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAgC,CAAC,CAAC;YACxE,CAAC;YACD,OAAO,YAAyB,CAAC;QACnC,CAAC;KAAA;IAED,GAAG,CAAgB,IAAY,EAAE,QAA6B,EAAE;QAC9D,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,CAAgB,IAAY,EAAE,OAAgC,EAAE;QAClE,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;YAC3C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;IACL,CAAC;CACF;AAED,kBAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"RestClient.js","sourceRoot":"","sources":["../../src/lib/RestClient.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,4CAA0D;AAC1D,4EAAkE;AAKlE,MAAM,UAAuC,SAAQ,2BAAoB;IAKvE,YAAY,OAAe,EAAE,IAAiB,EAAE,MAAc;QAC5D,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAEO,SAAS,CAAC,WAAmB,EAAE,QAAgC,EAAE;QACvE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACjC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAEa,OAAO;6DAAgB,GAAW,EAAE,UAAuB,EAAE;YACzE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC,GAAG,kCACX,OAAO,KACV,OAAO,kCACF,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,GACvB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAE5C,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAM,CAAC,CAAC;QAC/C,CAAC;KAAA;IAEa,eAAe,CAAC,QAAkB;;YAC9C,IAAI,YAAY,CAAC;YACjB,IAAI,CAAC;gBACH,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACvC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,CAAC,CAAC,CAAC;gBACnD,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAC9C,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,oBAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAgC,CAAC,CAAC;YACxE,CAAC;YACD,OAAO,YAAyB,CAAC;QACnC,CAAC;KAAA;IAED,GAAG,CAAgB,IAAY,EAAE,QAA6B,EAAE;QAC9D,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,CAAgB,IAAY,EAAE,OAAgC,EAAE;QAClE,OAAO,IAAI,CAAC,OAAO,CAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;YAC3C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;IACL,CAAC;CACF;AAED,kBAAe,UAAU,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare function decodeToken(token: string): {
2
+ walletAddress: string;
3
+ expiresAt: Date;
4
+ };
5
+ export declare function decodeRefreshToken(token: string): {
6
+ env: string;
7
+ expiresAt: Date;
8
+ };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decodeToken = decodeToken;
4
+ exports.decodeRefreshToken = decodeRefreshToken;
5
+ const jwt_decode_1 = require("jwt-decode");
6
+ function decodeToken(token) {
7
+ const data = (0, jwt_decode_1.jwtDecode)(token);
8
+ return {
9
+ walletAddress: data.addr,
10
+ expiresAt: new Date(data.exp * 1000)
11
+ };
12
+ }
13
+ function decodeRefreshToken(token) {
14
+ const data = (0, jwt_decode_1.jwtDecode)(token);
15
+ return {
16
+ env: data.env,
17
+ expiresAt: new Date(data.exp * 1000)
18
+ };
19
+ }
20
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":";;AAEA,kCAMC;AAED,gDAMC;AAhBD,2CAAuC;AAEvC,SAAgB,WAAW,CAAC,KAAa;IACvC,MAAM,IAAI,GAAG,IAAA,sBAAS,EAA0D,KAAK,CAAC,CAAC;IACvF,OAAO;QACL,aAAa,EAAE,IAAI,CAAC,IAAI;QACxB,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAa;IAC9C,MAAM,IAAI,GAAG,IAAA,sBAAS,EAA0D,KAAK,CAAC,CAAC;IACvF,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;KACrC,CAAC;AACJ,CAAC"}
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const LIB_VERSION = "0.4.3";
1
+ export declare const LIB_VERSION = "0.5.0-alpha.1";
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LIB_VERSION = void 0;
4
- exports.LIB_VERSION = "0.4.3";
4
+ exports.LIB_VERSION = "0.5.0-alpha.1";
5
5
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAAa,QAAA,WAAW,GAAG,OAAO,CAAC"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAAa,QAAA,WAAW,GAAG,eAAe,CAAC"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.4.3",
6
+ "version": "0.5.0-alpha.1",
7
7
  "description": "Sogni Supernet Client",
8
8
  "main": "dist/index.js",
9
9
  "types": "dist/index.d.ts",
@@ -1,12 +1,10 @@
1
1
  import DataEntity from '../lib/DataEntity';
2
2
  import { BalanceData } from './types';
3
- import { jwtDecode } from 'jwt-decode';
4
3
  import { SupernetType } from '../ApiClient/WebSocketClient/types';
5
4
  /**
6
5
  * @inline
7
6
  */
8
7
  export interface AccountData {
9
- token: string | null;
10
8
  /**
11
9
  * Current network status:\
12
10
  * - `connected` - connected to the socket
@@ -21,13 +19,13 @@ export interface AccountData {
21
19
  network: SupernetType | null;
22
20
  balance: BalanceData;
23
21
  walletAddress?: string;
24
- expiresAt?: Date;
25
22
  username?: string;
23
+ token?: string;
24
+ refreshToken?: string;
26
25
  }
27
26
 
28
27
  function getDefaults(): AccountData {
29
28
  return {
30
- token: null,
31
29
  networkStatus: 'disconnected',
32
30
  network: null,
33
31
  balance: {
@@ -35,15 +33,11 @@ function getDefaults(): AccountData {
35
33
  debit: '0',
36
34
  net: '0',
37
35
  settled: '0'
38
- }
39
- };
40
- }
41
-
42
- function decodeToken(token: string) {
43
- const data = jwtDecode<{ addr: string; env: string; iat: number; exp: number }>(token);
44
- return {
45
- walletAddress: data.addr,
46
- expiresAt: new Date(data.exp * 1000)
36
+ },
37
+ walletAddress: undefined,
38
+ username: undefined,
39
+ token: undefined,
40
+ refreshToken: undefined
47
41
  };
48
42
  }
49
43
 
@@ -56,29 +50,10 @@ class CurrentAccount extends DataEntity<AccountData> {
56
50
  super(data || getDefaults());
57
51
  }
58
52
 
59
- _update<K extends keyof AccountData>(delta: Partial<AccountData>) {
60
- this.data = { ...this.data, ...(delta as Partial<AccountData>) };
61
- const keys = Object.keys(delta);
62
- if (delta.hasOwnProperty('token')) {
63
- if (delta.token) {
64
- Object.assign(this.data, decodeToken(delta.token));
65
- } else {
66
- delete this.data.walletAddress;
67
- delete this.data.expiresAt;
68
- }
69
- keys.push('walletAddress', 'expiresAt');
70
- }
71
- this.emit('updated', keys);
72
- }
73
-
74
53
  _clear() {
75
54
  this._update(getDefaults());
76
55
  }
77
56
 
78
- get isAuthenicated() {
79
- return !!this.data.token && !!this.data.expiresAt && this.data.expiresAt > new Date();
80
- }
81
-
82
57
  get networkStatus() {
83
58
  return this.data.networkStatus;
84
59
  }
@@ -95,10 +70,6 @@ class CurrentAccount extends DataEntity<AccountData> {
95
70
  return this.data.walletAddress;
96
71
  }
97
72
 
98
- get expiresAt() {
99
- return this.data.expiresAt;
100
- }
101
-
102
73
  get username() {
103
74
  return this.data.username;
104
75
  }
@@ -106,6 +77,10 @@ class CurrentAccount extends DataEntity<AccountData> {
106
77
  get token() {
107
78
  return this.data.token;
108
79
  }
80
+
81
+ get refreshToken() {
82
+ return this.data.refreshToken;
83
+ }
109
84
  }
110
85
 
111
86
  export default CurrentAccount;
@@ -14,6 +14,7 @@ import { Wallet, pbkdf2, toUtf8Bytes, Signature, parseEther } from 'ethers';
14
14
  import { ApiError, ApiReponse } from '../ApiClient';
15
15
  import CurrentAccount from './CurrentAccount';
16
16
  import { SupernetType } from '../ApiClient/WebSocketClient/types';
17
+ import { AuthUpdatedEvent, Tokens } from '../lib/AuthManager';
17
18
 
18
19
  /**
19
20
  * Account API methods that let you interact with the user's account.
@@ -34,6 +35,7 @@ class AccountApi extends ApiGroup {
34
35
  this.client.socket.on('balanceUpdate', this.handleBalanceUpdate.bind(this));
35
36
  this.client.on('connected', this.handleServerConnected.bind(this));
36
37
  this.client.on('disconnected', this.handleServerDisconnected.bind(this));
38
+ this.client.auth.on('updated', this.handleAuthUpdated.bind(this));
37
39
  }
38
40
 
39
41
  private handleBalanceUpdate(data: BalanceData) {
@@ -51,6 +53,14 @@ class AccountApi extends ApiGroup {
51
53
  this.currentAccount._clear();
52
54
  }
53
55
 
56
+ private handleAuthUpdated({ refreshToken, token, walletAddress }: AuthUpdatedEvent) {
57
+ if (!refreshToken) {
58
+ this.currentAccount._clear();
59
+ } else {
60
+ this.currentAccount._update({ walletAddress, token, refreshToken });
61
+ }
62
+ }
63
+
54
64
  private async getNonce(walletAddress: string): Promise<string> {
55
65
  const res = await this.client.rest.post<ApiReponse<Nonce>>('/v1/account/nonce', {
56
66
  walletAddress
@@ -111,12 +121,12 @@ class AccountApi extends ApiGroup {
111
121
  referralCode,
112
122
  signature
113
123
  });
114
- this.setToken(username, res.data.token);
124
+ await this.setToken(username, { refreshToken: res.data.refreshToken, token: res.data.token });
115
125
  return res.data;
116
126
  }
117
127
 
118
128
  /**
119
- * Restore session with username and access token.
129
+ * Restore session with username and refresh token.
120
130
  *
121
131
  * You can save access token that you get from the login method and restore the session with this method.
122
132
  *
@@ -138,13 +148,13 @@ class AccountApi extends ApiGroup {
138
148
  * ```
139
149
  *
140
150
  * @param username
141
- * @param token
151
+ * @param tokens - Refresh token, access token pair { refreshToken: string, token: string }
142
152
  */
143
- setToken(username: string, token: string): void {
144
- this.client.authenticate(token);
153
+ async setToken(username: string, tokens: Tokens): Promise<void> {
154
+ await this.client.authenticate(tokens);
145
155
  this.currentAccount._update({
146
- token,
147
- username
156
+ username,
157
+ walletAddress: this.client.auth.walletAddress
148
158
  });
149
159
  }
150
160
 
@@ -171,7 +181,7 @@ class AccountApi extends ApiGroup {
171
181
  walletAddress: wallet.address,
172
182
  signature
173
183
  });
174
- this.setToken(username, res.data.token);
184
+ await this.setToken(username, { refreshToken: res.data.refreshToken, token: res.data.token });
175
185
  return res.data;
176
186
  }
177
187
 
@@ -4,10 +4,12 @@ export interface Nonce {
4
4
 
5
5
  export interface AccountCreateData {
6
6
  token: string;
7
+ refreshToken: string;
7
8
  }
8
9
 
9
10
  export interface LoginData {
10
11
  token: string;
12
+ refreshToken: string;
11
13
  username: string;
12
14
  }
13
15
 
@@ -1,13 +1,13 @@
1
1
  import { MessageType, SocketMessageMap } from './messages';
2
2
  import { SocketEventMap } from './events';
3
- import RestClient, { AuthData } from '../../lib/RestClient';
3
+ import RestClient from '../../lib/RestClient';
4
4
  import { SupernetType } from './types';
5
5
  import WebSocket, { CloseEvent, ErrorEvent, MessageEvent } from 'isomorphic-ws';
6
6
  import { base64Decode, base64Encode } from '../../lib/base64';
7
7
  import isNodejs from '../../lib/isNodejs';
8
- import Cookie from 'js-cookie';
9
8
  import { LIB_VERSION } from '../../version';
10
9
  import { Logger } from '../../lib/DefaultLogger';
10
+ import AuthManager from '../../lib/AuthManager';
11
11
 
12
12
  const PING_INTERVAL = 15000;
13
13
 
@@ -18,34 +18,23 @@ class WebSocketClient extends RestClient<SocketEventMap> {
18
18
  private _supernetType: SupernetType;
19
19
  private _pingInterval: NodeJS.Timeout | null = null;
20
20
 
21
- constructor(baseUrl: string, appId: string, supernetType: SupernetType, logger: Logger) {
21
+ constructor(
22
+ baseUrl: string,
23
+ auth: AuthManager,
24
+ appId: string,
25
+ supernetType: SupernetType,
26
+ logger: Logger
27
+ ) {
22
28
  const _baseUrl = new URL(baseUrl);
23
29
  if (_baseUrl.protocol === 'wss:') {
24
30
  _baseUrl.protocol = 'https:';
25
31
  }
26
- super(_baseUrl.toString(), logger);
32
+ super(_baseUrl.toString(), auth, logger);
27
33
  this.appId = appId;
28
34
  this.baseUrl = _baseUrl.toString();
29
35
  this._supernetType = supernetType;
30
36
  }
31
37
 
32
- set auth(auth: AuthData | null) {
33
- //In browser, set the cookie
34
- if (!isNodejs) {
35
- if (auth) {
36
- Cookie.set('authorization', auth.token, {
37
- domain: '.sogni.ai',
38
- expires: 1
39
- });
40
- } else {
41
- Cookie.remove('authorization', {
42
- domain: '.sogni.ai'
43
- });
44
- }
45
- }
46
- this._auth = auth;
47
- }
48
-
49
38
  get supernetType(): SupernetType {
50
39
  return this._supernetType;
51
40
  }
@@ -54,7 +43,7 @@ class WebSocketClient extends RestClient<SocketEventMap> {
54
43
  return !!this.socket;
55
44
  }
56
45
 
57
- connect() {
46
+ async connect() {
58
47
  if (this.socket) {
59
48
  this.disconnect();
60
49
  }
@@ -71,7 +60,7 @@ class WebSocketClient extends RestClient<SocketEventMap> {
71
60
  if (isNodejs) {
72
61
  params = {
73
62
  headers: {
74
- Authorization: this._auth?.token,
63
+ Authorization: await this.auth.getToken(),
75
64
  'User-Agent': userAgent
76
65
  }
77
66
  };
@@ -114,7 +103,7 @@ class WebSocketClient extends RestClient<SocketEventMap> {
114
103
  }
115
104
 
116
105
  switchNetwork(supernetType: SupernetType): Promise<SupernetType> {
117
- return new Promise<SupernetType>(async (resolve, reject) => {
106
+ return new Promise<SupernetType>(async (resolve) => {
118
107
  this.once('changeNetwork', ({ network }) => {
119
108
  this._supernetType = network;
120
109
  resolve(network);