@formo/analytics 1.12.0-alpha.2 → 2.0.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.
Files changed (46) hide show
  1. package/dist/cjs/src/FormoAnalytics.d.ts +7 -48
  2. package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
  3. package/dist/cjs/src/FormoAnalytics.js +86 -62
  4. package/dist/cjs/src/FormoAnalytics.js.map +1 -1
  5. package/dist/cjs/src/constants/events.d.ts +5 -3
  6. package/dist/cjs/src/constants/events.d.ts.map +1 -1
  7. package/dist/cjs/src/constants/events.js +4 -2
  8. package/dist/cjs/src/constants/events.js.map +1 -1
  9. package/dist/cjs/src/types/index.d.ts +1 -1
  10. package/dist/cjs/src/types/index.d.ts.map +1 -1
  11. package/dist/cjs/src/types/index.js +1 -1
  12. package/dist/cjs/src/types/index.js.map +1 -1
  13. package/dist/cjs/src/types/{wallet.d.ts → web3.d.ts} +1 -1
  14. package/dist/cjs/src/types/web3.d.ts.map +1 -0
  15. package/dist/cjs/src/types/{wallet.js → web3.js} +1 -1
  16. package/dist/cjs/src/types/web3.js.map +1 -0
  17. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  18. package/dist/esm/src/FormoAnalytics.d.ts +7 -48
  19. package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
  20. package/dist/esm/src/FormoAnalytics.js +86 -62
  21. package/dist/esm/src/FormoAnalytics.js.map +1 -1
  22. package/dist/esm/src/constants/events.d.ts +5 -3
  23. package/dist/esm/src/constants/events.d.ts.map +1 -1
  24. package/dist/esm/src/constants/events.js +4 -2
  25. package/dist/esm/src/constants/events.js.map +1 -1
  26. package/dist/esm/src/types/index.d.ts +1 -1
  27. package/dist/esm/src/types/index.d.ts.map +1 -1
  28. package/dist/esm/src/types/index.js +1 -1
  29. package/dist/esm/src/types/index.js.map +1 -1
  30. package/dist/esm/src/types/{wallet.d.ts → web3.d.ts} +1 -1
  31. package/dist/esm/src/types/web3.d.ts.map +1 -0
  32. package/dist/esm/src/types/web3.js +2 -0
  33. package/dist/esm/src/types/web3.js.map +1 -0
  34. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  35. package/dist/index.umd.min.js +1 -1
  36. package/dist/index.umd.min.js.map +1 -1
  37. package/package.json +1 -1
  38. package/src/FormoAnalytics.ts +83 -92
  39. package/src/constants/events.ts +5 -3
  40. package/src/types/index.ts +1 -1
  41. package/dist/cjs/src/types/wallet.d.ts.map +0 -1
  42. package/dist/cjs/src/types/wallet.js.map +0 -1
  43. package/dist/esm/src/types/wallet.d.ts.map +0 -1
  44. package/dist/esm/src/types/wallet.js +0 -2
  45. package/dist/esm/src/types/wallet.js.map +0 -1
  46. /package/src/types/{wallet.ts → web3.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formo/analytics",
3
- "version": "1.12.0-alpha.2",
3
+ "version": "2.0.0-alpha.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/getformo/sdk.git"
@@ -10,49 +10,19 @@ import { H } from 'highlight.run';
10
10
  import { ChainID, EIP1193Provider, RequestArguments } from './types';
11
11
 
12
12
  interface IFormoAnalytics {
13
- /**
14
- * Initializes the FormoAnalytics instance with the provided API key and project ID.
15
- */
16
13
  init(apiKey: string, projectId: string): Promise<FormoAnalytics>;
17
-
18
- /**
19
- * Identifies the user with the provided user data.
20
- */
21
- identify(userData: Record<string, any>): void;
22
-
23
- /**
24
- * Tracks page visit events.
25
- */
14
+ identify(userData: any): void;
26
15
  page(): void;
27
-
28
- /**
29
- * Connects to a wallet with the specified chain ID and address.
30
- */
31
- connect(params: { account: string; chainId: ChainID }): Promise<void>;
32
-
33
- /**
34
- * Disconnects the current wallet and clears the session information.
35
- */
36
- disconnect(attributes?: { account?: string; chainId?: ChainID }): void;
37
-
38
- /**
39
- * Tracks a specific event with a name and associated data.
40
- */
41
- track(eventName: string, eventData: Record<string, any>): void;
42
-
43
- /**
44
- * Switches the blockchain chain context and optionally logs additional attributes.
45
- */
46
- chain(attributes: { chainId: ChainID; account?: string }): void;
16
+ track(eventName: string, eventData: any): void;
47
17
  }
48
18
  export class FormoAnalytics implements IFormoAnalytics {
49
19
  private _provider?: EIP1193Provider;
20
+ private _originalRequest?: EIP1193Provider['request'];
50
21
  private _registeredProviderListeners: Record<
51
22
  string,
52
23
  (...args: unknown[]) => void
53
24
  > = {};
54
25
 
55
- private sessionKey = 'walletAddress';
56
26
  private config: any;
57
27
  private sessionIdKey: string = SESSION_STORAGE_ID_KEY;
58
28
  private timezoneToCountry: Record<string, string> = COUNTRY_LIST;
@@ -92,7 +62,7 @@ export class FormoAnalytics implements IFormoAnalytics {
92
62
  }
93
63
 
94
64
  private identifyUser(userData: any) {
95
- this.trackEvent(Event.IDENTIFY, userData);
65
+ this.trackEvent('identify', userData);
96
66
  }
97
67
 
98
68
  private getSessionId() {
@@ -276,7 +246,7 @@ export class FormoAnalytics implements IFormoAnalytics {
276
246
  setTimeout(() => {
277
247
  const url = new URL(window.location.href);
278
248
  const params = new URLSearchParams(url.search);
279
- this.trackEvent(Event.PAGE, {
249
+ this.trackEvent('page_hit', {
280
250
  'user-agent': window.navigator.userAgent,
281
251
  locale: language,
282
252
  location: location,
@@ -308,13 +278,24 @@ export class FormoAnalytics implements IFormoAnalytics {
308
278
  );
309
279
  delete this._registeredProviderListeners[eventName];
310
280
  }
281
+
282
+ // Restore original request
283
+ if (
284
+ this._originalRequest &&
285
+ Object.getOwnPropertyDescriptor(this._provider, 'request')?.writable !==
286
+ false
287
+ ) {
288
+ this._provider.request = this._originalRequest;
289
+ }
311
290
  }
312
291
 
313
292
  this._provider = provider;
293
+ this._originalRequest = provider?.request;
314
294
 
315
295
  this.getCurrentWallet();
316
296
  this.registerAccountsChangedListener();
317
297
  this.registerChainChangedListener();
298
+ this.trackSigning();
318
299
  }
319
300
 
320
301
  private registerChainChangedListener() {
@@ -335,7 +316,6 @@ export class FormoAnalytics implements IFormoAnalytics {
335
316
  };
336
317
  this.currentChainId = undefined;
337
318
  this.currentConnectedAccount = undefined;
338
- this.clearWalletAddress();
339
319
 
340
320
  return this.trackEvent(Event.DISCONNECT, disconnectAttributes);
341
321
  }
@@ -353,12 +333,12 @@ export class FormoAnalytics implements IFormoAnalytics {
353
333
 
354
334
  try {
355
335
  const res: string[] | null | undefined = await this.provider.request({
356
- method: 'eth_accounts',
336
+ method: 'eth_requestAccounts',
357
337
  });
358
338
  if (!res || res.length === 0) {
359
339
  console.error(
360
340
  'error',
361
- 'FormoAnalytics::onChainChanged: unable to get account. eth_accounts returned empty'
341
+ 'FormoAnalytics::onChainChanged: unable to get account. eth_requestAccounts returned empty'
362
342
  );
363
343
  return;
364
344
  }
@@ -370,7 +350,7 @@ export class FormoAnalytics implements IFormoAnalytics {
370
350
  // 4001: The request is rejected by the user , see https://docs.metamask.io/wallet/reference/provider-api/#errors
371
351
  console.error(
372
352
  'error',
373
- `FormoAnalytics::onChainChanged: unable to get account. eth_accounts threw an error`,
353
+ `FormoAnalytics::onChainChanged: unable to get account. eth_requestAccounts threw an error`,
374
354
  err
375
355
  );
376
356
  return;
@@ -386,10 +366,7 @@ export class FormoAnalytics implements IFormoAnalytics {
386
366
 
387
367
  private async onAccountsChanged(accounts: string[]) {
388
368
  if (accounts.length > 0) {
389
- const newAccount = accounts[0];
390
- if (newAccount !== this.currentConnectedAccount) {
391
- this.handleAccountConnected(newAccount);
392
- }
369
+ this.handleAccountConnected(accounts[0]);
393
370
  } else {
394
371
  this.handleAccountDisconnected();
395
372
  }
@@ -407,6 +384,49 @@ export class FormoAnalytics implements IFormoAnalytics {
407
384
  this._registeredProviderListeners['disconnect'] = handleAccountDisconnected;
408
385
  }
409
386
 
387
+ private trackSigning() {
388
+ if (!this.provider) {
389
+ console.error(
390
+ 'error',
391
+ 'FormoAnalytics::_trackSigning: provider not found'
392
+ );
393
+ return false;
394
+ }
395
+
396
+ if (
397
+ Object.getOwnPropertyDescriptor(this.provider, 'request')?.writable ===
398
+ false
399
+ ) {
400
+ console.error(
401
+ 'warning',
402
+ 'FormoAnalytics::_trackSigning: provider.request is not writable'
403
+ );
404
+ return false;
405
+ }
406
+
407
+ // Deliberately not using this._original request to not interfere with the transaction tracking's
408
+ // request modification
409
+ const request = this.provider.request.bind(this.provider);
410
+ this.provider.request = async ({ method, params }: RequestArguments) => {
411
+ if (Array.isArray(params)) {
412
+ if (['signTypedData_v4', 'eth_sign'].includes(method)) {
413
+ this.trackEvent(Event.SIGNING_TRIGGERED, {
414
+ account: params[0],
415
+ message: params[1],
416
+ });
417
+ }
418
+ if (method === 'personal_sign') {
419
+ this.trackEvent(Event.SIGNING_TRIGGERED, {
420
+ message: params[0],
421
+ account: params[1],
422
+ });
423
+ }
424
+ }
425
+ return request({ method, params });
426
+ };
427
+ return true;
428
+ }
429
+
410
430
  private async getCurrentChainId(): Promise<string> {
411
431
  if (!this.provider) {
412
432
  console.error('FormoAnalytics::getCurrentChainId: provider not set');
@@ -435,8 +455,7 @@ export class FormoAnalytics implements IFormoAnalytics {
435
455
 
436
456
  this.currentChainId = await this.getCurrentChainId();
437
457
 
438
- this.connect({ account, chainId: this.currentChainId });
439
- this.storeWalletAddress(account);
458
+ return this.connect({ chainId: this.currentChainId, address: account });
440
459
  }
441
460
 
442
461
  private async getCurrentWallet() {
@@ -444,49 +463,21 @@ export class FormoAnalytics implements IFormoAnalytics {
444
463
  console.warn('FormoAnalytics::getCurrentWallet: the provider is not set');
445
464
  return;
446
465
  }
447
- const sessionData = sessionStorage.getItem(this.sessionKey);
448
-
449
- if (!sessionData) {
450
- return null;
451
- }
466
+ try {
467
+ const accounts = await this.provider.request<string[]>({
468
+ method: 'eth_accounts',
469
+ });
452
470
 
453
- const parsedData = JSON.parse(sessionData);
454
- const sessionExpiry = 30 * 60 * 1000; // 30 minutes in milliseconds
455
- const currentTime = Date.now();
471
+ if (accounts && accounts.length > 0 && accounts[0]) {
472
+ this.handleAccountConnected(accounts[0]);
473
+ return accounts && accounts.length > 0 && accounts[0];
474
+ }
456
475
 
457
- if (currentTime - parsedData.timestamp > sessionExpiry) {
458
- console.warn('Session expired. Ignoring wallet address.');
459
- sessionStorage.removeItem(this.sessionKey); // Clear expired session data
476
+ return '';
477
+ } catch (error) {
478
+ console.error('Failed to fetch connected address:', error);
460
479
  return '';
461
480
  }
462
-
463
- this.handleAccountConnected(parsedData.address);
464
- return parsedData.address || '';
465
- }
466
-
467
- /**
468
- * Stores the wallet address in session storage when connected.
469
- * @param address - The wallet address to store.
470
- */
471
- private storeWalletAddress(address: string): void {
472
- if (!address) {
473
- console.error('No wallet address provided to store.');
474
- return;
475
- }
476
-
477
- const sessionData = {
478
- address,
479
- timestamp: Date.now(),
480
- };
481
-
482
- sessionStorage.setItem(this.sessionKey, JSON.stringify(sessionData));
483
- }
484
-
485
- /**
486
- * Clears the wallet address from session storage when disconnected.
487
- */
488
- private clearWalletAddress(): void {
489
- sessionStorage.removeItem(this.sessionKey);
490
481
  }
491
482
 
492
483
  // Function to build the API URL
@@ -507,20 +498,20 @@ export class FormoAnalytics implements IFormoAnalytics {
507
498
  return 'Error: No token provided';
508
499
  }
509
500
 
510
- connect({ account, chainId }: { account: string; chainId: ChainID }) {
501
+ connect({ chainId, address }: { chainId: ChainID; address: string }): void {
511
502
  if (!chainId) {
512
- throw new Error('FormoAnalytics::connect: chainId cannot be empty');
503
+ throw new Error('FormoAnalytics::wallet: chainId cannot be empty');
513
504
  }
514
- if (!account) {
515
- throw new Error('FormoAnalytics::connect: account cannot be empty');
505
+ if (!address) {
506
+ throw new Error('FormoAnalytics::wallet: account cannot be empty');
516
507
  }
517
508
 
518
509
  this.currentChainId = chainId.toString();
519
- this.currentConnectedAccount = account;
510
+ this.currentConnectedAccount = address;
520
511
 
521
- return this.trackEvent(Event.CONNECT, {
512
+ this.trackEvent(Event.CONNECT, {
522
513
  chainId,
523
- address: account,
514
+ address,
524
515
  });
525
516
  }
526
517
 
@@ -551,7 +542,7 @@ export class FormoAnalytics implements IFormoAnalytics {
551
542
 
552
543
  if (!account && !this.currentConnectedAccount) {
553
544
  throw new Error(
554
- 'FormoAnalytics::chain: account was empty and no previous account has been recorded. You can either pass an account or call connect() first'
545
+ 'FormoAnalytics::chain: account was empty and no previous account has been recorded. You can either pass an account or call wallet() first'
555
546
  );
556
547
  }
557
548
 
@@ -1,7 +1,9 @@
1
1
  export enum Event {
2
- IDENTIFY = 'identify',
3
- PAGE = 'page_hit',
2
+ PAGE = 'page',
4
3
  CONNECT = 'connect',
5
4
  DISCONNECT = 'disconnect',
6
5
  CHAIN_CHANGED = 'chain_changed',
7
- }
6
+ SIGNING_TRIGGERED = 'signing_triggered',
7
+ CLICK = 'click',
8
+ CUSTOM = 'custom',
9
+ }
@@ -1,2 +1,2 @@
1
1
  export * from './base';
2
- export * from './wallet'
2
+ export * from './web3'
@@ -1 +0,0 @@
1
- {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../../../src/types/wallet.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,QAAQ,CAAA;AAEjC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC7C;AAED,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;IACjE,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAA;IAC5E,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAA;CACzF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"wallet.js","sourceRoot":"","sources":["../../../../src/types/wallet.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../../../src/types/wallet.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,QAAQ,CAAA;AAEjC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC7C;AAED,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;IACjE,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAA;IAC5E,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAA;CACzF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=wallet.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"wallet.js","sourceRoot":"","sources":["../../../../src/types/wallet.ts"],"names":[],"mappings":""}
File without changes