@formo/analytics 1.11.5-alpha.4 → 1.11.6

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.
Files changed (57) hide show
  1. package/README.md +131 -39
  2. package/dist/cjs/src/FormoAnalytics.d.ts +72 -2
  3. package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
  4. package/dist/cjs/src/FormoAnalytics.js +282 -5
  5. package/dist/cjs/src/FormoAnalytics.js.map +1 -1
  6. package/dist/cjs/src/constants/events.d.ts +8 -0
  7. package/dist/cjs/src/constants/events.d.ts.map +1 -0
  8. package/dist/cjs/src/constants/events.js +12 -0
  9. package/dist/cjs/src/constants/events.js.map +1 -0
  10. package/dist/cjs/src/constants/index.d.ts +1 -0
  11. package/dist/cjs/src/constants/index.d.ts.map +1 -1
  12. package/dist/cjs/src/constants/index.js +1 -0
  13. package/dist/cjs/src/constants/index.js.map +1 -1
  14. package/dist/cjs/src/types/base.d.ts +1 -0
  15. package/dist/cjs/src/types/base.d.ts.map +1 -1
  16. package/dist/cjs/src/types/index.d.ts +1 -0
  17. package/dist/cjs/src/types/index.d.ts.map +1 -1
  18. package/dist/cjs/src/types/index.js +1 -0
  19. package/dist/cjs/src/types/index.js.map +1 -1
  20. package/dist/cjs/src/types/wallet.d.ts +11 -0
  21. package/dist/cjs/src/types/wallet.d.ts.map +1 -0
  22. package/dist/cjs/src/types/wallet.js +3 -0
  23. package/dist/cjs/src/types/wallet.js.map +1 -0
  24. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  25. package/dist/esm/src/FormoAnalytics.d.ts +72 -2
  26. package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
  27. package/dist/esm/src/FormoAnalytics.js +283 -6
  28. package/dist/esm/src/FormoAnalytics.js.map +1 -1
  29. package/dist/esm/src/constants/events.d.ts +8 -0
  30. package/dist/esm/src/constants/events.d.ts.map +1 -0
  31. package/dist/esm/src/constants/events.js +9 -0
  32. package/dist/esm/src/constants/events.js.map +1 -0
  33. package/dist/esm/src/constants/index.d.ts +1 -0
  34. package/dist/esm/src/constants/index.d.ts.map +1 -1
  35. package/dist/esm/src/constants/index.js +1 -0
  36. package/dist/esm/src/constants/index.js.map +1 -1
  37. package/dist/esm/src/types/base.d.ts +1 -0
  38. package/dist/esm/src/types/base.d.ts.map +1 -1
  39. package/dist/esm/src/types/index.d.ts +1 -0
  40. package/dist/esm/src/types/index.d.ts.map +1 -1
  41. package/dist/esm/src/types/index.js +1 -0
  42. package/dist/esm/src/types/index.js.map +1 -1
  43. package/dist/esm/src/types/wallet.d.ts +11 -0
  44. package/dist/esm/src/types/wallet.d.ts.map +1 -0
  45. package/dist/esm/src/types/wallet.js +2 -0
  46. package/dist/esm/src/types/wallet.js.map +1 -0
  47. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  48. package/dist/index.umd.min.js +1 -1
  49. package/dist/index.umd.min.js.map +1 -1
  50. package/package.json +1 -1
  51. package/src/FormoAnalytics.ts +322 -6
  52. package/src/constants/events.ts +7 -0
  53. package/src/constants/index.ts +1 -0
  54. package/src/global.d.ts +4 -0
  55. package/src/types/base.ts +2 -0
  56. package/src/types/index.ts +1 -0
  57. package/src/types/wallet.ts +12 -0
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ---
6
6
 
7
- Add the following to your `index.html`:
7
+ Add the following to your page:
8
8
 
