@formo/analytics 1.19.10 → 1.21.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.
Files changed (55) hide show
  1. package/README.md +3 -1
  2. package/dist/cjs/src/FormoAnalytics.d.ts +17 -1
  3. package/dist/cjs/src/FormoAnalytics.js +150 -82
  4. package/dist/cjs/src/FormoAnalyticsProvider.js +5 -1
  5. package/dist/cjs/src/constants/base.d.ts +4 -0
  6. package/dist/cjs/src/constants/base.js +8 -1
  7. package/dist/cjs/src/lib/browser/browsers.d.ts +3 -0
  8. package/dist/cjs/src/lib/browser/browsers.js +132 -0
  9. package/dist/cjs/src/lib/consent.d.ts +35 -0
  10. package/dist/cjs/src/lib/consent.js +102 -0
  11. package/dist/cjs/src/lib/event/EventFactory.d.ts +10 -10
  12. package/dist/cjs/src/lib/event/EventFactory.js +272 -140
  13. package/dist/cjs/src/lib/event/EventManager.d.ts +1 -1
  14. package/dist/cjs/src/lib/event/EventManager.js +62 -9
  15. package/dist/cjs/src/lib/event/type.d.ts +2 -2
  16. package/dist/cjs/src/lib/index.d.ts +1 -0
  17. package/dist/cjs/src/lib/index.js +1 -0
  18. package/dist/cjs/src/lib/storage/built-in/blueprint.js +2 -1
  19. package/dist/cjs/src/lib/version.d.ts +1 -1
  20. package/dist/cjs/src/lib/version.js +1 -1
  21. package/dist/cjs/src/types/base.d.ts +3 -0
  22. package/dist/cjs/src/utils/address.d.ts +7 -0
  23. package/dist/cjs/src/utils/address.js +21 -1
  24. package/dist/cjs/src/utils/hash.d.ts +10 -0
  25. package/dist/cjs/src/utils/hash.js +21 -0
  26. package/dist/cjs/src/utils/index.d.ts +1 -0
  27. package/dist/cjs/src/utils/index.js +1 -0
  28. package/dist/esm/src/FormoAnalytics.d.ts +17 -1
  29. package/dist/esm/src/FormoAnalytics.js +152 -84
  30. package/dist/esm/src/FormoAnalyticsProvider.js +5 -1
  31. package/dist/esm/src/constants/base.d.ts +4 -0
  32. package/dist/esm/src/constants/base.js +7 -0
  33. package/dist/esm/src/lib/browser/browsers.d.ts +3 -0
  34. package/dist/esm/src/lib/browser/browsers.js +129 -0
  35. package/dist/esm/src/lib/consent.d.ts +35 -0
  36. package/dist/esm/src/lib/consent.js +97 -0
  37. package/dist/esm/src/lib/event/EventFactory.d.ts +10 -10
  38. package/dist/esm/src/lib/event/EventFactory.js +272 -140
  39. package/dist/esm/src/lib/event/EventManager.d.ts +1 -1
  40. package/dist/esm/src/lib/event/EventManager.js +62 -9
  41. package/dist/esm/src/lib/event/type.d.ts +2 -2
  42. package/dist/esm/src/lib/index.d.ts +1 -0
  43. package/dist/esm/src/lib/index.js +1 -0
  44. package/dist/esm/src/lib/storage/built-in/blueprint.js +2 -1
  45. package/dist/esm/src/lib/version.d.ts +1 -1
  46. package/dist/esm/src/lib/version.js +1 -1
  47. package/dist/esm/src/types/base.d.ts +3 -0
  48. package/dist/esm/src/utils/address.d.ts +7 -0
  49. package/dist/esm/src/utils/address.js +19 -0
  50. package/dist/esm/src/utils/hash.d.ts +10 -0
  51. package/dist/esm/src/utils/hash.js +18 -0
  52. package/dist/esm/src/utils/index.d.ts +1 -0
  53. package/dist/esm/src/utils/index.js +1 -0
  54. package/dist/index.umd.min.js +1 -1
  55. package/package.json +2 -2
