@formo/analytics 1.11.14-alpha.1 → 1.11.14-alpha.2
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/CONTRIBUTING.md +43 -0
- package/README.md +4 -251
- package/dist/cjs/src/FormoAnalytics.d.ts +1 -6
- package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
- package/dist/cjs/src/FormoAnalytics.js +24 -56
- package/dist/cjs/src/FormoAnalytics.js.map +1 -1
- package/dist/cjs/src/FormoAnalyticsProvider.d.ts.map +1 -1
- package/dist/cjs/src/FormoAnalyticsProvider.js +53 -37
- package/dist/cjs/src/FormoAnalyticsProvider.js.map +1 -1
- package/dist/cjs/src/constants/config.d.ts +0 -1
- package/dist/cjs/src/constants/config.d.ts.map +1 -1
- package/dist/cjs/src/constants/config.js +1 -2
- package/dist/cjs/src/constants/config.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/src/FormoAnalytics.d.ts +1 -6
- package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
- package/dist/esm/src/FormoAnalytics.js +25 -57
- package/dist/esm/src/FormoAnalytics.js.map +1 -1
- package/dist/esm/src/FormoAnalyticsProvider.d.ts.map +1 -1
- package/dist/esm/src/FormoAnalyticsProvider.js +53 -37
- package/dist/esm/src/FormoAnalyticsProvider.js.map +1 -1
- package/dist/esm/src/constants/config.d.ts +0 -1
- package/dist/esm/src/constants/config.d.ts.map +1 -1
- package/dist/esm/src/constants/config.js +0 -1
- package/dist/esm/src/constants/config.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/FormoAnalytics.ts +24 -75
- package/src/FormoAnalyticsProvider.tsx +36 -30
- package/src/constants/config.ts +0 -1
package/package.json
CHANGED
package/src/FormoAnalytics.ts
CHANGED
|
@@ -2,7 +2,6 @@ import axios from "axios";
|
|
|
2
2
|
import {
|
|
3
3
|
COUNTRY_LIST,
|
|
4
4
|
EVENTS_API_URL,
|
|
5
|
-
SESSION_STORAGE_ID_KEY,
|
|
6
5
|
Event,
|
|
7
6
|
} from "./constants";
|
|
8
7
|
import { H } from "highlight.run";
|
|
@@ -51,7 +50,6 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
51
50
|
|
|
52
51
|
private walletAddressSessionKey = "walletAddress";
|
|
53
52
|
private config: Config;
|
|
54
|
-
private sessionIdKey: string = SESSION_STORAGE_ID_KEY;
|
|
55
53
|
private timezoneToCountry: Record<string, string> = COUNTRY_LIST;
|
|
56
54
|
|
|
57
55
|
currentChainId?: string | null;
|
|
@@ -89,56 +87,16 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
89
87
|
return this._provider;
|
|
90
88
|
}
|
|
91
89
|
|
|
92
|
-
private getSessionId() {
|
|
93
|
-
const existingSessionId = this.getCookieValue(this.sessionIdKey);
|
|
94
|
-
|
|
95
|
-
if (existingSessionId) {
|
|
96
|
-
return existingSessionId;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const newSessionId = this.generateSessionId();
|
|
100
|
-
return newSessionId;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private getOrigin(): string {
|
|
104
|
-
return window.location.origin || "ORIGIN_NOT_FOUND";
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Function to set the session cookie
|
|
108
|
-
private setSessionCookie(): void {
|
|
109
|
-
const sessionId = this.getSessionId();
|
|
110
|
-
let cookieValue = `${
|
|
111
|
-
this.sessionIdKey
|
|
112
|
-
}=${sessionId}; Max-Age=1800; path=/; secure; domain=${this.getOrigin()}`;
|
|
113
|
-
document.cookie = cookieValue;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Function to generate a new session ID
|
|
117
|
-
private generateSessionId(): string {
|
|
118
|
-
return crypto.randomUUID();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Function to get a cookie value by name
|
|
122
|
-
private getCookieValue(name: string): string | undefined {
|
|
123
|
-
const cookies = document.cookie.split(";").reduce((acc, cookie) => {
|
|
124
|
-
const [key, value] = cookie.split("=");
|
|
125
|
-
acc[key.trim()] = value;
|
|
126
|
-
return acc;
|
|
127
|
-
}, {} as Record<string, string>);
|
|
128
|
-
return cookies[name];
|
|
129
|
-
}
|
|
130
90
|
|
|
131
91
|
// Function to send tracking data
|
|
132
92
|
private async trackEvent(action: string, payload: any) {
|
|
133
93
|
const maxRetries = 3;
|
|
134
94
|
let attempt = 0;
|
|
135
95
|
|
|
136
|
-
this.setSessionCookie();
|
|
137
96
|
const address = await this.getCurrentWallet();
|
|
138
97
|
|
|
139
98
|
const requestData = {
|
|
140
99
|
address: address,
|
|
141
|
-
session_id: this.getSessionId(),
|
|
142
100
|
timestamp: new Date().toISOString(),
|
|
143
101
|
action,
|
|
144
102
|
version: "1",
|
|
@@ -305,7 +263,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
305
263
|
return address;
|
|
306
264
|
}
|
|
307
265
|
} catch (err) {
|
|
308
|
-
console.
|
|
266
|
+
console.log("Failed to fetch accounts from provider:", err);
|
|
309
267
|
}
|
|
310
268
|
return null;
|
|
311
269
|
}
|
|
@@ -327,7 +285,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
327
285
|
const currentTime = Date.now();
|
|
328
286
|
|
|
329
287
|
if (currentTime - parsedData.timestamp > sessionExpiry) {
|
|
330
|
-
console.
|
|
288
|
+
console.log("Session expired. Ignoring wallet address.");
|
|
331
289
|
sessionStorage.removeItem(this.walletAddressSessionKey); // Clear expired session data
|
|
332
290
|
return "";
|
|
333
291
|
}
|
|
@@ -343,8 +301,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
343
301
|
method: "eth_accounts",
|
|
344
302
|
});
|
|
345
303
|
if (!res || res.length === 0) {
|
|
346
|
-
console.
|
|
347
|
-
"error",
|
|
304
|
+
console.log(
|
|
348
305
|
"FormoAnalytics::fetchAccounts: unable to get account. eth_accounts returned empty"
|
|
349
306
|
);
|
|
350
307
|
return null;
|
|
@@ -352,8 +309,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
352
309
|
return res;
|
|
353
310
|
} catch (err) {
|
|
354
311
|
if ((err as any).code !== 4001) {
|
|
355
|
-
console.
|
|
356
|
-
"error",
|
|
312
|
+
console.log(
|
|
357
313
|
"FormoAnalytics::fetchAccounts: eth_accounts threw an error",
|
|
358
314
|
err
|
|
359
315
|
);
|
|
@@ -369,15 +325,14 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
369
325
|
method: "eth_chainId",
|
|
370
326
|
});
|
|
371
327
|
if (!chainIdHex) {
|
|
372
|
-
console.
|
|
328
|
+
console.log(
|
|
373
329
|
"FormoAnalytics::fetchChainId: chainIdHex is null or undefined"
|
|
374
330
|
);
|
|
375
331
|
return null;
|
|
376
332
|
}
|
|
377
333
|
return chainIdHex;
|
|
378
334
|
} catch (err) {
|
|
379
|
-
console.
|
|
380
|
-
"error",
|
|
335
|
+
console.log(
|
|
381
336
|
"FormoAnalytics::fetchChainId: eth_chainId threw an error",
|
|
382
337
|
err
|
|
383
338
|
);
|
|
@@ -387,13 +342,13 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
387
342
|
|
|
388
343
|
private async getCurrentChainId(): Promise<string> {
|
|
389
344
|
if (!this.provider) {
|
|
390
|
-
console.
|
|
345
|
+
console.log("FormoAnalytics::getCurrentChainId: provider not set");
|
|
391
346
|
}
|
|
392
347
|
|
|
393
348
|
const chainIdHex = await this.fetchChainId();
|
|
394
349
|
// Because we're connected, the chainId cannot be null
|
|
395
350
|
if (!chainIdHex) {
|
|
396
|
-
console.
|
|
351
|
+
console.log(
|
|
397
352
|
`FormoAnalytics::getCurrentChainId: chainIdHex is: ${chainIdHex}`
|
|
398
353
|
);
|
|
399
354
|
}
|
|
@@ -445,28 +400,32 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
445
400
|
this.storeWalletAddress(address);
|
|
446
401
|
}
|
|
447
402
|
|
|
448
|
-
private
|
|
449
|
-
if (!
|
|
403
|
+
private handleDisconnection(chainId?: string, address?: string) {
|
|
404
|
+
if (!address) {
|
|
450
405
|
return;
|
|
451
406
|
}
|
|
452
|
-
|
|
453
407
|
const payload = {
|
|
454
|
-
chain_id: this.currentChainId,
|
|
455
|
-
address
|
|
408
|
+
chain_id: chainId || this.currentChainId,
|
|
409
|
+
address,
|
|
456
410
|
};
|
|
457
411
|
this.currentChainId = undefined;
|
|
458
412
|
this.currentConnectedAddress = undefined;
|
|
459
413
|
this.clearWalletAddress();
|
|
460
|
-
|
|
461
414
|
return this.trackEvent(Event.DISCONNECT, payload);
|
|
462
415
|
}
|
|
463
416
|
|
|
417
|
+
private onAddressDisconnected() {
|
|
418
|
+
if (!this.currentConnectedAddress) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
this.handleDisconnection(this.currentChainId || undefined, this.currentConnectedAddress);
|
|
422
|
+
}
|
|
423
|
+
|
|
464
424
|
private async onChainChanged(chainIdHex: string) {
|
|
465
425
|
this.currentChainId = parseInt(chainIdHex).toString();
|
|
466
426
|
if (!this.currentConnectedAddress) {
|
|
467
427
|
if (!this.provider) {
|
|
468
|
-
console.
|
|
469
|
-
"error",
|
|
428
|
+
console.log(
|
|
470
429
|
"FormoAnalytics::onChainChanged: provider not found. CHAIN_CHANGED not reported"
|
|
471
430
|
);
|
|
472
431
|
return;
|
|
@@ -475,8 +434,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
475
434
|
// Attempt to fetch and store the connected address
|
|
476
435
|
const address = await this.getAndStoreConnectedAddress();
|
|
477
436
|
if (!address) {
|
|
478
|
-
console.
|
|
479
|
-
"error",
|
|
437
|
+
console.log(
|
|
480
438
|
"FormoAnalytics::onChainChanged: Unable to fetch or store connected address"
|
|
481
439
|
);
|
|
482
440
|
return;
|
|
@@ -492,8 +450,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
492
450
|
address: this.currentConnectedAddress,
|
|
493
451
|
});
|
|
494
452
|
} else {
|
|
495
|
-
console.
|
|
496
|
-
"error",
|
|
453
|
+
console.log(
|
|
497
454
|
"FormoAnalytics::onChainChanged: currentConnectedAddress is null despite fetch attempt"
|
|
498
455
|
);
|
|
499
456
|
}
|
|
@@ -505,7 +462,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
505
462
|
*/
|
|
506
463
|
private storeWalletAddress(address: string): void {
|
|
507
464
|
if (!address) {
|
|
508
|
-
console.
|
|
465
|
+
console.log("No wallet address provided to store.");
|
|
509
466
|
return;
|
|
510
467
|
}
|
|
511
468
|
|
|
@@ -556,15 +513,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
556
513
|
// `disconnect` detection
|
|
557
514
|
return;
|
|
558
515
|
}
|
|
559
|
-
|
|
560
|
-
const payload = {
|
|
561
|
-
chain_id: params?.chainId || this.currentChainId,
|
|
562
|
-
address,
|
|
563
|
-
};
|
|
564
|
-
this.currentChainId = undefined;
|
|
565
|
-
this.currentConnectedAddress = undefined;
|
|
566
|
-
|
|
567
|
-
return this.trackEvent(Event.DISCONNECT, payload);
|
|
516
|
+
return this.handleDisconnection((params?.chainId?.toString() || this.currentChainId) as string, address);
|
|
568
517
|
}
|
|
569
518
|
|
|
570
519
|
chain({ chainId, address }: { chainId: ChainID; address?: string }) {
|
|
@@ -26,6 +26,40 @@ export const FormoAnalyticsProvider = ({
|
|
|
26
26
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
27
27
|
const initializedStartedRef = useRef(false);
|
|
28
28
|
|
|
29
|
+
const initializeHighlight = async () => {
|
|
30
|
+
if (HIGHLIGHT_PROJECT_ID) {
|
|
31
|
+
try {
|
|
32
|
+
H.init(HIGHLIGHT_PROJECT_ID, {
|
|
33
|
+
serviceName: 'formo-analytics-sdk',
|
|
34
|
+
tracingOrigins: true,
|
|
35
|
+
networkRecording: {
|
|
36
|
+
enabled: true,
|
|
37
|
+
recordHeadersAndBody: true,
|
|
38
|
+
urlBlocklist: [
|
|
39
|
+
'https://www.googleapis.com/identitytoolkit',
|
|
40
|
+
'https://securetoken.googleapis.com',
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
console.log('Highlight.run initialized successfully');
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error('Failed to initialize Highlight.run', error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const initializeFormoAnalytics = async (apiKey: string, options: any) => {
|
|
52
|
+
try {
|
|
53
|
+
const sdkInstance = await FormoAnalytics.init(apiKey, options);
|
|
54
|
+
setSdk(sdkInstance);
|
|
55
|
+
console.log('FormoAnalytics SDK initialized successfully');
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Failed to initialize FormoAnalytics SDK', error);
|
|
58
|
+
} finally {
|
|
59
|
+
setIsInitialized(true); // Ensure UI renders even after failure
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
29
63
|
useEffect(() => {
|
|
30
64
|
const initialize = async () => {
|
|
31
65
|
if (!apiKey) {
|
|
@@ -38,37 +72,9 @@ export const FormoAnalyticsProvider = ({
|
|
|
38
72
|
}
|
|
39
73
|
if (initializedStartedRef.current) return;
|
|
40
74
|
initializedStartedRef.current = true;
|
|
41
|
-
// Initialize Highlight.run if project ID is available
|
|
42
|
-
if (HIGHLIGHT_PROJECT_ID) {
|
|
43
|
-
try {
|
|
44
|
-
H.init(HIGHLIGHT_PROJECT_ID, {
|
|
45
|
-
serviceName: 'formo-analytics-sdk',
|
|
46
|
-
tracingOrigins: true,
|
|
47
|
-
networkRecording: {
|
|
48
|
-
enabled: true,
|
|
49
|
-
recordHeadersAndBody: true,
|
|
50
|
-
urlBlocklist: [
|
|
51
|
-
'https://www.googleapis.com/identitytoolkit',
|
|
52
|
-
'https://securetoken.googleapis.com',
|
|
53
|
-
],
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
console.log('Highlight.run initialized successfully');
|
|
57
|
-
} catch (error) {
|
|
58
|
-
console.error('Failed to initialize Highlight.run', error);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
75
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const sdkInstance = await FormoAnalytics.init(apiKey, options);
|
|
65
|
-
setSdk(sdkInstance);
|
|
66
|
-
console.log('FormoAnalytics SDK initialized successfully');
|
|
67
|
-
} catch (error) {
|
|
68
|
-
console.error('Failed to initialize FormoAnalytics SDK', error);
|
|
69
|
-
} finally {
|
|
70
|
-
setIsInitialized(true); // Ensure UI renders even after failure
|
|
71
|
-
}
|
|
76
|
+
await initializeHighlight();
|
|
77
|
+
await initializeFormoAnalytics(apiKey, options);
|
|
72
78
|
};
|
|
73
79
|
|
|
74
80
|
initialize();
|