9
9
  ```html
10
10
  <script>
@@ -33,21 +33,96 @@ Add the following to your `index.html`:
33
33
 
34
34
  ---
35
35
 
36
- ### 1. Install the npm package:
36
+ ### React Application
37
37
 
38
- Install @formo/analytics via yarn or npm:
38
+ **1. Install the SDK**
39
+ Install the Formo Analytics SDK using Yarn or NPM:
39
40
 
40
- ```
41
+ ```jsx
41
42
  yarn add @formo/analytics
42
43
  ```
43
44
 
44
45
  or
45
46
 
47
+ ```jsx
48
+ npm install @formo/analytics --save
49
+ ```
50
+
51
+ **2. Set up FormoAnalyticsProvider in Your Application**
52
+
53
+ Wrap your entire React application in the `FormoAnalyticsProvider` provided by the SDK.
54
+
55
+ ```jsx
56
+ //App.tsx (or App.js)
57
+ import React from 'react';
58
+ import ReactDOM from 'react-dom/client';
59
+ import { FormoAnalyticsProvider } from '@formo/analytics';
60
+ import App from './App';
61
+
62
+ const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
63
+
64
+ root.render(
65
+ <React.StrictMode>
66
+ <FormoAnalyticsProvider apiKey="YOUR_API_KEY" projectId="YOUR_PROJECT_ID">
67
+ <App />
68
+ </FormoAnalyticsProvider>
69
+ </React.StrictMode>
70
+ );
46
71
  ```
72
+
73
+ **3. Tracking Events and Page Views**
74
+
75
+ You can use the `useFormoAnalytics` hook from the SDK to track user interactions and page views.
76
+
77
+ Example: Tracking a Page View and Custom Event
78
+
79
+ ```jsx
80
+ import React, { useEffect } from 'react';
81
+ import { useFormoAnalytics } from '@formo/analytics';
82
+
83
+ const HomePage = () => {
84
+ const analytics = useFormoAnalytics();
85
+
86
+ useEffect(() => {
87
+ // Track a custom event
88
+ analytics?.track('custom_event', { key: 'value' });
89
+ }, [analytics]);
90
+
91
+ return <div>Welcome to the Home Page!</div>;
92
+ };
93
+
94
+ export default HomePage;
95
+ ```
96
+
97
+ **4. Folder Structure Example**
98
+
99
+ ```
100
+ /src
101
+ ├── /components
102
+ │ └── HomePage.tsx
103
+ ├── /App.tsx
104
+ └── /index.tsx (or index.js)
105
+ ```
106
+
107
+ ---
108
+
109
+ ### Next.js Application
110
+
111
+ **1. Install the npm package:**
112
+
113
+ Install `@formo/analytics` via yarn or npm:
114
+
115
+ ```jsx
116
+ yarn add @formo/analytics
117
+ ```
118
+
119
+ or
120
+
121
+ ```jsx
47
122
  npm install @formo/analytics --save
48
123
  ```
49
124
 
50
- ### 2. Set up the `FormoAnalyticsProvider` in your application:
125
+ **2. Set up the `FormoAnalyticsProvider` in your application:**
51
126
 
52
127
  ```jsx
53
128
  // AnalyticsProvider.tsx
@@ -69,32 +144,6 @@ export const AnalyticsProvider: FC<FormoAnalyticsProviderProps> = ({
69
144
  projectId,
70
145
  children,
71
146
  }) => {
72
- // Initialize the FormoAnalytics SDK inside useEffect
73
- const [isInitialized, setIsInitialized] = useState(false);
74
-
75
- useEffect(() => {
76
- const initialize = async () => {
77
- try {
78
- await FormoAnalytics.init(apiKey, projectId);
79
- console.log('FormoAnalytics SDK initialized');
80
- setIsInitialized(true);
81
- } catch (error) {
82
- console.error('Failed to initialize FormoAnalytics SDK', error);
83
- }
84
- };
85
-
86
- initialize();
87
- }, [apiKey, projectId]);
88
-
89
- // To prevent app crashes, render a loading state during initialization
90
- if (!isInitialized) {
91
- return (
92
- <FormoAnalyticsProvider apiKey={apiKey} projectId={projectId}>
93
- Loading Content
94
- </FormoAnalyticsProvider>
95
- );
96
- }
97
-
98
147
  return (
99
148
  <FormoAnalyticsProvider apiKey={apiKey} projectId={projectId}>
100
149
  {children}
@@ -105,7 +154,7 @@ export const AnalyticsProvider: FC<FormoAnalyticsProviderProps> = ({
105
154
  export default AnalyticsProvider;
106
155
  ```