package/README.md CHANGED
@@ -24,7 +24,9 @@ You can install Formo on:
24
24
  - [React apps](https://docs.formo.so/install#react)
25
25
  - [Next.js apps](https://docs.formo.so/install#next-js-app-router)
26
26
 
27
- Visit Formo's [Developer Docs](https://docs.formo.so) for detailed guides and installation instructions.
27
+ ## Configuration
28
+
29
+ Visit Formo's [Developer Docs](https://docs.formo.so) for detailed guides on local testing, debugging, and consent management.
28
30
 
29
31
  ## Methodology
30
32
 
@@ -177,6 +177,22 @@ export declare class FormoAnalytics implements IFormoAnalytics {
177
177
  * @returns {Promise<void>}
178
178
  */
179
179
  track(event: string, properties?: IFormoEventProperties, context?: IFormoEventContext, callback?: (...args: unknown[]) => void): Promise<void>;
180
+ /**
181
+ * Opt out of tracking.
182
+ * @returns {void}
183
+ */
184
+ optOutTracking(): void;
185
+ /**
186
+ * Opt back into tracking after previously opting out. This will re-enable analytics tracking
187
+ * and switch back to persistent storage.
188
+ * @returns {void}
189
+ */
190
+ optInTracking(): void;
191
+ /**
192
+ * Check if the user has opted out of tracking.
193
+ * @returns {boolean} True if the user has opted out
194
+ */
195
+ hasOptedOutTracking(): boolean;
180
196
  private trackProvider;
181
197
  private trackProviders;
182
198
  private addProviderListener;
@@ -204,7 +220,7 @@ export declare class FormoAnalytics implements IFormoAnalytics {
204
220
  private trackPageHit;
205
221
  private trackEvent;
206
222
  /**
207
- * Determines if tracking should be enabled based on configuration
223
+ * Determines if tracking should be enabled based on configuration and consent
208
224
  * @returns {boolean} True if tracking should be enabled
209
225
  */
210
226
  private shouldTrack;
@@ -71,7 +71,7 @@ var chain_1 = require("./utils/chain");
71
71
  var PROVIDER_SWITCH_REASONS = {
72
72
  ADDRESS_MISMATCH: "Address mismatch indicates wallet switch",
73
73
  NO_ACCOUNTS: "Current provider has no accounts",
74
- CHECK_FAILED: "Could not check current provider accounts"
74
+ CHECK_FAILED: "Could not check current provider accounts",
75
75
  };
76
76
  var FormoAnalytics = /** @class */ (function () {
77
77
  function FormoAnalytics(writeKey, options) {
@@ -126,13 +126,17 @@ var FormoAnalytics = /** @class */ (function () {
126
126
  maxQueueSize: options.maxQueueSize,
127
127
  flushInterval: options.flushInterval,
128
128
  }));
129
+ // Check consent status on initialization
130
+ if (this.hasOptedOutTracking()) {
131
+ lib_1.logger.info("User has previously opted out of tracking");
132
+ }
129
133
  // Handle initial provider (injected) as fallback; listeners for EIP-6963 are added later
130
134
  var provider = undefined;
131
135
  var optProvider = options.provider;
132
136
  if (optProvider) {
133
137
  provider = optProvider;
134
138
  }
135
- else if (typeof window !== 'undefined' && window.ethereum) {
139
+ else if (typeof window !== "undefined" && window.ethereum) {
136
140
  provider = window.ethereum;
137
141
  }
138
142
  if (provider) {
@@ -159,9 +163,9 @@ var FormoAnalytics = /** @class */ (function () {
159
163
  FormoAnalytics.prototype.isProviderInValidState = function (provider) {
160
164
  // Basic validation: ensure provider exists and has required methods
161
165
  return (provider &&
162
- typeof provider.request === 'function' &&
163
- typeof provider.on === 'function' &&
164
- typeof provider.removeListener === 'function');
166
+ typeof provider.request === "function" &&
167
+ typeof provider.on === "function" &&
168
+ typeof provider.removeListener === "function");
165
169
  };
166
170
  FormoAnalytics.init = function (writeKey, options) {
167
171
  return __awaiter(this, void 0, void 0, function () {
@@ -280,16 +284,18 @@ var FormoAnalytics = /** @class */ (function () {
280
284
  case 0:
281
285
  chainId = (params === null || params === void 0 ? void 0 : params.chainId) || this.currentChainId;
282
286
  address = (params === null || params === void 0 ? void 0 : params.address) || this.currentAddress;
283
- providerInfo = this._provider ? this.getProviderInfo(this._provider) : null;
287
+ providerInfo = this._provider
288
+ ? this.getProviderInfo(this._provider)
289
+ : null;
284
290
  lib_1.logger.info("Disconnect: Emitting disconnect event with:", {
285
291
  chainId: chainId,
286
292
  address: address,
287
293
  providerName: providerInfo === null || providerInfo === void 0 ? void 0 : providerInfo.name,
288
- rdns: providerInfo === null || providerInfo === void 0 ? void 0 : providerInfo.rdns
294
+ rdns: providerInfo === null || providerInfo === void 0 ? void 0 : providerInfo.rdns,
289
295
  });
290
296
  disconnectProperties = __assign(__assign({}, (providerInfo && {
291
297
  providerName: providerInfo.name,
292
- rdns: providerInfo.rdns
298
+ rdns: providerInfo.rdns,
293
299
  })), properties);
294
300
  return [4 /*yield*/, this.trackEvent(constants_1.EventType.DISCONNECT, __assign(__assign({}, (chainId && { chainId: chainId })), (address && { address: address })), disconnectProperties, context, callback)];
295
301
  case 1:
@@ -436,9 +442,12 @@ var FormoAnalytics = /** @class */ (function () {
436
442
  validAddress: validAddress_1,
437
443
  rdns: providerDetail.info.rdns,
438
444
  providerName: providerDetail.info.name,
439
- isAlreadyIdentified: validAddress_1 ? this.session.isWalletIdentified(validAddress_1, providerDetail.info.rdns) : false
445
+ isAlreadyIdentified: validAddress_1
446
+ ? this.session.isWalletIdentified(validAddress_1, providerDetail.info.rdns)
447
+ : false,
440
448
  });
441
- if (!(validAddress_1 && !this.session.isWalletIdentified(validAddress_1, providerDetail.info.rdns))) return [3 /*break*/, 5];
449
+ if (!(validAddress_1 &&
450
+ !this.session.isWalletIdentified(validAddress_1, providerDetail.info.rdns))) return [3 /*break*/, 5];
442
451
  lib_1.logger.info("Auto-identifying", validAddress_1, providerDetail.info.name, providerDetail.info.rdns);
443
452
  // NOTE: do not set this.currentAddress without explicit connect or identify
444
453
  return [4 /*yield*/, this.identify({
@@ -482,23 +491,25 @@ var FormoAnalytics = /** @class */ (function () {
482
491
  this.currentUserId = userId;
483
492
  (0, lib_1.cookie)().set(constants_1.SESSION_USER_ID_KEY, userId);
484
493
  }
485
- isAlreadyIdentified = validAddress ? this.session.isWalletIdentified(validAddress, rdns || '') : false;
494
+ isAlreadyIdentified = validAddress
495
+ ? this.session.isWalletIdentified(validAddress, rdns || "")
496
+ : false;
486
497
  lib_1.logger.debug("Identify: Checking deduplication", {
487
498
  validAddress: validAddress,
488
499
  rdns: rdns,
489
500
  providerName: providerName,
490
501
  hasValidAddress: !!validAddress,
491
502
  hasRdns: !!rdns,
492
- isAlreadyIdentified: isAlreadyIdentified
503
+ isAlreadyIdentified: isAlreadyIdentified,
493
504
  });
494
505
  if (isAlreadyIdentified) {
495
- lib_1.logger.info("Identify: Wallet ".concat(providerName || 'Unknown', " with address ").concat(validAddress, " already identified in this session (rdns: ").concat(rdns || 'empty', ")"));
506
+ lib_1.logger.info("Identify: Wallet ".concat(providerName || "Unknown", " with address ").concat(validAddress, " already identified in this session (rdns: ").concat(rdns || "empty", ")"));
496
507
  return [2 /*return*/];
497
508
  }
498
509
  // Mark as identified before emitting the event
499
510
  // Mark even if rdns is empty to prevent duplicate empty identifies
500
511
  if (validAddress) {
501
- this.session.markWalletIdentified(validAddress, rdns || '');
512
+ this.session.markWalletIdentified(validAddress, rdns || "");
502
513
  }
503
514
  return [4 /*yield*/, this.trackEvent(constants_1.EventType.IDENTIFY, {
504
515
  address: validAddress,
@@ -567,6 +578,39 @@ var FormoAnalytics = /** @class */ (function () {
567
578
  });
568
579
  });
569
580
  };
581
+ /*
582
+ Consent management functions
583
+ */
584
+ /**
585
+ * Opt out of tracking.
586
+ * @returns {void}
587
+ */
588
+ FormoAnalytics.prototype.optOutTracking = function () {
589
+ lib_1.logger.info("Opting out of tracking");
590
+ // Set opt-out flag in persistent storage using direct cookie access
591
+ // This must be done before switching storage to ensure persistence
592
+ (0, lib_1.setConsentFlag)(this.writeKey, constants_1.CONSENT_OPT_OUT_KEY, "true");
593
+ this.reset();
594
+ lib_1.logger.info("Successfully opted out of tracking");
595
+ };
596
+ /**
597
+ * Opt back into tracking after previously opting out. This will re-enable analytics tracking
598
+ * and switch back to persistent storage.
599
+ * @returns {void}
600
+ */
601
+ FormoAnalytics.prototype.optInTracking = function () {
602
+ lib_1.logger.info("Opting back into tracking");
603
+ // Remove opt-out flag
604
+ (0, lib_1.removeConsentFlag)(this.writeKey, constants_1.CONSENT_OPT_OUT_KEY);
605
+ lib_1.logger.info("Successfully opted back into tracking");
606
+ };
607
+ /**
608
+ * Check if the user has opted out of tracking.
609
+ * @returns {boolean} True if the user has opted out
610
+ */
611
+ FormoAnalytics.prototype.hasOptedOutTracking = function () {
612
+ return (0, lib_1.getConsentFlag)(this.writeKey, constants_1.CONSENT_OPT_OUT_KEY) === "true";
613
+ };
570
614
  /*
571
615
  SDK tracking and event listener functions
572
616
  */
@@ -633,7 +677,7 @@ var FormoAnalytics = /** @class */ (function () {
633
677
  // Prevent concurrent processing of accountsChanged events to avoid race conditions
634
678
  if (this._processingAccountsChanged) {
635
679
  lib_1.logger.debug("OnAccountsChanged: Already processing accountsChanged, skipping", {
636
- provider: this.getProviderInfo(provider).name
680
+ provider: this.getProviderInfo(provider).name,
637
681
  });
638
682
  return [2 /*return*/];
639
683
  }
@@ -674,7 +718,7 @@ var FormoAnalytics = /** @class */ (function () {
674
718
  lib_1.logger.info("OnAccountsChanged: Detecting disconnect, current state:", {
675
719
  currentAddress: this.currentAddress,
676
720
  currentChainId: this.currentChainId,
677
- providerMatch: this._provider === provider
721
+ providerMatch: this._provider === provider,
678
722
  });
679
723
  _a.label = 1;
680
724
  case 1:
@@ -682,7 +726,7 @@ var FormoAnalytics = /** @class */ (function () {
682
726
  // Pass current state explicitly to ensure we have the data for the disconnect event
683
727
  return [4 /*yield*/, this.disconnect({
684
728
  chainId: this.currentChainId,
685
- address: this.currentAddress
729
+ address: this.currentAddress,
686
730
  })];
687
731
  case 2:
688
732
  // Pass current state explicitly to ensure we have the data for the disconnect event
@@ -710,7 +754,7 @@ var FormoAnalytics = /** @class */ (function () {
710
754
  activeProvider: this.getProviderInfo(this._provider).name,
711
755
  eventProvider: this.getProviderInfo(provider).name,
712
756
  currentStoredAddress: currentStoredAddress,
713
- newProviderAddress: newProviderAddress
757
+ newProviderAddress: newProviderAddress,
714
758
  });
715
759
  _a.label = 8;
716
760
  case 8:
@@ -720,22 +764,26 @@ var FormoAnalytics = /** @class */ (function () {
720
764
  activeProviderAccounts = _a.sent();
721
765
  lib_1.logger.info("OnAccountsChanged: Checking current provider accounts", {
722
766
  activeProvider: this.getProviderInfo(this._provider).name,
723
- accountsLength: activeProviderAccounts ? activeProviderAccounts.length : 0,
724
- accounts: activeProviderAccounts
767
+ accountsLength: activeProviderAccounts
768
+ ? activeProviderAccounts.length
769
+ : 0,
770
+ accounts: activeProviderAccounts,
725
771
  });
726
772
  if (!(activeProviderAccounts && activeProviderAccounts.length > 0)) return [3 /*break*/, 13];
727
- if (!(newProviderAddress && currentStoredAddress && newProviderAddress !== currentStoredAddress)) return [3 /*break*/, 11];
773
+ if (!(newProviderAddress &&
774
+ currentStoredAddress &&
775
+ newProviderAddress !== currentStoredAddress)) return [3 /*break*/, 11];
728
776
  lib_1.logger.info("OnAccountsChanged: Different address detected, switching providers despite current provider having accounts", {
729
777
  activeProvider: this.getProviderInfo(this._provider).name,
730
778
  eventProvider: this.getProviderInfo(provider).name,
731
779
  currentAddress: currentStoredAddress,
732
780
  newAddress: newProviderAddress,
733
- reason: PROVIDER_SWITCH_REASONS.ADDRESS_MISMATCH
781
+ reason: PROVIDER_SWITCH_REASONS.ADDRESS_MISMATCH,
734
782
  });
735
783
  // Emit disconnect for the old provider
736
784
  return [4 /*yield*/, this.disconnect({
737
785
  chainId: this.currentChainId,
738
- address: this.currentAddress
786
+ address: this.currentAddress,
739
787
  })];
740
788
  case 10:
741
789
  // Emit disconnect for the old provider
@@ -749,7 +797,7 @@ var FormoAnalytics = /** @class */ (function () {
749
797
  eventProvider: this.getProviderInfo(provider).name,
750
798
  activeProviderAccountsCount: activeProviderAccounts.length,
751
799
  currentAddress: currentStoredAddress,
752
- newAddress: newProviderAddress
800
+ newAddress: newProviderAddress,
753
801
  });
754
802
  return [2 /*return*/];
755
803
  case 12: return [3 /*break*/, 15];
@@ -757,12 +805,12 @@ var FormoAnalytics = /** @class */ (function () {
757
805
  lib_1.logger.info("OnAccountsChanged: Current provider has no accounts, switching to new provider", {
758
806
  oldProvider: this.getProviderInfo(this._provider).name,
759
807
  newProvider: this.getProviderInfo(provider).name,
760
- reason: PROVIDER_SWITCH_REASONS.NO_ACCOUNTS
808
+ reason: PROVIDER_SWITCH_REASONS.NO_ACCOUNTS,
761
809
  });
762
810
  // Emit disconnect for the old provider that didn't signal properly
763
811
  return [4 /*yield*/, this.disconnect({
764
812
  chainId: this.currentChainId,
765
- address: this.currentAddress
813
+ address: this.currentAddress,
766
814
  })];
767
815
  case 14:
768
816
  // Emit disconnect for the old provider that didn't signal properly
@@ -776,14 +824,16 @@ var FormoAnalytics = /** @class */ (function () {
776
824
  lib_1.logger.warn("OnAccountsChanged: Could not check current provider accounts, switching to new provider", {
777
825
  error: error_2 instanceof Error ? error_2.message : String(error_2),
778
826
  errorType: error_2 instanceof Error ? error_2.constructor.name : typeof error_2,
779
- oldProvider: this._provider ? this.getProviderInfo(this._provider).name : 'unknown',
827
+ oldProvider: this._provider
828
+ ? this.getProviderInfo(this._provider).name
829
+ : "unknown",
780
830
  newProvider: this.getProviderInfo(provider).name,
781
- reason: PROVIDER_SWITCH_REASONS.CHECK_FAILED
831
+ reason: PROVIDER_SWITCH_REASONS.CHECK_FAILED,
782
832
  });
783
833
  // If we can't check the current provider, assume it's disconnected
784
834
  return [4 /*yield*/, this.disconnect({
785
835
  chainId: this.currentChainId,
786
- address: this.currentAddress
836
+ address: this.currentAddress,
787
837
  })];
788
838
  case 17:
789
839
  // If we can't check the current provider, assume it's disconnected
@@ -812,7 +862,7 @@ var FormoAnalytics = /** @class */ (function () {
812
862
  wasDisconnected: wasDisconnected,
813
863
  providerName: providerInfo.name,
814
864
  rdns: providerInfo.rdns,
815
- hasChainId: !!nextChainId
865
+ hasChainId: !!nextChainId,
816
866
  });
817
867
  effectiveChainId = nextChainId || 0;
818
868
  if (effectiveChainId === 0) {
@@ -820,10 +870,10 @@ var FormoAnalytics = /** @class */ (function () {
820
870
  }
821
871
  this.connect({
822
872
  chainId: effectiveChainId,
823
- address: address
873
+ address: address,
824
874
  }, {
825
875
  providerName: providerInfo.name,
826
- rdns: providerInfo.rdns
876
+ rdns: providerInfo.rdns,
827
877
  }).catch(function (error) {
828
878
  lib_1.logger.error("Failed to track connect event during account change:", error);
829
879
  });
@@ -905,7 +955,7 @@ var FormoAnalytics = /** @class */ (function () {
905
955
  return [2 /*return*/];
906
956
  lib_1.logger.info("OnDisconnect: Wallet disconnect event received, current state:", {
907
957
  currentAddress: this.currentAddress,
908
- currentChainId: this.currentChainId
958
+ currentChainId: this.currentChainId,
909
959
  });
910
960
  _a.label = 1;
911
961
  case 1:
@@ -913,7 +963,7 @@ var FormoAnalytics = /** @class */ (function () {
913
963
  // Pass current state explicitly to ensure we have the data for the disconnect event
914
964
  return [4 /*yield*/, this.disconnect({
915
965
  chainId: this.currentChainId,
916
- address: this.currentAddress
966
+ address: this.currentAddress,
917
967
  })];
918
968
  case 2:
919
969
  // Pass current state explicitly to ensure we have the data for the disconnect event
@@ -940,7 +990,7 @@ var FormoAnalytics = /** @class */ (function () {
940
990
  _a.label = 1;
941
991
  case 1:
942
992
  _a.trys.push([1, 3, , 4]);
943
- if (!(connection === null || connection === void 0 ? void 0 : connection.chainId) || typeof connection.chainId !== 'string')
993
+ if (!(connection === null || connection === void 0 ? void 0 : connection.chainId) || typeof connection.chainId !== "string")
944
994
  return [2 /*return*/];
945
995
  chainId = (0, chain_1.parseChainId)(connection.chainId);
946
996
  return [4 /*yield*/, this.getAddress(provider)];
@@ -956,7 +1006,8 @@ var FormoAnalytics = /** @class */ (function () {
956
1006
  // Only update global state (chainId/address) from the active provider
957
1007
  if (isActiveProvider) {
958
1008
  this.currentChainId = chainId;
959
- this.currentAddress = this.validateAndChecksumAddress(address) || undefined;
1009
+ this.currentAddress =
1010
+ this.validateAndChecksumAddress(address) || undefined;
960
1011
  }
961
1012
  if (isActiveProvider && this.currentAddress) {
962
1013
  providerInfo = this.getProviderInfo(provider);
@@ -966,7 +1017,7 @@ var FormoAnalytics = /** @class */ (function () {
966
1017
  providerName: providerInfo.name,
967
1018
  rdns: providerInfo.rdns,
968
1019
  hasChainId: !!chainId,
969
- isActiveProvider: isActiveProvider
1020
+ isActiveProvider: isActiveProvider,
970
1021
  });
971
1022
  effectiveChainId = chainId || 0;
972
1023
  if (effectiveChainId === 0) {
@@ -974,10 +1025,10 @@ var FormoAnalytics = /** @class */ (function () {
974
1025
  }
975
1026
  this.connect({
976
1027
  chainId: effectiveChainId,
977
- address: address
1028
+ address: address,
978
1029
  }, {
979
1030
  providerName: providerInfo.name,
980
- rdns: providerInfo.rdns
1031
+ rdns: providerInfo.rdns,
981
1032
  }).catch(function (error) {
982
1033
  lib_1.logger.error("Failed to track connect event during provider connection:", error);
983
1034
  });
@@ -989,7 +1040,9 @@ var FormoAnalytics = /** @class */ (function () {
989
1040
  providerName: providerInfo.name,
990
1041
  rdns: providerInfo.rdns,
991
1042
  isActiveProvider: isActiveProvider,
992
- activeProviderInfo: this._provider ? this.getProviderInfo(this._provider) : null
1043
+ activeProviderInfo: this._provider
1044
+ ? this.getProviderInfo(this._provider)
1045
+ : null,
993
1046
  });
994
1047
  }
995
1048
  }
@@ -1171,7 +1224,8 @@ var FormoAnalytics = /** @class */ (function () {
1171
1224
  }); };
1172
1225
  // Mark the wrapper so we can detect if request is replaced externally and keep a reference on provider
1173
1226
  wrappedRequest[types_1.WRAPPED_REQUEST_SYMBOL] = true;
1174
- provider[types_1.WRAPPED_REQUEST_REF_SYMBOL] = wrappedRequest;
1227
+ provider[types_1.WRAPPED_REQUEST_REF_SYMBOL] =
1228
+ wrappedRequest;
1175
1229
  try {
1176
1230
  // Attempt to assign the wrapped request function (rely on try-catch for mutability errors)
1177
1231
  provider.request = wrappedRequest;
@@ -1261,44 +1315,55 @@ var FormoAnalytics = /** @class */ (function () {
1261
1315
  };
1262
1316
  FormoAnalytics.prototype.trackEvent = function (type, payload, properties, context, callback) {
1263
1317
  return __awaiter(this, void 0, void 0, function () {
1318
+ var error_5;
1264
1319
  return __generator(this, function (_a) {
1265
- try {
1266
- if (!this.shouldTrack()) {
1267
- lib_1.logger.info("Skipping ".concat(type, " event due to tracking configuration"));
1268
- return [2 /*return*/];
1269
- }
1270
- this.eventManager.addEvent(__assign(__assign({ type: type }, payload), { properties: properties, context: context, callback: callback }), this.currentAddress, this.currentUserId);
1271
- }
1272
- catch (error) {
1273
- lib_1.logger.error("Error tracking event:", error);
1320
+ switch (_a.label) {
1321
+ case 0:
1322
+ _a.trys.push([0, 2, , 3]);
1323
+ if (!this.shouldTrack()) {
1324
+ lib_1.logger.info("Skipping ".concat(type, " event due to tracking configuration"));
1325
+ return [2 /*return*/];
1326
+ }
1327
+ return [4 /*yield*/, this.eventManager.addEvent(__assign(__assign({ type: type }, payload), { properties: properties, context: context, callback: callback }), this.currentAddress, this.currentUserId)];
1328
+ case 1:
1329
+ _a.sent();
1330
+ return [3 /*break*/, 3];
1331
+ case 2:
1332
+ error_5 = _a.sent();
1333
+ lib_1.logger.error("Error tracking event:", error_5);
1334
+ return [3 /*break*/, 3];
1335
+ case 3: return [2 /*return*/];
1274
1336
  }
1275
- return [2 /*return*/];
1276
1337
  });
1277
1338
  });
1278
1339
  };
1279
1340
  /**
1280
- * Determines if tracking should be enabled based on configuration
1341
+ * Determines if tracking should be enabled based on configuration and consent
1281
1342
  * @returns {boolean} True if tracking should be enabled
1282
1343
  */
1283
1344
  FormoAnalytics.prototype.shouldTrack = function () {
1345
+ // First check if user has opted out of tracking
1346
+ if (this.hasOptedOutTracking()) {
1347
+ return false;
1348
+ }
1284
1349
  // Check if tracking is explicitly provided as a boolean
1285
- if (typeof this.options.tracking === 'boolean') {
1350
+ if (typeof this.options.tracking === "boolean") {
1286
1351
  return this.options.tracking;
1287
1352
  }
1288
1353
  // Handle object configuration with exclusion rules
1289
1354
  if (this.options.tracking !== null &&
1290
- typeof this.options.tracking === 'object' &&
1355
+ typeof this.options.tracking === "object" &&
1291
1356
  !Array.isArray(this.options.tracking)) {
1292
1357
  var _a = this.options.tracking, _b = _a.excludeHosts, excludeHosts = _b === void 0 ? [] : _b, _c = _a.excludePaths, excludePaths = _c === void 0 ? [] : _c, _d = _a.excludeChains, excludeChains = _d === void 0 ? [] : _d;
1293
1358
  // Check hostname exclusions - use exact matching
1294
- if (excludeHosts.length > 0 && typeof window !== 'undefined') {
1359
+ if (excludeHosts.length > 0 && typeof window !== "undefined") {
1295
1360
  var hostname = window.location.hostname;
1296
1361
  if (excludeHosts.includes(hostname)) {
1297
1362
  return false;
1298
1363
  }
1299
1364
  }
1300
1365
  // Check path exclusions - use exact matching
1301
- if (excludePaths.length > 0 && typeof window !== 'undefined') {
1366
+ if (excludePaths.length > 0 && typeof window !== "undefined") {
1302
1367
  var pathname = window.location.pathname;
1303
1368
  if (excludePaths.includes(pathname)) {
1304
1369
  return false;
@@ -1330,14 +1395,14 @@ var FormoAnalytics = /** @class */ (function () {
1330
1395
  if (eip6963Provider) {
1331
1396
  return {
1332
1397
  name: eip6963Provider.info.name,
1333
- rdns: eip6963Provider.info.rdns
1398
+ rdns: eip6963Provider.info.rdns,
1334
1399
  };
1335
1400
  }
1336
1401
  // Fallback to injected provider detection
1337
1402
  var injectedInfo = this.detectInjectedProviderInfo(provider);
1338
1403
  return {
1339
1404
  name: injectedInfo.name,
1340
- rdns: injectedInfo.rdns
1405
+ rdns: injectedInfo.rdns,
1341
1406
  };
1342
1407
  };
1343
1408
  /**
@@ -1347,45 +1412,45 @@ var FormoAnalytics = /** @class */ (function () {
1347
1412
  */
1348
1413
  FormoAnalytics.prototype.detectInjectedProviderInfo = function (provider) {
1349
1414
  // Try to detect provider type from common properties
1350
- var name = 'Injected Provider';
1351
- var rdns = 'io.injected.provider';
1415
+ var name = "Injected Provider";
1416
+ var rdns = "io.injected.provider";
1352
1417
  // Use WalletProviderFlags interface for type safety
1353
1418
  var flags = provider;
1354
1419
  // Check if it's MetaMask
1355
1420
  if (flags.isMetaMask) {
1356
- name = 'MetaMask';
1357
- rdns = 'io.metamask';
1421
+ name = "MetaMask";
1422
+ rdns = "io.metamask";
1358
1423
  }
1359
1424
  // Check if it's Coinbase Wallet
1360
1425
  else if (flags.isCoinbaseWallet) {
1361
- name = 'Coinbase Wallet';
1362
- rdns = 'com.coinbase.wallet';
1426
+ name = "Coinbase Wallet";
1427
+ rdns = "com.coinbase.wallet";
1363
1428
  }
1364
1429
  // Check if it's WalletConnect
1365
1430
  else if (flags.isWalletConnect) {
1366
- name = 'WalletConnect';
1367
- rdns = 'com.walletconnect';
1431
+ name = "WalletConnect";
1432
+ rdns = "com.walletconnect";
1368
1433
  }
1369
1434
  // Check if it's Trust Wallet
1370
1435
  else if (flags.isTrust) {
1371
- name = 'Trust Wallet';
1372
- rdns = 'com.trustwallet';
1436
+ name = "Trust Wallet";
1437
+ rdns = "com.trustwallet";
1373
1438
  }
1374
1439
  // Check if it's Brave Wallet
1375
1440
  else if (flags.isBraveWallet) {
1376
- name = 'Brave Wallet';
1377
- rdns = 'com.brave.wallet';
1441
+ name = "Brave Wallet";
1442
+ rdns = "com.brave.wallet";
1378
1443
  }
1379
1444
  // Check if it's Phantom
1380
1445
  else if (flags.isPhantom) {
1381
- name = 'Phantom';
1382
- rdns = 'app.phantom';
1446
+ name = "Phantom";
1447
+ rdns = "app.phantom";
1383
1448
  }
1384
1449
  return {
1385
1450
  name: name,
1386
1451
  rdns: rdns,
1387
- uuid: "injected-".concat(rdns.replace(/[^a-zA-Z0-9]/g, '-')),
1388
- icon: constants_1.DEFAULT_PROVIDER_ICON
1452
+ uuid: "injected-".concat(rdns.replace(/[^a-zA-Z0-9]/g, "-")),
1453
+ icon: constants_1.DEFAULT_PROVIDER_ICON,
1389
1454
  };
1390
1455
  };
1391
1456
  FormoAnalytics.prototype.getProviders = function () {
@@ -1439,7 +1504,7 @@ var FormoAnalytics = /** @class */ (function () {
1439
1504
  });
1440
1505
  // Fallback to injected provider if no providers are found
1441
1506
  if (providers.length === 0) {
1442
- injected_1 = typeof window !== 'undefined' ? window.ethereum : undefined;
1507
+ injected_1 = typeof window !== "undefined" ? window.ethereum : undefined;
1443
1508
  if (injected_1) {
1444
1509
  // If we have already detected and cached the injected provider, and it's the same instance, return the cached result
1445
1510
  if (this._injectedProviderDetail &&
@@ -1450,7 +1515,9 @@ var FormoAnalytics = /** @class */ (function () {
1450
1515
  }
1451
1516
  // Merge with existing providers instead of overwriting
1452
1517
  if (!this._providers.some(function (existing) { return existing.provider === injected_1; })) {
1453
- this._providers = __spreadArray(__spreadArray([], this._providers, true), [this._injectedProviderDetail], false);
1518
+ this._providers = __spreadArray(__spreadArray([], this._providers, true), [
1519
+ this._injectedProviderDetail,
1520
+ ], false);
1454
1521
  }
1455
1522
  return [2 /*return*/, this._providers];
1456
1523
  }
@@ -1461,7 +1528,7 @@ var FormoAnalytics = /** @class */ (function () {
1461
1528
  injectedProviderInfo = this.detectInjectedProviderInfo(injected_1);
1462
1529
  injectedDetail = {
1463
1530
  provider: injected_1,
1464
- info: injectedProviderInfo
1531
+ info: injectedProviderInfo,
1465
1532
  };
1466
1533
  // Cache the detected injected provider detail
1467
1534
  this._injectedProviderDetail = injectedDetail;
@@ -1800,9 +1867,10 @@ var FormoAnalytics = /** @class */ (function () {
1800
1867
  */
1801
1868
  FormoAnalytics.prototype.isProviderAlreadyWrapped = function (provider, currentRequest) {
1802
1869
  return !!(currentRequest &&
1803
- typeof currentRequest === 'function' &&
1870
+ typeof currentRequest === "function" &&
1804
1871
  currentRequest[types_1.WRAPPED_REQUEST_SYMBOL] &&
1805
- provider[types_1.WRAPPED_REQUEST_REF_SYMBOL] === currentRequest);
1872
+ provider[types_1.WRAPPED_REQUEST_REF_SYMBOL] ===
1873
+ currentRequest);
1806
1874
  };
1807
1875
  /**
1808
1876
  * Handle provider mismatch by switching to the new provider and invalidating old tokens
@@ -1891,7 +1959,7 @@ var FormoAnalyticsSession = /** @class */ (function () {
1891
1959
  lib_1.logger.debug("Session: Checking wallet identification", {
1892
1960
  identifiedKey: identifiedKey,
1893
1961
  isIdentified: isIdentified,
1894
- hasRdns: !!rdns
1962
+ hasRdns: !!rdns,
1895
1963
  });
1896
1964
  return isIdentified;
1897
1965
  };
@@ -1909,14 +1977,14 @@ var FormoAnalyticsSession = /** @class */ (function () {
1909
1977
  });
1910
1978
  lib_1.logger.debug("Session: Marked wallet as identified", {
1911
1979
  identifiedKey: identifiedKey,
1912
- hasRdns: !!rdns
1980
+ hasRdns: !!rdns,
1913
1981
  });
1914
1982
  }
1915
1983
  else {
1916
1984
  lib_1.logger.info("Session: Wallet already marked as identified", {
1917
1985
  identifiedKey: identifiedKey,
1918
1986
  existingWallets: identifiedWallets,
1919
- hasRdns: !!rdns
1987
+ hasRdns: !!rdns,
1920
1988
  });
1921
1989
  }
1922
1990
  };
@@ -55,7 +55,7 @@ var lib_1 = require("./lib");
55
55
  var defaultContext = {
56
56
  chain: function () { return Promise.resolve(); },
57
57
  page: function () { return Promise.resolve(); },
58
- reset: function () { return Promise.resolve(); },
58
+ reset: function () { },
59
59
  detect: function () { return Promise.resolve(); },
60
60
  connect: function () { return Promise.resolve(); },
61
61
  disconnect: function () { return Promise.resolve(); },
@@ -63,6 +63,10 @@ var defaultContext = {
63
63
  transaction: function () { return Promise.resolve(); },
64
64
  identify: function () { return Promise.resolve(); },
65
65
  track: function () { return Promise.resolve(); },
66
+ // Consent management methods
67
+ optOutTracking: function () { },
68
+ optInTracking: function () { },
69
+ hasOptedOutTracking: function () { return false; },
66
70
  };
67
71
  exports.FormoAnalyticsContext = (0, react_1.createContext)(defaultContext);
68
72
  var FormoAnalyticsProvider = function (props) {
@@ -4,5 +4,9 @@ export declare const SESSION_WALLET_IDENTIFIED_KEY = "wallet-identified";
4
4
  export declare const SESSION_CURRENT_URL_KEY = "analytics-current-url";
5
5
  export declare const SESSION_USER_ID_KEY = "user-id";
6
6
  export declare const LOCAL_ANONYMOUS_ID_KEY = "anonymous-id";
7
+ export declare const CONSENT_OPT_OUT_KEY = "opt-out-tracking";
7
8
  export declare const DEFAULT_PROVIDER_ICON = "data:image/svg+xml;base64,";
9
+ export declare const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
10
+ export declare const DEAD_ADDRESS = "0x000000000000000000000000000000000000dEaD";
11
+ export declare const BLOCKED_ADDRESSES: readonly ["0x0000000000000000000000000000000000000000", "0x000000000000000000000000000000000000dEaD"];
8
12
  //# sourceMappingURL=base.d.ts.map