@formo/analytics 1.20.0 → 1.22.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.
@@ -68,7 +68,7 @@ import { parseChainId } from "./utils/chain";
68
68
  var PROVIDER_SWITCH_REASONS = {
69
69
  ADDRESS_MISMATCH: "Address mismatch indicates wallet switch",
70
70
  NO_ACCOUNTS: "Current provider has no accounts",
71
- CHECK_FAILED: "Could not check current provider accounts"
71
+ CHECK_FAILED: "Could not check current provider accounts",
72
72
  };
73
73
  var FormoAnalytics = /** @class */ (function () {
74
74
  function FormoAnalytics(writeKey, options) {
@@ -111,6 +111,7 @@ var FormoAnalytics = /** @class */ (function () {
111
111
  this.transaction = this.transaction.bind(this);
112
112
  this.detect = this.detect.bind(this);
113
113
  this.track = this.track.bind(this);
114
+ this.isAutocaptureEnabled = this.isAutocaptureEnabled.bind(this);
114
115
  // Initialize logger with configuration from options
115
116
  Logger.init({
116
117
  enabled: ((_a = options.logger) === null || _a === void 0 ? void 0 : _a.enabled) || false,
@@ -133,7 +134,7 @@ var FormoAnalytics = /** @class */ (function () {
133
134
  if (optProvider) {
134
135
  provider = optProvider;
135
136
  }
136
- else if (typeof window !== 'undefined' && window.ethereum) {
137
+ else if (typeof window !== "undefined" && window.ethereum) {
137
138
  provider = window.ethereum;
138
139
  }
139
140
  if (provider) {
@@ -160,9 +161,9 @@ var FormoAnalytics = /** @class */ (function () {
160
161
  FormoAnalytics.prototype.isProviderInValidState = function (provider) {
161
162
  // Basic validation: ensure provider exists and has required methods
162
163
  return (provider &&
163
- typeof provider.request === 'function' &&
164
- typeof provider.on === 'function' &&
165
- typeof provider.removeListener === 'function');
164
+ typeof provider.request === "function" &&
165
+ typeof provider.on === "function" &&
166
+ typeof provider.removeListener === "function");
166
167
  };
167
168
  FormoAnalytics.init = function (writeKey, options) {
168
169
  return __awaiter(this, void 0, void 0, function () {
@@ -281,16 +282,18 @@ var FormoAnalytics = /** @class */ (function () {
281
282
  case 0:
282
283
  chainId = (params === null || params === void 0 ? void 0 : params.chainId) || this.currentChainId;
283
284
  address = (params === null || params === void 0 ? void 0 : params.address) || this.currentAddress;
284
- providerInfo = this._provider ? this.getProviderInfo(this._provider) : null;
285
+ providerInfo = this._provider
286
+ ? this.getProviderInfo(this._provider)
287
+ : null;
285
288
  logger.info("Disconnect: Emitting disconnect event with:", {
286
289
  chainId: chainId,
287
290
  address: address,
288
291
  providerName: providerInfo === null || providerInfo === void 0 ? void 0 : providerInfo.name,
289
- rdns: providerInfo === null || providerInfo === void 0 ? void 0 : providerInfo.rdns
292
+ rdns: providerInfo === null || providerInfo === void 0 ? void 0 : providerInfo.rdns,
290
293
  });
291
294
  disconnectProperties = __assign(__assign({}, (providerInfo && {
292
295
  providerName: providerInfo.name,
293
- rdns: providerInfo.rdns
296
+ rdns: providerInfo.rdns,
294
297
  })), properties);
295
298
  return [4 /*yield*/, this.trackEvent(EventType.DISCONNECT, __assign(__assign({}, (chainId && { chainId: chainId })), (address && { address: address })), disconnectProperties, context, callback)];
296
299
  case 1:
@@ -437,9 +440,12 @@ var FormoAnalytics = /** @class */ (function () {
437
440
  validAddress: validAddress_1,
438
441
  rdns: providerDetail.info.rdns,
439
442
  providerName: providerDetail.info.name,
440
- isAlreadyIdentified: validAddress_1 ? this.session.isWalletIdentified(validAddress_1, providerDetail.info.rdns) : false
443
+ isAlreadyIdentified: validAddress_1
444
+ ? this.session.isWalletIdentified(validAddress_1, providerDetail.info.rdns)
445
+ : false,
441
446
  });
442
- if (!(validAddress_1 && !this.session.isWalletIdentified(validAddress_1, providerDetail.info.rdns))) return [3 /*break*/, 5];
447
+ if (!(validAddress_1 &&
448
+ !this.session.isWalletIdentified(validAddress_1, providerDetail.info.rdns))) return [3 /*break*/, 5];
443
449
  logger.info("Auto-identifying", validAddress_1, providerDetail.info.name, providerDetail.info.rdns);
444
450
  // NOTE: do not set this.currentAddress without explicit connect or identify
445
451
  return [4 /*yield*/, this.identify({
@@ -483,23 +489,25 @@ var FormoAnalytics = /** @class */ (function () {
483
489
  this.currentUserId = userId;
484
490
  cookie().set(SESSION_USER_ID_KEY, userId);
485
491
  }
486
- isAlreadyIdentified = validAddress ? this.session.isWalletIdentified(validAddress, rdns || '') : false;
492
+ isAlreadyIdentified = validAddress
493
+ ? this.session.isWalletIdentified(validAddress, rdns || "")
494
+ : false;
487
495
  logger.debug("Identify: Checking deduplication", {
488
496
  validAddress: validAddress,
489
497
  rdns: rdns,
490
498
  providerName: providerName,
491
499
  hasValidAddress: !!validAddress,
492
500
  hasRdns: !!rdns,
493
- isAlreadyIdentified: isAlreadyIdentified
501
+ isAlreadyIdentified: isAlreadyIdentified,
494
502
  });
495
503
  if (isAlreadyIdentified) {
496
- logger.info("Identify: Wallet ".concat(providerName || 'Unknown', " with address ").concat(validAddress, " already identified in this session (rdns: ").concat(rdns || 'empty', ")"));
504
+ logger.info("Identify: Wallet ".concat(providerName || "Unknown", " with address ").concat(validAddress, " already identified in this session (rdns: ").concat(rdns || "empty", ")"));
497
505
  return [2 /*return*/];
498
506
  }
499
507
  // Mark as identified before emitting the event
500
508
  // Mark even if rdns is empty to prevent duplicate empty identifies
501
509
  if (validAddress) {
502
- this.session.markWalletIdentified(validAddress, rdns || '');
510
+ this.session.markWalletIdentified(validAddress, rdns || "");
503
511
  }
504
512
  return [4 /*yield*/, this.trackEvent(EventType.IDENTIFY, {
505
513
  address: validAddress,
@@ -613,12 +621,26 @@ var FormoAnalytics = /** @class */ (function () {
613
621
  logger.warn("TrackProvider: Provider already tracked.");
614
622
  return;
615
623
  }
616
- // Register listeners for this provider first
624
+ // CRITICAL: Always register accountsChanged for state management
625
+ // This ensures currentAddress, currentChainId, and _provider are always up-to-date
626
+ // Event emission is controlled conditionally inside the handlers
617
627
  this.registerAccountsChangedListener(provider);
618
- this.registerChainChangedListener(provider);
619
- this.registerConnectListener(provider);
620
- this.registerRequestListeners(provider);
621
- this.registerDisconnectListener(provider);
628
+ // Register other listeners based on autocapture configuration
629
+ if (this.isAutocaptureEnabled("chain")) {
630
+ this.registerChainChangedListener(provider);
631
+ }
632
+ if (this.isAutocaptureEnabled("connect")) {
633
+ this.registerConnectListener(provider);
634
+ }
635
+ if (this.isAutocaptureEnabled("signature") || this.isAutocaptureEnabled("transaction")) {
636
+ this.registerRequestListeners(provider);
637
+ }
638
+ else {
639
+ logger.debug("TrackProvider: Skipping request wrapping (both signature and transaction autocapture disabled)");
640
+ }
641
+ if (this.isAutocaptureEnabled("disconnect")) {
642
+ this.registerDisconnectListener(provider);
643
+ }
622
644
  // Only add to tracked providers after all listeners are successfully registered
623
645
  this._trackedProviders.add(provider);
624
646
  }
@@ -667,7 +689,7 @@ var FormoAnalytics = /** @class */ (function () {
667
689
  // Prevent concurrent processing of accountsChanged events to avoid race conditions
668
690
  if (this._processingAccountsChanged) {
669
691
  logger.debug("OnAccountsChanged: Already processing accountsChanged, skipping", {
670
- provider: this.getProviderInfo(provider).name
692
+ provider: this.getProviderInfo(provider).name,
671
693
  });
672
694
  return [2 /*return*/];
673
695
  }
@@ -703,20 +725,21 @@ var FormoAnalytics = /** @class */ (function () {
703
725
  return __generator(this, function (_a) {
704
726
  switch (_a.label) {
705
727
  case 0:
706
- if (!(accounts.length === 0)) return [3 /*break*/, 7];
707
- if (!(this._provider === provider)) return [3 /*break*/, 5];
728
+ if (!(accounts.length === 0)) return [3 /*break*/, 9];
729
+ if (!(this._provider === provider)) return [3 /*break*/, 7];
708
730
  logger.info("OnAccountsChanged: Detecting disconnect, current state:", {
709
731
  currentAddress: this.currentAddress,
710
732
  currentChainId: this.currentChainId,
711
- providerMatch: this._provider === provider
733
+ providerMatch: this._provider === provider,
712
734
  });
735
+ if (!this.isAutocaptureEnabled("disconnect")) return [3 /*break*/, 5];
713
736
  _a.label = 1;
714
737
  case 1:
715
738
  _a.trys.push([1, 3, , 4]);
716
739
  // Pass current state explicitly to ensure we have the data for the disconnect event
717
740
  return [4 /*yield*/, this.disconnect({
718
741
  chainId: this.currentChainId,
719
- address: this.currentAddress
742
+ address: this.currentAddress,
720
743
  })];
721
744
  case 2:
722
745
  // Pass current state explicitly to ensure we have the data for the disconnect event
@@ -728,103 +751,138 @@ var FormoAnalytics = /** @class */ (function () {
728
751
  return [3 /*break*/, 4];
729
752
  case 4: return [3 /*break*/, 6];
730
753
  case 5:
731
- logger.info("OnAccountsChanged: Ignoring disconnect for non-active provider");
754
+ logger.debug("OnAccountsChanged: Disconnect event skipped (autocapture.disconnect: false)");
755
+ // Still clear state even if not tracking the event
756
+ this.currentAddress = undefined;
757
+ this.currentChainId = undefined;
758
+ this.clearActiveProvider();
732
759
  _a.label = 6;
733
- case 6: return [2 /*return*/];
760
+ case 6: return [3 /*break*/, 8];
734
761
  case 7:
762
+ logger.info("OnAccountsChanged: Ignoring disconnect for non-active provider");
763
+ _a.label = 8;
764
+ case 8: return [2 /*return*/];
765
+ case 9:
735
766
  address = this.validateAndChecksumAddress(accounts[0]);
736
767
  if (!address) {
737
768
  logger.warn("onAccountsChanged: Invalid address received", accounts[0]);
738
769
  return [2 /*return*/];
739
770
  }
740
- if (!(this._provider && this._provider !== provider)) return [3 /*break*/, 18];
771
+ if (!(this._provider && this._provider !== provider)) return [3 /*break*/, 26];
741
772
  currentStoredAddress = this.currentAddress;
742
773
  newProviderAddress = this.validateAndChecksumAddress(address);
743
774
  logger.info("OnAccountsChanged: Different provider attempting to connect", {
744
775
  activeProvider: this.getProviderInfo(this._provider).name,
745
776
  eventProvider: this.getProviderInfo(provider).name,
746
777
  currentStoredAddress: currentStoredAddress,
747
- newProviderAddress: newProviderAddress
778
+ newProviderAddress: newProviderAddress,
748
779
  });
749
- _a.label = 8;
750
- case 8:
751
- _a.trys.push([8, 16, , 18]);
780
+ _a.label = 10;
781
+ case 10:
782
+ _a.trys.push([10, 22, , 26]);
752
783
  return [4 /*yield*/, this.getAccounts(this._provider)];
753
- case 9:
784
+ case 11:
754
785
  activeProviderAccounts = _a.sent();
755
786
  logger.info("OnAccountsChanged: Checking current provider accounts", {
756
787
  activeProvider: this.getProviderInfo(this._provider).name,
757
- accountsLength: activeProviderAccounts ? activeProviderAccounts.length : 0,
758
- accounts: activeProviderAccounts
788
+ accountsLength: activeProviderAccounts
789
+ ? activeProviderAccounts.length
790
+ : 0,
791
+ accounts: activeProviderAccounts,
759
792
  });
760
- if (!(activeProviderAccounts && activeProviderAccounts.length > 0)) return [3 /*break*/, 13];
761
- if (!(newProviderAddress && currentStoredAddress && newProviderAddress !== currentStoredAddress)) return [3 /*break*/, 11];
793
+ if (!(activeProviderAccounts && activeProviderAccounts.length > 0)) return [3 /*break*/, 17];
794
+ if (!(newProviderAddress &&
795
+ currentStoredAddress &&
796
+ newProviderAddress !== currentStoredAddress)) return [3 /*break*/, 15];
762
797
  logger.info("OnAccountsChanged: Different address detected, switching providers despite current provider having accounts", {
763
798
  activeProvider: this.getProviderInfo(this._provider).name,
764
799
  eventProvider: this.getProviderInfo(provider).name,
765
800
  currentAddress: currentStoredAddress,
766
801
  newAddress: newProviderAddress,
767
- reason: PROVIDER_SWITCH_REASONS.ADDRESS_MISMATCH
802
+ reason: PROVIDER_SWITCH_REASONS.ADDRESS_MISMATCH,
768
803
  });
769
- // Emit disconnect for the old provider
804
+ if (!this.isAutocaptureEnabled("disconnect")) return [3 /*break*/, 13];
770
805
  return [4 /*yield*/, this.disconnect({
771
806
  chainId: this.currentChainId,
772
- address: this.currentAddress
807
+ address: this.currentAddress,
773
808
  })];
774
- case 10:
775
- // Emit disconnect for the old provider
809
+ case 12:
776
810
  _a.sent();
811
+ return [3 /*break*/, 14];
812
+ case 13:
813
+ logger.debug("OnAccountsChanged: Disconnect event skipped during provider switch (autocapture.disconnect: false)");
814
+ // Still clear state even if not tracking the event
815
+ this.currentAddress = undefined;
816
+ this.currentChainId = undefined;
817
+ _a.label = 14;
818
+ case 14:
777
819
  // Clear state and let the new provider become active
778
820
  this.clearActiveProvider();
779
- return [3 /*break*/, 12];
780
- case 11:
821
+ return [3 /*break*/, 16];
822
+ case 15:
781
823
  logger.info("OnAccountsChanged: Current provider still has accounts and same address, ignoring new provider", {
782
824
  activeProvider: this.getProviderInfo(this._provider).name,
783
825
  eventProvider: this.getProviderInfo(provider).name,
784
826
  activeProviderAccountsCount: activeProviderAccounts.length,
785
827
  currentAddress: currentStoredAddress,
786
- newAddress: newProviderAddress
828
+ newAddress: newProviderAddress,
787
829
  });
788
830
  return [2 /*return*/];
789
- case 12: return [3 /*break*/, 15];
790
- case 13:
831
+ case 16: return [3 /*break*/, 21];
832
+ case 17:
791
833
  logger.info("OnAccountsChanged: Current provider has no accounts, switching to new provider", {
792
834
  oldProvider: this.getProviderInfo(this._provider).name,
793
835
  newProvider: this.getProviderInfo(provider).name,
794
- reason: PROVIDER_SWITCH_REASONS.NO_ACCOUNTS
836
+ reason: PROVIDER_SWITCH_REASONS.NO_ACCOUNTS,
795
837
  });
796
- // Emit disconnect for the old provider that didn't signal properly
838
+ if (!this.isAutocaptureEnabled("disconnect")) return [3 /*break*/, 19];
797
839
  return [4 /*yield*/, this.disconnect({
798
840
  chainId: this.currentChainId,
799
- address: this.currentAddress
841
+ address: this.currentAddress,
800
842
  })];
801
- case 14:
802
- // Emit disconnect for the old provider that didn't signal properly
843
+ case 18:
803
844
  _a.sent();
845
+ return [3 /*break*/, 20];
846
+ case 19:
847
+ logger.debug("OnAccountsChanged: Disconnect event skipped for old provider (autocapture.disconnect: false)");
848
+ // Still clear state even if not tracking the event
849
+ this.currentAddress = undefined;
850
+ this.currentChainId = undefined;
851
+ _a.label = 20;
852
+ case 20:
804
853
  // Clear state and let the new provider become active
805
854
  this.clearActiveProvider();
806
- _a.label = 15;
807
- case 15: return [3 /*break*/, 18];
808
- case 16:
855
+ _a.label = 21;
856
+ case 21: return [3 /*break*/, 26];
857
+ case 22:
809
858
  error_2 = _a.sent();
810
859
  logger.warn("OnAccountsChanged: Could not check current provider accounts, switching to new provider", {
811
860
  error: error_2 instanceof Error ? error_2.message : String(error_2),
812
861
  errorType: error_2 instanceof Error ? error_2.constructor.name : typeof error_2,
813
- oldProvider: this._provider ? this.getProviderInfo(this._provider).name : 'unknown',
862
+ oldProvider: this._provider
863
+ ? this.getProviderInfo(this._provider).name
864
+ : "unknown",
814
865
  newProvider: this.getProviderInfo(provider).name,
815
- reason: PROVIDER_SWITCH_REASONS.CHECK_FAILED
866
+ reason: PROVIDER_SWITCH_REASONS.CHECK_FAILED,
816
867
  });
817
- // If we can't check the current provider, assume it's disconnected
868
+ if (!this.isAutocaptureEnabled("disconnect")) return [3 /*break*/, 24];
818
869
  return [4 /*yield*/, this.disconnect({
819
870
  chainId: this.currentChainId,
820
- address: this.currentAddress
871
+ address: this.currentAddress,
821
872
  })];
822
- case 17:
823
- // If we can't check the current provider, assume it's disconnected
873
+ case 23:
824
874
  _a.sent();
875
+ return [3 /*break*/, 25];
876
+ case 24:
877
+ logger.debug("OnAccountsChanged: Disconnect event skipped for failed provider check (autocapture.disconnect: false)");
878
+ // Still clear state even if not tracking the event
879
+ this.currentAddress = undefined;
880
+ this.currentChainId = undefined;
881
+ _a.label = 25;
882
+ case 25:
825
883
  this.clearActiveProvider();
826
- return [3 /*break*/, 18];
827
- case 18:
884
+ return [3 /*break*/, 26];
885
+ case 26:
828
886
  // Set provider if none exists (first connection)
829
887
  if (!this._provider) {
830
888
  this._provider = provider;
@@ -834,33 +892,44 @@ var FormoAnalytics = /** @class */ (function () {
834
892
  return [2 /*return*/];
835
893
  }
836
894
  return [4 /*yield*/, this.getCurrentChainId(provider)];
837
- case 19:
895
+ case 27:
838
896
  nextChainId = _a.sent();
839
897
  wasDisconnected = !this.currentAddress;
898
+ // CRITICAL: Always update state regardless of whether connect tracking is enabled
899
+ // This ensures disconnect events will have valid address/chainId values
840
900
  this.currentAddress = address;
841
901
  this.currentChainId = nextChainId;
842
902
  providerInfo = this.getProviderInfo(provider);
843
- logger.info("OnAccountsChanged: Detected wallet connection, emitting connect event", {
844
- chainId: nextChainId,
845
- address: address,
846
- wasDisconnected: wasDisconnected,
847
- providerName: providerInfo.name,
848
- rdns: providerInfo.rdns,
849
- hasChainId: !!nextChainId
850
- });
851
903
  effectiveChainId = nextChainId || 0;
852
- if (effectiveChainId === 0) {
853
- logger.info("OnAccountsChanged: Using fallback chainId 0 for connect event");
904
+ if (this.isAutocaptureEnabled("connect")) {
905
+ logger.info("OnAccountsChanged: Detected wallet connection, emitting connect event", {
906
+ chainId: nextChainId,
907
+ address: address,
908
+ wasDisconnected: wasDisconnected,
909
+ providerName: providerInfo.name,
910
+ rdns: providerInfo.rdns,
911
+ hasChainId: !!nextChainId,
912
+ });
913
+ if (effectiveChainId === 0) {
914
+ logger.info("OnAccountsChanged: Using fallback chainId 0 for connect event");
915
+ }
916
+ this.connect({
917
+ chainId: effectiveChainId,
918
+ address: address,
919
+ }, {
920
+ providerName: providerInfo.name,
921
+ rdns: providerInfo.rdns,
922
+ }).catch(function (error) {
923
+ logger.error("Failed to track connect event during account change:", error);
924
+ });
925
+ }
926
+ else {
927
+ logger.debug("OnAccountsChanged: Connect event skipped (autocapture.connect: false)", {
928
+ chainId: nextChainId,
929
+ address: address,
930
+ providerName: providerInfo.name,
931
+ });
854
932
  }
855
- this.connect({
856
- chainId: effectiveChainId,
857
- address: address
858
- }, {
859
- providerName: providerInfo.name,
860
- rdns: providerInfo.rdns
861
- }).catch(function (error) {
862
- logger.error("Failed to track connect event during account change:", error);
863
- });
864
933
  return [2 /*return*/];
865
934
  }
866
935
  });
@@ -901,10 +970,18 @@ var FormoAnalytics = /** @class */ (function () {
901
970
  this.currentChainId = nextChainId;
902
971
  try {
903
972
  // This is just a chain change since we already confirmed currentAddress exists
904
- return [2 /*return*/, this.chain({
973
+ if (this.isAutocaptureEnabled("chain")) {
974
+ return [2 /*return*/, this.chain({
975
+ chainId: this.currentChainId,
976
+ address: this.currentAddress,
977
+ })];
978
+ }
979
+ else {
980
+ logger.debug("OnChainChanged: Chain event skipped (autocapture.chain: false)", {
905
981
  chainId: this.currentChainId,
906
982
  address: this.currentAddress,
907
- })];
983
+ });
984
+ }
908
985
  }
909
986
  catch (error) {
910
987
  logger.error("OnChainChanged: Failed to emit chain event:", error);
@@ -939,15 +1016,16 @@ var FormoAnalytics = /** @class */ (function () {
939
1016
  return [2 /*return*/];
940
1017
  logger.info("OnDisconnect: Wallet disconnect event received, current state:", {
941
1018
  currentAddress: this.currentAddress,
942
- currentChainId: this.currentChainId
1019
+ currentChainId: this.currentChainId,
943
1020
  });
1021
+ if (!this.isAutocaptureEnabled("disconnect")) return [3 /*break*/, 5];
944
1022
  _a.label = 1;
945
1023
  case 1:
946
1024
  _a.trys.push([1, 3, , 4]);
947
1025
  // Pass current state explicitly to ensure we have the data for the disconnect event
948
1026
  return [4 /*yield*/, this.disconnect({
949
1027
  chainId: this.currentChainId,
950
- address: this.currentAddress
1028
+ address: this.currentAddress,
951
1029
  })];
952
1030
  case 2:
953
1031
  // Pass current state explicitly to ensure we have the data for the disconnect event
@@ -957,7 +1035,15 @@ var FormoAnalytics = /** @class */ (function () {
957
1035
  e_2 = _a.sent();
958
1036
  logger.error("Error during disconnect in disconnect listener", e_2);
959
1037
  return [3 /*break*/, 4];
960
- case 4: return [2 /*return*/];
1038
+ case 4: return [3 /*break*/, 6];
1039
+ case 5:
1040
+ logger.debug("OnDisconnect: Disconnect event skipped (autocapture.disconnect: false)");
1041
+ // Still clear state even if not tracking the event
1042
+ this.currentAddress = undefined;
1043
+ this.currentChainId = undefined;
1044
+ this.clearActiveProvider();
1045
+ _a.label = 6;
1046
+ case 6: return [2 /*return*/];
961
1047
  }
962
1048
  });
963
1049
  }); };
@@ -974,7 +1060,7 @@ var FormoAnalytics = /** @class */ (function () {
974
1060
  _a.label = 1;
975
1061
  case 1:
976
1062
  _a.trys.push([1, 3, , 4]);
977
- if (!(connection === null || connection === void 0 ? void 0 : connection.chainId) || typeof connection.chainId !== 'string')
1063
+ if (!(connection === null || connection === void 0 ? void 0 : connection.chainId) || typeof connection.chainId !== "string")
978
1064
  return [2 /*return*/];
979
1065
  chainId = parseChainId(connection.chainId);
980
1066
  return [4 /*yield*/, this.getAddress(provider)];
@@ -987,34 +1073,46 @@ var FormoAnalytics = /** @class */ (function () {
987
1073
  this._provider = provider;
988
1074
  }
989
1075
  isActiveProvider = this._provider === provider;
990
- // Only update global state (chainId/address) from the active provider
1076
+ // CRITICAL: Always update state from active provider regardless of tracking config
1077
+ // This ensures disconnect events will have valid address/chainId values
991
1078
  if (isActiveProvider) {
992
1079
  this.currentChainId = chainId;
993
- this.currentAddress = this.validateAndChecksumAddress(address) || undefined;
1080
+ this.currentAddress =
1081
+ this.validateAndChecksumAddress(address) || undefined;
994
1082
  }
1083
+ // Conditionally emit connect event based on tracking configuration
995
1084
  if (isActiveProvider && this.currentAddress) {
996
1085
  providerInfo = this.getProviderInfo(provider);
997
- logger.info("OnConnected: Detected wallet connection, emitting connect event", {
998
- chainId: chainId,
999
- wasDisconnected: wasDisconnected,
1000
- providerName: providerInfo.name,
1001
- rdns: providerInfo.rdns,
1002
- hasChainId: !!chainId,
1003
- isActiveProvider: isActiveProvider
1004
- });
1005
1086
  effectiveChainId = chainId || 0;
1006
- if (effectiveChainId === 0) {
1007
- logger.info("OnConnected: Using fallback chainId 0 for connect event");
1087
+ if (this.isAutocaptureEnabled("connect")) {
1088
+ logger.info("OnConnected: Detected wallet connection, emitting connect event", {
1089
+ chainId: chainId,
1090
+ wasDisconnected: wasDisconnected,
1091
+ providerName: providerInfo.name,
1092
+ rdns: providerInfo.rdns,
1093
+ hasChainId: !!chainId,
1094
+ isActiveProvider: isActiveProvider,
1095
+ });
1096
+ if (effectiveChainId === 0) {
1097
+ logger.info("OnConnected: Using fallback chainId 0 for connect event");
1098
+ }
1099
+ this.connect({
1100
+ chainId: effectiveChainId,
1101
+ address: address,
1102
+ }, {
1103
+ providerName: providerInfo.name,
1104
+ rdns: providerInfo.rdns,
1105
+ }).catch(function (error) {
1106
+ logger.error("Failed to track connect event during provider connection:", error);
1107
+ });
1108
+ }
1109
+ else {
1110
+ logger.debug("OnConnected: Connect event skipped (autocapture.connect: false)", {
1111
+ chainId: chainId,
1112
+ address: address,
1113
+ providerName: providerInfo.name,
1114
+ });
1008
1115
  }
1009
- this.connect({
1010
- chainId: effectiveChainId,
1011
- address: address
1012
- }, {
1013
- providerName: providerInfo.name,
1014
- rdns: providerInfo.rdns
1015
- }).catch(function (error) {
1016
- logger.error("Failed to track connect event during provider connection:", error);
1017
- });
1018
1116
  }
1019
1117
  else if (address && !isActiveProvider) {
1020
1118
  providerInfo = this.getProviderInfo(provider);
@@ -1023,7 +1121,9 @@ var FormoAnalytics = /** @class */ (function () {
1023
1121
  providerName: providerInfo.name,
1024
1122
  rdns: providerInfo.rdns,
1025
1123
  isActiveProvider: isActiveProvider,
1026
- activeProviderInfo: this._provider ? this.getProviderInfo(this._provider) : null
1124
+ activeProviderInfo: this._provider
1125
+ ? this.getProviderInfo(this._provider)
1126
+ : null,
1027
1127
  });
1028
1128
  }
1029
1129
  }
@@ -1060,6 +1160,10 @@ var FormoAnalytics = /** @class */ (function () {
1060
1160
  case 0:
1061
1161
  if (!(Array.isArray(params) &&
1062
1162
  ["eth_signTypedData_v4", "personal_sign"].includes(method))) return [3 /*break*/, 6];
1163
+ if (!this.isAutocaptureEnabled("signature")) {
1164
+ logger.debug("Signature event skipped (autocapture.signature: false)", { method: method });
1165
+ return [2 /*return*/, request({ method: method, params: params })];
1166
+ }
1063
1167
  _c = this.currentChainId;
1064
1168
  if (_c) return [3 /*break*/, 2];
1065
1169
  return [4 /*yield*/, this.getCurrentChainId(provider)];
@@ -1123,6 +1227,10 @@ var FormoAnalytics = /** @class */ (function () {
1123
1227
  if (!(Array.isArray(params) &&
1124
1228
  method === "eth_sendTransaction" &&
1125
1229
  params[0])) return [3 /*break*/, 10];
1230
+ if (!this.isAutocaptureEnabled("transaction")) {
1231
+ logger.debug("Transaction event skipped (autocapture.transaction: false)", { method: method });
1232
+ return [2 /*return*/, request({ method: method, params: params })];
1233
+ }
1126
1234
  (function () { return __awaiter(_this, void 0, void 0, function () {
1127
1235
  var payload, e_4;
1128
1236
  return __generator(this, function (_a) {
@@ -1205,7 +1313,8 @@ var FormoAnalytics = /** @class */ (function () {
1205
1313
  }); };
1206
1314
  // Mark the wrapper so we can detect if request is replaced externally and keep a reference on provider
1207
1315
  wrappedRequest[WRAPPED_REQUEST_SYMBOL] = true;
1208
- provider[WRAPPED_REQUEST_REF_SYMBOL] = wrappedRequest;
1316
+ provider[WRAPPED_REQUEST_REF_SYMBOL] =
1317
+ wrappedRequest;
1209
1318
  try {
1210
1319
  // Attempt to assign the wrapped request function (rely on try-catch for mutability errors)
1211
1320
  provider.request = wrappedRequest;
@@ -1295,18 +1404,25 @@ var FormoAnalytics = /** @class */ (function () {
1295
1404
  };
1296
1405
  FormoAnalytics.prototype.trackEvent = function (type, payload, properties, context, callback) {
1297
1406
  return __awaiter(this, void 0, void 0, function () {
1407
+ var error_5;
1298
1408
  return __generator(this, function (_a) {
1299
- try {
1300
- if (!this.shouldTrack()) {
1301
- logger.info("Skipping ".concat(type, " event due to tracking configuration"));
1302
- return [2 /*return*/];
1303
- }
1304
- this.eventManager.addEvent(__assign(__assign({ type: type }, payload), { properties: properties, context: context, callback: callback }), this.currentAddress, this.currentUserId);
1305
- }
1306
- catch (error) {
1307
- logger.error("Error tracking event:", error);
1409
+ switch (_a.label) {
1410
+ case 0:
1411
+ _a.trys.push([0, 2, , 3]);
1412
+ if (!this.shouldTrack()) {
1413
+ logger.info("Skipping ".concat(type, " event due to tracking configuration"));
1414
+ return [2 /*return*/];
1415
+ }
1416
+ return [4 /*yield*/, this.eventManager.addEvent(__assign(__assign({ type: type }, payload), { properties: properties, context: context, callback: callback }), this.currentAddress, this.currentUserId)];
1417
+ case 1:
1418
+ _a.sent();
1419
+ return [3 /*break*/, 3];
1420
+ case 2:
1421
+ error_5 = _a.sent();
1422
+ logger.error("Error tracking event:", error_5);
1423
+ return [3 /*break*/, 3];
1424
+ case 3: return [2 /*return*/];
1308
1425
  }
1309
- return [2 /*return*/];
1310
1426
  });
1311
1427
  });
1312
1428
  };
@@ -1320,23 +1436,23 @@ var FormoAnalytics = /** @class */ (function () {
1320
1436
  return false;
1321
1437
  }
1322
1438
  // Check if tracking is explicitly provided as a boolean
1323
- if (typeof this.options.tracking === 'boolean') {
1439
+ if (typeof this.options.tracking === "boolean") {
1324
1440
  return this.options.tracking;
1325
1441
  }
1326
1442
  // Handle object configuration with exclusion rules
1327
1443
  if (this.options.tracking !== null &&
1328
- typeof this.options.tracking === 'object' &&
1444
+ typeof this.options.tracking === "object" &&
1329
1445
  !Array.isArray(this.options.tracking)) {
1330
1446
  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;
1331
1447
  // Check hostname exclusions - use exact matching
1332
- if (excludeHosts.length > 0 && typeof window !== 'undefined') {
1448
+ if (excludeHosts.length > 0 && typeof window !== "undefined") {
1333
1449
  var hostname = window.location.hostname;
1334
1450
  if (excludeHosts.includes(hostname)) {
1335
1451
  return false;
1336
1452
  }
1337
1453
  }
1338
1454
  // Check path exclusions - use exact matching
1339
- if (excludePaths.length > 0 && typeof window !== 'undefined') {
1455
+ if (excludePaths.length > 0 && typeof window !== "undefined") {
1340
1456
  var pathname = window.location.pathname;
1341
1457
  if (excludePaths.includes(pathname)) {
1342
1458
  return false;
@@ -1354,6 +1470,30 @@ var FormoAnalytics = /** @class */ (function () {
1354
1470
  // Default behavior: track everywhere except localhost
1355
1471
  return !isLocalhost();
1356
1472
  };
1473
+ /**
1474
+ * Check if a specific wallet event type is enabled for autocapture
1475
+ * @param eventType The wallet event type to check
1476
+ * @returns {boolean} True if the event type should be autocaptured
1477
+ */
1478
+ FormoAnalytics.prototype.isAutocaptureEnabled = function (eventType) {
1479
+ // If no configuration provided, default to enabled
1480
+ if (this.options.autocapture === undefined) {
1481
+ return true;
1482
+ }
1483
+ // If boolean, return that value for all events
1484
+ if (typeof this.options.autocapture === "boolean") {
1485
+ return this.options.autocapture;
1486
+ }
1487
+ // If it's an object, check the specific event configuration
1488
+ if (this.options.autocapture !== null &&
1489
+ typeof this.options.autocapture === "object") {
1490
+ var eventConfig = this.options.autocapture[eventType];
1491
+ // Default to true if not explicitly set to false
1492
+ return eventConfig !== false;
1493
+ }
1494
+ // Default to enabled if no specific configuration
1495
+ return true;
1496
+ };
1357
1497
  /*
1358
1498
  Utility functions
1359
1499
  */
@@ -1368,14 +1508,14 @@ var FormoAnalytics = /** @class */ (function () {
1368
1508
  if (eip6963Provider) {
1369
1509
  return {
1370
1510
  name: eip6963Provider.info.name,
1371
- rdns: eip6963Provider.info.rdns
1511
+ rdns: eip6963Provider.info.rdns,
1372
1512
  };
1373
1513
  }
1374
1514
  // Fallback to injected provider detection
1375
1515
  var injectedInfo = this.detectInjectedProviderInfo(provider);
1376
1516
  return {
1377
1517
  name: injectedInfo.name,
1378
- rdns: injectedInfo.rdns
1518
+ rdns: injectedInfo.rdns,
1379
1519
  };
1380
1520
  };
1381
1521
  /**
@@ -1385,45 +1525,45 @@ var FormoAnalytics = /** @class */ (function () {
1385
1525
  */
1386
1526
  FormoAnalytics.prototype.detectInjectedProviderInfo = function (provider) {
1387
1527
  // Try to detect provider type from common properties
1388
- var name = 'Injected Provider';
1389
- var rdns = 'io.injected.provider';
1528
+ var name = "Injected Provider";
1529
+ var rdns = "io.injected.provider";
1390
1530
  // Use WalletProviderFlags interface for type safety
1391
1531
  var flags = provider;
1392
1532
  // Check if it's MetaMask
1393
1533
  if (flags.isMetaMask) {
1394
- name = 'MetaMask';
1395
- rdns = 'io.metamask';
1534
+ name = "MetaMask";
1535
+ rdns = "io.metamask";
1396
1536
  }
1397
1537
  // Check if it's Coinbase Wallet
1398
1538
  else if (flags.isCoinbaseWallet) {
1399
- name = 'Coinbase Wallet';
1400
- rdns = 'com.coinbase.wallet';
1539
+ name = "Coinbase Wallet";
1540
+ rdns = "com.coinbase.wallet";
1401
1541
  }
1402
1542
  // Check if it's WalletConnect
1403
1543
  else if (flags.isWalletConnect) {
1404
- name = 'WalletConnect';
1405
- rdns = 'com.walletconnect';
1544
+ name = "WalletConnect";
1545
+ rdns = "com.walletconnect";
1406
1546
  }
1407
1547
  // Check if it's Trust Wallet
1408
1548
  else if (flags.isTrust) {
1409
- name = 'Trust Wallet';
1410
- rdns = 'com.trustwallet';
1549
+ name = "Trust Wallet";
1550
+ rdns = "com.trustwallet";
1411
1551
  }
1412
1552
  // Check if it's Brave Wallet
1413
1553
  else if (flags.isBraveWallet) {
1414
- name = 'Brave Wallet';
1415
- rdns = 'com.brave.wallet';
1554
+ name = "Brave Wallet";
1555
+ rdns = "com.brave.wallet";
1416
1556
  }
1417
1557
  // Check if it's Phantom
1418
1558
  else if (flags.isPhantom) {
1419
- name = 'Phantom';
1420
- rdns = 'app.phantom';
1559
+ name = "Phantom";
1560
+ rdns = "app.phantom";
1421
1561
  }
1422
1562
  return {
1423
1563
  name: name,
1424
1564
  rdns: rdns,
1425
- uuid: "injected-".concat(rdns.replace(/[^a-zA-Z0-9]/g, '-')),
1426
- icon: DEFAULT_PROVIDER_ICON
1565
+ uuid: "injected-".concat(rdns.replace(/[^a-zA-Z0-9]/g, "-")),
1566
+ icon: DEFAULT_PROVIDER_ICON,
1427
1567
  };
1428
1568
  };
1429
1569
  FormoAnalytics.prototype.getProviders = function () {
@@ -1477,7 +1617,7 @@ var FormoAnalytics = /** @class */ (function () {
1477
1617
  });
1478
1618
  // Fallback to injected provider if no providers are found
1479
1619
  if (providers.length === 0) {
1480
- injected_1 = typeof window !== 'undefined' ? window.ethereum : undefined;
1620
+ injected_1 = typeof window !== "undefined" ? window.ethereum : undefined;
1481
1621
  if (injected_1) {
1482
1622
  // If we have already detected and cached the injected provider, and it's the same instance, return the cached result
1483
1623
  if (this._injectedProviderDetail &&
@@ -1488,7 +1628,9 @@ var FormoAnalytics = /** @class */ (function () {
1488
1628
  }
1489
1629
  // Merge with existing providers instead of overwriting
1490
1630
  if (!this._providers.some(function (existing) { return existing.provider === injected_1; })) {
1491
- this._providers = __spreadArray(__spreadArray([], this._providers, true), [this._injectedProviderDetail], false);
1631
+ this._providers = __spreadArray(__spreadArray([], this._providers, true), [
1632
+ this._injectedProviderDetail,
1633
+ ], false);
1492
1634
  }
1493
1635
  return [2 /*return*/, this._providers];
1494
1636
  }
@@ -1499,7 +1641,7 @@ var FormoAnalytics = /** @class */ (function () {
1499
1641
  injectedProviderInfo = this.detectInjectedProviderInfo(injected_1);
1500
1642
  injectedDetail = {
1501
1643
  provider: injected_1,
1502
- info: injectedProviderInfo
1644
+ info: injectedProviderInfo,
1503
1645
  };
1504
1646
  // Cache the detected injected provider detail
1505
1647
  this._injectedProviderDetail = injectedDetail;
@@ -1838,9 +1980,10 @@ var FormoAnalytics = /** @class */ (function () {
1838
1980
  */
1839
1981
  FormoAnalytics.prototype.isProviderAlreadyWrapped = function (provider, currentRequest) {
1840
1982
  return !!(currentRequest &&
1841
- typeof currentRequest === 'function' &&
1983
+ typeof currentRequest === "function" &&
1842
1984
  currentRequest[WRAPPED_REQUEST_SYMBOL] &&
1843
- provider[WRAPPED_REQUEST_REF_SYMBOL] === currentRequest);
1985
+ provider[WRAPPED_REQUEST_REF_SYMBOL] ===
1986
+ currentRequest);
1844
1987
  };
1845
1988
  /**
1846
1989
  * Handle provider mismatch by switching to the new provider and invalidating old tokens
@@ -1929,7 +2072,7 @@ var FormoAnalyticsSession = /** @class */ (function () {
1929
2072
  logger.debug("Session: Checking wallet identification", {
1930
2073
  identifiedKey: identifiedKey,
1931
2074
  isIdentified: isIdentified,
1932
- hasRdns: !!rdns
2075
+ hasRdns: !!rdns,
1933
2076
  });
1934
2077
  return isIdentified;
1935
2078
  };
@@ -1947,14 +2090,14 @@ var FormoAnalyticsSession = /** @class */ (function () {
1947
2090
  });
1948
2091
  logger.debug("Session: Marked wallet as identified", {
1949
2092
  identifiedKey: identifiedKey,
1950
- hasRdns: !!rdns
2093
+ hasRdns: !!rdns,
1951
2094
  });
1952
2095
  }
1953
2096
  else {
1954
2097
  logger.info("Session: Wallet already marked as identified", {
1955
2098
  identifiedKey: identifiedKey,
1956
2099
  existingWallets: identifiedWallets,
1957
- hasRdns: !!rdns
2100
+ hasRdns: !!rdns,
1958
2101
  });
1959
2102
  }
1960
2103
  };