107
156
 
108
- ### 3. Integrating the Provider in Your Root Layout
157
+ **3. Integrating the Provider in Your Root Layout**
109
158
 
110
159
  Wrap your application with the newly created `AnalyticsProvider` in your main layout file:
111
160
 
@@ -129,7 +178,7 @@ export default function RootLayout({
129
178
  }
130
179
  ```
131
180
 
132
- ### 4. Using the SDK
181
+ **4. Using the SDK**
133
182
 
134
183
  Once the SDK is initialized, you can use its methods to track events and user interactions. Here’s how to do that:
135
184
 
@@ -144,7 +193,6 @@ const YourComponent = () => {
144
193
  const track = async () => {
145
194
  try {
146
195
  console.log('Tracking page hit...');
147
- analytics.page(); // Track the page view
148
196
  analytics.track('custom_event', { key: 'value' }); // Track a custom event
149
197
  } catch (error) {
150
198
  console.error('Failed to track page hit', error);
@@ -158,10 +206,54 @@ const YourComponent = () => {
158
206
  };
159
207
  ```
160
208
 
161
- # Development notes
209
+ # Development Notes
210
+
211
+ If you want to contribute or run a local version of the Formo Analytics SDK, follow these steps:
212
+
213
+ 1. Build the SDK Locally
214
+
215
+ Run the following command to build both CommonJS and ESM versions of the SDK:
216
+
217
+ ```jsx
218
+ yarn build-cjs && yarn build-esm && yarn webpack --mode=production
219
+ ```
220
+
221
+ or if you're using NPM:
222
+
223
+ ```jsx
224
+ npm run build
225
+ ```
226
+
227
+ 2. Authenticate with NPM
228
+
229
+ To publish a new version of the package, log in to your NPM account:
230
+
231
+ ```jsx
232
+ npm login
233
+ ```
234
+
235
+ or:
236
+
237
+ ```jsx
238
+ npm adduser
239
+ ```
240
+
241
+ 3. Publish the Package
242
+
243
+ Run the following command to publish the package to NPM:
244
+
245
+ ```jsx
246
+ yarn publish
247
+ ```
248
+
249
+ or:
250
+
251
+ ```jsx
252
+ npm run publish
253
+ ```
162
254
 
163
- To run a local version of the script:
255
+ # Troubleshooting
164
256
 
165
- 1. Run `yarn build-cjs && yarn build-esm && yarn webpack --mode=production` or `npm run build` at the root level to build the script.
166
- 2. To authorize device, login into npmjs using `npm login` or `npm adduser`
167
- 3. Run `yarn publish` or `npm run publish` to publish new versions of the package.
257
+ **API Key Not Provided:** Ensure you pass a valid apiKey when initializing the SDK.
258
+ **SDK Not Initialized:** If you encounter issues with initialization, check the console logs for errors and ensure the project ID and API key are correct.
259
+ **Network Errors:** Verify that the analytics service URL is accessible from your network.
@@ -1,17 +1,57 @@
1
+ import { ChainID, EIP1193Provider } from './types';
1
2
  interface IFormoAnalytics {
3
+ /**
4
+ * Initializes the FormoAnalytics instance with the provided API key and project ID.
5
+ */
2
6
  init(apiKey: string, projectId: string): Promise<FormoAnalytics>;
3
- identify(userData: any): void;
7
+ /**
8
+ * Identifies the user with the provided user data.
9
+ */
10
+ identify(userData: Record<string, any>): void;
11
+ /**
12
+ * Tracks page visit events.
13
+ */
4
14
  page(): void;
5
- track(eventName: string, eventData: any): void;
15
+ /**
16
+ * Connects to a wallet with the specified chain ID and address.
17
+ */
18
+ connect(params: {
19
+ account: string;
20
+ chainId: ChainID;
21
+ }): Promise<void>;
22
+ /**
23
+ * Disconnects the current wallet and clears the session information.
24
+ */
25
+ disconnect(attributes?: {
26
+ account?: string;
27
+ chainId?: ChainID;
28
+ }): void;
29
+ /**
30
+ * Tracks a specific event with a name and associated data.
31
+ */
32
+ track(eventName: string, eventData: Record<string, any>): void;
33
+ /**
34
+ * Switches the blockchain chain context and optionally logs additional attributes.
35
+ */
36
+ chain(attributes: {
37
+ chainId: ChainID;
38
+ account?: string;
39
+ }): void;
6
40
  }
7
41
  export declare class FormoAnalytics implements IFormoAnalytics {
8
42
  readonly apiKey: string;
9
43
  projectId: string;
44
+ private _provider?;
45
+ private _registeredProviderListeners;
46
+ private sessionKey;
10
47
  private config;
11
48
  private sessionIdKey;
12
49
  private timezoneToCountry;
50
+ currentChainId?: string | null;
51
+ currentConnectedAccount?: string;
13
52
  private constructor();
14
53
  static init(apiKey: string, projectId: string): Promise<FormoAnalytics>;
54
+ get provider(): EIP1193Provider | undefined;
15
55
  private identifyUser;
16
56
  private getSessionId;
17
57
  private setSessionCookie;
@@ -20,7 +60,37 @@ export declare class FormoAnalytics implements IFormoAnalytics {
20
60
  private trackEvent;
21
61
  private maskSensitiveData;
22
62
  private trackPageHit;
63
+ private trackProvider;
64
+ private registerChainChangedListener;
65
+ private handleAccountDisconnected;
66
+ private onChainChanged;
67
+ private onAccountsChanged;
68
+ private registerAccountsChangedListener;
69
+ private getCurrentChainId;
70
+ private handleAccountConnected;
71
+ private getCurrentWallet;
72
+ /**
73
+ * Stores the wallet address in session storage when connected.
74
+ * @param address - The wallet address to store.
75
+ */
76
+ private storeWalletAddress;
77
+ /**
78
+ * Clears the wallet address from session storage when disconnected.
79
+ */
80
+ private clearWalletAddress;
23
81
  private buildApiUrl;
82
+ connect({ account, chainId }: {
83
+ account: string;
84
+ chainId: ChainID;
85
+ }): Promise<void>;
86
+ disconnect(attributes?: {
87
+ account?: string;
88
+ chainId?: ChainID;
89
+ }): Promise<void> | undefined;
90
+ chain({ chainId, account }: {
91
+ chainId: ChainID;
92
+ account?: string;
93
+ }): Promise<void>;
24
94
  init(apiKey: string, projectId: string): Promise<FormoAnalytics>;
25
95
  identify(userData: any): void;
26
96
  page(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"FormoAnalytics.d.ts","sourceRoot":"","sources":["../../../src/FormoAnalytics.ts"],"names":[],"mappings":"AAKA,UAAU,eAAe;IACvB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACjE,QAAQ,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI,CAAC;IAC9B,IAAI,IAAI,IAAI,CAAC;IACb,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC;CAChD;AACD,qBAAa,cAAe,YAAW,eAAe;aAMlC,MAAM,EAAE,MAAM;IACvB,SAAS,EAAE,MAAM;IAN1B,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,iBAAiB,CAAwC;IAEjE,OAAO;WASM,IAAI,CACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC;IAU1B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,cAAc;YAUR,UAAU;IAyDxB,OAAO,CAAC,iBAAiB;IAkEzB,OAAO,CAAC,YAAY;IAoCpB,OAAO,CAAC,WAAW;IAiBnB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAMhE,QAAQ,CAAC,QAAQ,EAAE,GAAG;IAItB,IAAI;IAIJ,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG;CAGxC"}
1
+ {"version":3,"file":"FormoAnalytics.d.ts","sourceRoot":"","sources":["../../../src/FormoAnalytics.ts"],"names":[],"mappings":"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"}
@@ -57,13 +57,20 @@ var utils_1 = require("./utils");
57
57
  var highlight_run_1 = require("highlight.run");
58
58
  var FormoAnalytics = /** @class */ (function () {
59
59
  function FormoAnalytics(apiKey, projectId) {
60
+ var _a;
60
61
  this.apiKey = apiKey;
61
62
  this.projectId = projectId;
63
+ this._registeredProviderListeners = {};
64
+ this.sessionKey = 'walletAddress';
62
65
  this.sessionIdKey = constants_1.SESSION_STORAGE_ID_KEY;
63
66
  this.timezoneToCountry = constants_1.COUNTRY_LIST;
64
67
  this.config = {
65
68
  token: this.apiKey,
66
69
  };
70
+ var provider = (window === null || window === void 0 ? void 0 : window.ethereum) || ((_a = window.web3) === null || _a === void 0 ? void 0 : _a.currentProvider);
71
+ if (provider) {
72
+ this.trackProvider(provider);
73
+ }
67
74
  }
68
75
  FormoAnalytics.init = function (apiKey, projectId) {
69
76
  return __awaiter(this, void 0, void 0, function () {
@@ -78,8 +85,15 @@ var FormoAnalytics = /** @class */ (function () {
78
85
  });
79
86
  });
80
87
  };
88
+ Object.defineProperty(FormoAnalytics.prototype, "provider", {
89
+ get: function () {
90
+ return this._provider;
91
+ },
92
+ enumerable: false,
93
+ configurable: true
94
+ });
81
95
  FormoAnalytics.prototype.identifyUser = function (userData) {
82
- this.trackEvent('identify', userData);
96
+ this.trackEvent(constants_1.Event.IDENTIFY, userData);
83
97
  };
84
98
  FormoAnalytics.prototype.getSessionId = function () {
85
99
  var existingSessionId = this.getCookieValue(this.sessionIdKey);
@@ -114,7 +128,7 @@ var FormoAnalytics = /** @class */ (function () {
114
128
  // Function to send tracking data
115
129
  FormoAnalytics.prototype.trackEvent = function (action, payload) {
116
130
  return __awaiter(this, void 0, void 0, function () {
117
- var maxRetries, attempt, apiUrl, requestData, sendRequest;
131
+ var maxRetries, attempt, apiUrl, address, requestData, sendRequest;
118
132
  var _this = this;
119
133
  return __generator(this, function (_a) {
120
134
  switch (_a.label) {
@@ -123,9 +137,12 @@ var FormoAnalytics = /** @class */ (function () {
123
137
  attempt = 0;
124
138
  this.setSessionCookie(this.config.domain);
125
139
  apiUrl = this.buildApiUrl();
140
+ return [4 /*yield*/, this.getCurrentWallet()];
141
+ case 1:
142
+ address = _a.sent();
126
143
  requestData = {
127
144
  project_id: this.projectId,
128
- address: '', // TODO: get cached / session wallet address
145
+ address: address,
129
146
  session_id: this.getSessionId(),
130
147
  timestamp: new Date().toISOString(),
131
148
  action: action,
@@ -170,7 +187,7 @@ var FormoAnalytics = /** @class */ (function () {
170
187
  });
171
188
  }); };
172
189
  return [4 /*yield*/, sendRequest()];
173
- case 1:
190
+ case 2:
174
191
  _a.sent();
175
192
  return [2 /*return*/];
176
193
  }
@@ -254,7 +271,7 @@ var FormoAnalytics = /** @class */ (function () {
254
271
  setTimeout(function () {
255
272
  var url = new URL(window.location.href);
256
273
  var params = new URLSearchParams(url.search);
257
- _this.trackEvent('page_hit', {
274
+ _this.trackEvent(constants_1.Event.PAGE, {
258
275
  'user-agent': window.navigator.userAgent,
259
276
  locale: language,
260
277
  location: location,
@@ -268,6 +285,221 @@ var FormoAnalytics = /** @class */ (function () {
268
285
  });
269
286
  }, 300);
270
287
  };
288
+ FormoAnalytics.prototype.trackProvider = function (provider) {
289
+ if (provider === this._provider) {
290
+ return;
291
+ }
292
+ this.currentChainId = undefined;
293
+ this.currentConnectedAccount = undefined;
294
+ if (this._provider) {
295
+ var eventNames = Object.keys(this._registeredProviderListeners);
296
+ for (var _i = 0, eventNames_1 = eventNames; _i < eventNames_1.length; _i++) {
297
+ var eventName = eventNames_1[_i];
298
+ this._provider.removeListener(eventName, this._registeredProviderListeners[eventName]);
299
+ delete this._registeredProviderListeners[eventName];
300
+ }
301
+ }
302
+ this._provider = provider;
303
+ this.getCurrentWallet();
304
+ this.registerAccountsChangedListener();
305
+ this.registerChainChangedListener();
306
+ };
307
+ FormoAnalytics.prototype.registerChainChangedListener = function () {
308
+ var _this = this;
309
+ var _a;
310
+ var listener = function () {
311
+ var args = [];
312
+ for (var _i = 0; _i < arguments.length; _i++) {
313
+ args[_i] = arguments[_i];
314
+ }
315
+ return _this.onChainChanged(args[0]);
316
+ };
317
+ (_a = this.provider) === null || _a === void 0 ? void 0 : _a.on('chainChanged', listener);
318
+ this._registeredProviderListeners['chainChanged'] = listener;
319
+ };
320
+ FormoAnalytics.prototype.handleAccountDisconnected = function () {
321
+ if (!this.currentConnectedAccount) {
322
+ return;
323
+ }
324
+ var disconnectAttributes = {
325
+ address: this.currentConnectedAccount,
326
+ chainId: this.currentChainId,
327
+ };
328
+ this.currentChainId = undefined;
329
+ this.currentConnectedAccount = undefined;
330
+ this.clearWalletAddress();
331
+ return this.trackEvent(constants_1.Event.DISCONNECT, disconnectAttributes);
332
+ };
333
+ FormoAnalytics.prototype.onChainChanged = function (chainIdHex) {
334
+ return __awaiter(this, void 0, void 0, function () {
335
+ var res, err_1;
336
+ return __generator(this, function (_a) {
337
+ switch (_a.label) {
338
+ case 0:
339
+ this.currentChainId = parseInt(chainIdHex).toString();
340
+ if (!!this.currentConnectedAccount) return [3 /*break*/, 4];
341
+ if (!this.provider) {
342
+ console.error('error', 'FormoAnalytics::onChainChanged: provider not found. CHAIN_CHANGED not reported');
343
+ return [2 /*return*/];
344
+ }
345
+ _a.label = 1;
346
+ case 1:
347
+ _a.trys.push([1, 3, , 4]);
348
+ return [4 /*yield*/, this.provider.request({
349
+ method: 'eth_accounts',
350
+ })];
351
+ case 2:
352
+ res = _a.sent();
353
+ if (!res || res.length === 0) {
354
+ console.error('error', 'FormoAnalytics::onChainChanged: unable to get account. eth_accounts returned empty');
355
+ return [2 /*return*/];
356
+ }
357
+ this.currentConnectedAccount = res[0];
358
+ return [3 /*break*/, 4];
359
+ case 3:
360
+ err_1 = _a.sent();
361
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
362
+ if (err_1.code !== 4001) {
363
+ // 4001: The request is rejected by the user , see https://docs.metamask.io/wallet/reference/provider-api/#errors
364
+ console.error('error', "FormoAnalytics::onChainChanged: unable to get account. eth_accounts threw an error", err_1);
365
+ return [2 /*return*/];
366
+ }
367
+ return [3 /*break*/, 4];
368
+ case 4: return [2 /*return*/, this.chain({
369
+ chainId: this.currentChainId,
370
+ account: this.currentConnectedAccount,
371
+ })];
372
+ }
373
+ });
374
+ });
375
+ };
376
+ FormoAnalytics.prototype.onAccountsChanged = function (accounts) {
377
+ return __awaiter(this, void 0, void 0, function () {
378
+ var newAccount;
379
+ return __generator(this, function (_a) {
380
+ if (accounts.length > 0) {
381
+ newAccount = accounts[0];
382
+ if (newAccount !== this.currentConnectedAccount) {
383
+ this.handleAccountConnected(newAccount);
384
+ }
385
+ }
386
+ else {
387
+ this.handleAccountDisconnected();
388
+ }
389
+ return [2 /*return*/];
390
+ });
391
+ });
392
+ };
393
+ FormoAnalytics.prototype.registerAccountsChangedListener = function () {
394
+ var _this = this;
395
+ var _a, _b;
396
+ var listener = function () {
397
+ var args = [];
398
+ for (var _i = 0; _i < arguments.length; _i++) {
399
+ args[_i] = arguments[_i];
400
+ }
401
+ return _this.onAccountsChanged(args[0]);
402
+ };
403
+ (_a = this._provider) === null || _a === void 0 ? void 0 : _a.on('accountsChanged', listener);
404
+ this._registeredProviderListeners['accountsChanged'] = listener;
405
+ var handleAccountDisconnected = this.handleAccountDisconnected.bind(this);
406
+ (_b = this._provider) === null || _b === void 0 ? void 0 : _b.on('disconnect', handleAccountDisconnected);
407
+ this._registeredProviderListeners['disconnect'] = handleAccountDisconnected;
408
+ };
409
+ FormoAnalytics.prototype.getCurrentChainId = function () {
410
+ return __awaiter(this, void 0, void 0, function () {
411
+ var chainIdHex;
412
+ var _a;
413
+ return __generator(this, function (_b) {
414
+ switch (_b.label) {
415
+ case 0:
416
+ if (!this.provider) {
417
+ console.error('FormoAnalytics::getCurrentChainId: provider not set');
418
+ }
419
+ return [4 /*yield*/, ((_a = this.provider) === null || _a === void 0 ? void 0 : _a.request({
420
+ method: 'eth_chainId',
421
+ }))];
422
+ case 1:
423
+ chainIdHex = _b.sent();
424
+ // Because we're connected, the chainId cannot be null
425
+ if (!chainIdHex) {
426
+ console.error("FormoAnalytics::getCurrentChainId: chainIdHex is: ".concat(chainIdHex));
427
+ }
428
+ return [2 /*return*/, parseInt(chainIdHex, 16).toString()];
429
+ }
430
+ });
431
+ });
432
+ };
433
+ FormoAnalytics.prototype.handleAccountConnected = function (account) {
434
+ return __awaiter(this, void 0, void 0, function () {
435
+ var _a;
436
+ return __generator(this, function (_b) {
437
+ switch (_b.label) {
438
+ case 0:
439
+ if (account === this.currentConnectedAccount) {
440
+ // We have already reported this account
441
+ return [2 /*return*/];
442
+ }
443
+ else {
444
+ this.currentConnectedAccount = account;
445
+ }
446
+ _a = this;
447
+ return [4 /*yield*/, this.getCurrentChainId()];
448
+ case 1:
449
+ _a.currentChainId = _b.sent();
450
+ this.connect({ account: account, chainId: this.currentChainId });
451
+ this.storeWalletAddress(account);
452
+ return [2 /*return*/];
453
+ }
454
+ });
455
+ });
456
+ };
457
+ FormoAnalytics.prototype.getCurrentWallet = function () {
458
+ return __awaiter(this, void 0, void 0, function () {
459
+ var sessionData, parsedData, sessionExpiry, currentTime;
460
+ return __generator(this, function (_a) {
461
+ if (!this.provider) {
462
+ console.warn('FormoAnalytics::getCurrentWallet: the provider is not set');
463
+ return [2 /*return*/];
464
+ }
465
+ sessionData = sessionStorage.getItem(this.sessionKey);
466
+ if (!sessionData) {
467
+ return [2 /*return*/, null];
468
+ }
469
+ parsedData = JSON.parse(sessionData);
470
+ sessionExpiry = 30 * 60 * 1000;
471
+ currentTime = Date.now();
472
+ if (currentTime - parsedData.timestamp > sessionExpiry) {
473
+ console.warn('Session expired. Ignoring wallet address.');
474
+ sessionStorage.removeItem(this.sessionKey); // Clear expired session data
475
+ return [2 /*return*/, ''];
476
+ }
477
+ this.handleAccountConnected(parsedData.address);
478
+ return [2 /*return*/, parsedData.address || ''];
479
+ });
480
+ });
481
+ };
482
+ /**
483
+ * Stores the wallet address in session storage when connected.
484
+ * @param address - The wallet address to store.
485
+ */
486
+ FormoAnalytics.prototype.storeWalletAddress = function (address) {
487
+ if (!address) {
488
+ console.error('No wallet address provided to store.');
489
+ return;
490
+ }
491
+ var sessionData = {
492
+ address: address,
493
+ timestamp: Date.now(),
494
+ };
495
+ sessionStorage.setItem(this.sessionKey, JSON.stringify(sessionData));
496
+ };
497
+ /**
498
+ * Clears the wallet address from session storage when disconnected.
499
+ */
500
+ FormoAnalytics.prototype.clearWalletAddress = function () {
501
+ sessionStorage.removeItem(this.sessionKey);
502
+ };
271
503
  // Function to build the API URL
272
504
  FormoAnalytics.prototype.buildApiUrl = function () {
273
505
  var _a = this.config, host = _a.host, proxy = _a.proxy, token = _a.token, _b = _a.dataSource, dataSource = _b === void 0 ? 'analytics_events' : _b;
@@ -282,6 +514,51 @@ var FormoAnalytics = /** @class */ (function () {
282
514
  }
283
515
  return 'Error: No token provided';
284
516
  };
517
+ FormoAnalytics.prototype.connect = function (_a) {
518
+ var account = _a.account, chainId = _a.chainId;
519
+ if (!chainId) {
520
+ throw new Error('FormoAnalytics::connect: chainId cannot be empty');
521
+ }
522
+ if (!account) {
523
+ throw new Error('FormoAnalytics::connect: account cannot be empty');
524
+ }
525
+ this.currentChainId = chainId.toString();
526
+ this.currentConnectedAccount = account;
527
+ return this.trackEvent(constants_1.Event.CONNECT, {
528
+ chainId: chainId,
529
+ address: account,
530
+ });
531
+ };
532
+ FormoAnalytics.prototype.disconnect = function (attributes) {
533
+ var account = (attributes === null || attributes === void 0 ? void 0 : attributes.account) || this.currentConnectedAccount;
534
+ if (!account) {
535
+ // We have most likely already reported this disconnection with the automatic
536
+ // `disconnect` detection
537
+ return;
538
+ }
539
+ var chainId = (attributes === null || attributes === void 0 ? void 0 : attributes.chainId) || this.currentChainId;
540
+ var eventAttributes = __assign({ account: account }, (chainId && { chainId: chainId }));
541
+ this.currentChainId = undefined;
542
+ this.currentConnectedAccount = undefined;
543
+ return this.trackEvent(constants_1.Event.DISCONNECT, eventAttributes);
544
+ };
545
+ FormoAnalytics.prototype.chain = function (_a) {
546
+ var chainId = _a.chainId, account = _a.account;
547
+ if (!chainId || Number(chainId) === 0) {
548
+ throw new Error('FormoAnalytics::chain: chainId cannot be empty or 0');
549
+ }
550
+ if (!account && !this.currentConnectedAccount) {
551
+ throw new Error('FormoAnalytics::chain: account was empty and no previous account has been recorded. You can either pass an account or call connect() first');
552
+ }
553
+ if (isNaN(Number(chainId))) {
554
+ throw new Error('FormoAnalytics::chain: chainId must be a valid hex or decimal number');
555
+ }
556
+ this.currentChainId = chainId.toString();
557
+ return this.trackEvent(constants_1.Event.CHAIN_CHANGED, {
558
+ chainId: chainId,
559
+ account: account || this.currentConnectedAccount,
560
+ });
561
+ };
285
562
  FormoAnalytics.prototype.init = function (apiKey, projectId) {
286
563
  var instance = new FormoAnalytics(apiKey, projectId);
287
564
  return Promise.resolve(instance);