@formo/analytics 1.28.5 → 1.29.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 (58) hide show
  1. package/dist/cjs/src/FormoAnalytics.d.ts +9 -3
  2. package/dist/cjs/src/FormoAnalytics.js +29 -16
  3. package/dist/cjs/src/constants/base.d.ts +0 -1
  4. package/dist/cjs/src/constants/base.js +1 -2
  5. package/dist/cjs/src/event/EventFactory.d.ts +1 -0
  6. package/dist/cjs/src/event/EventFactory.js +21 -14
  7. package/dist/cjs/src/event/constants.d.ts +8 -2
  8. package/dist/cjs/src/event/constants.js +31 -5
  9. package/dist/cjs/src/index.d.ts +3 -1
  10. package/dist/cjs/src/index.js +5 -1
  11. package/dist/cjs/src/solana/SolanaManager.d.ts +36 -11
  12. package/dist/cjs/src/solana/SolanaManager.js +47 -49
  13. package/dist/cjs/src/solana/SolanaStoreHandler.d.ts +88 -0
  14. package/dist/cjs/src/solana/SolanaStoreHandler.js +471 -0
  15. package/dist/cjs/src/solana/index.d.ts +8 -4
  16. package/dist/cjs/src/solana/index.js +10 -6
  17. package/dist/cjs/src/solana/storeTypes.d.ts +107 -0
  18. package/dist/cjs/src/solana/storeTypes.js +12 -0
  19. package/dist/cjs/src/solana/types.d.ts +23 -154
  20. package/dist/cjs/src/solana/types.js +4 -37
  21. package/dist/cjs/src/storage/StorageManager.d.ts +1 -0
  22. package/dist/cjs/src/storage/StorageManager.js +10 -2
  23. package/dist/cjs/src/types/base.d.ts +16 -5
  24. package/dist/cjs/src/types/events.d.ts +5 -1
  25. package/dist/cjs/src/version.d.ts +1 -1
  26. package/dist/cjs/src/version.js +1 -1
  27. package/dist/esm/src/FormoAnalytics.d.ts +9 -3
  28. package/dist/esm/src/FormoAnalytics.js +30 -17
  29. package/dist/esm/src/constants/base.d.ts +0 -1
  30. package/dist/esm/src/constants/base.js +0 -1
  31. package/dist/esm/src/event/EventFactory.d.ts +1 -0
  32. package/dist/esm/src/event/EventFactory.js +22 -15
  33. package/dist/esm/src/event/constants.d.ts +8 -2
  34. package/dist/esm/src/event/constants.js +30 -5
  35. package/dist/esm/src/index.d.ts +3 -1
  36. package/dist/esm/src/index.js +1 -0
  37. package/dist/esm/src/solana/SolanaManager.d.ts +36 -11
  38. package/dist/esm/src/solana/SolanaManager.js +47 -49
  39. package/dist/esm/src/solana/SolanaStoreHandler.d.ts +88 -0
  40. package/dist/esm/src/solana/SolanaStoreHandler.js +468 -0
  41. package/dist/esm/src/solana/index.d.ts +8 -4
  42. package/dist/esm/src/solana/index.js +8 -4
  43. package/dist/esm/src/solana/storeTypes.d.ts +107 -0
  44. package/dist/esm/src/solana/storeTypes.js +11 -0
  45. package/dist/esm/src/solana/types.d.ts +23 -154
  46. package/dist/esm/src/solana/types.js +3 -34
  47. package/dist/esm/src/storage/StorageManager.d.ts +1 -0
  48. package/dist/esm/src/storage/StorageManager.js +10 -2
  49. package/dist/esm/src/types/base.d.ts +16 -5
  50. package/dist/esm/src/types/events.d.ts +5 -1
  51. package/dist/esm/src/version.d.ts +1 -1
  52. package/dist/esm/src/version.js +1 -1
  53. package/dist/index.umd.min.js +1 -1
  54. package/package.json +14 -14
  55. package/dist/cjs/src/solana/SolanaAdapter.d.ts +0 -210
  56. package/dist/cjs/src/solana/SolanaAdapter.js +0 -988
  57. package/dist/esm/src/solana/SolanaAdapter.d.ts +0 -210
  58. package/dist/esm/src/solana/SolanaAdapter.js +0 -985
@@ -45,8 +45,15 @@ export declare class FormoAnalytics implements IFormoAnalytics {
45
45
  * When true, EIP-1193 provider wrapping is skipped
46
46
  */
47
47
  private isWagmiMode;
48
+ /**
49
+ * Flag indicating if EVM provider tracking is disabled.
50
+ * When true, all EIP-1193/EIP-6963 detection and wrapping is skipped.
51
+ */
52
+ private isEvmDisabled;
48
53
  /** Instance-level flag so multiple SDK instances don't interfere. */
49
54
  private crossSubdomainCookies;
55
+ /** In-memory URL used to deduplicate SPA pageview events. */
56
+ private _currentUrl;
50
57
  config: Config;
51
58
  currentChainId?: ChainID;
52
59
  currentAddress?: Address;
@@ -294,10 +301,9 @@ export declare class FormoAnalytics implements IFormoAnalytics {
294
301
  *
295
302
  * @example
296
303
  * ```tsx
297
- * formo.solana.setWallet(wallet);
298
- * formo.solana.setConnection(connection);
304
+ * formo.solana.setStore(client.store);
299
305
  * formo.solana.setCluster("devnet");
300
- * formo.solana.syncWalletState();
306
+ * // For signatures, use formo.signature() directly
301
307
  * ```
302
308
  */
303
309
  get solana(): SolanaManager;
@@ -117,6 +117,13 @@ var FormoAnalytics = /** @class */ (function () {
117
117
  * When true, EIP-1193 provider wrapping is skipped
118
118
  */
119
119
  this.isWagmiMode = false;
120
+ /**
121
+ * Flag indicating if EVM provider tracking is disabled.
122
+ * When true, all EIP-1193/EIP-6963 detection and wrapping is skipped.
123
+ */
124
+ this.isEvmDisabled = false;
125
+ /** In-memory URL used to deduplicate SPA pageview events. */
126
+ this._currentUrl = "";
120
127
  this.currentUserId = "";
121
128
  this.config = {
122
129
  writeKey: writeKey,
@@ -124,6 +131,7 @@ var FormoAnalytics = /** @class */ (function () {
124
131
  this.options = options;
125
132
  // Check if Wagmi mode is enabled
126
133
  this.isWagmiMode = !!options.wagmi;
134
+ this.isEvmDisabled = options.evm === false;
127
135
  this.crossSubdomainCookies = (_a = options.crossSubdomainCookies) !== null && _a !== void 0 ? _a : true;
128
136
  // Normalize so downstream consumers (EventFactory) read the resolved value.
129
137
  options.crossSubdomainCookies = this.crossSubdomainCookies;
@@ -156,8 +164,11 @@ var FormoAnalytics = /** @class */ (function () {
156
164
  if (this.hasOptedOutTracking()) {
157
165
  logger_1.logger.info("User has previously opted out of tracking");
158
166
  }
159
- // Initialize Wagmi handler if Wagmi mode is enabled
160
- if (this.isWagmiMode && options.wagmi) {
167
+ // Initialize EVM provider tracking (unless explicitly disabled)
168
+ if (this.isEvmDisabled) {
169
+ logger_1.logger.info("FormoAnalytics: EVM provider tracking disabled");
170
+ }
171
+ else if (this.isWagmiMode && options.wagmi) {
161
172
  logger_1.logger.info("FormoAnalytics: Initializing in Wagmi mode");
162
173
  this.wagmiHandler = new wagmi_1.WagmiEventHandler(this, options.wagmi.config, options.wagmi.queryClient);
163
174
  }
@@ -179,6 +190,7 @@ var FormoAnalytics = /** @class */ (function () {
179
190
  if (options.solana) {
180
191
  this.solanaManager = new SolanaManager_1.SolanaManager(this, options.solana);
181
192
  }
193
+ this._currentUrl = window.location.href;
182
194
  this.trackPageHit();
183
195
  this.trackPageHits();
184
196
  }
@@ -226,22 +238,26 @@ var FormoAnalytics = /** @class */ (function () {
226
238
  case 0:
227
239
  (0, storage_1.initStorageManager)(writeKey);
228
240
  analytics = new FormoAnalytics(writeKey, options);
229
- if (!!analytics.isWagmiMode) return [3 /*break*/, 3];
241
+ if (!analytics.isEvmDisabled) return [3 /*break*/, 1];
242
+ logger_1.logger.info("FormoAnalytics: Skipping provider detection (EVM disabled)");
243
+ return [3 /*break*/, 5];
244
+ case 1:
245
+ if (!!analytics.isWagmiMode) return [3 /*break*/, 4];
230
246
  // Auto-detect wallet provider
231
247
  _a = analytics;
232
248
  return [4 /*yield*/, analytics.getProviders()];
233
- case 1:
249
+ case 2:
234
250
  // Auto-detect wallet provider
235
251
  _a._providers = _b.sent();
236
252
  return [4 /*yield*/, analytics.detectWallets(analytics._providers)];
237
- case 2:
253
+ case 3:
238
254
  _b.sent();
239
255
  analytics.trackProviders(analytics._providers);
240
- return [3 /*break*/, 4];
241
- case 3:
256
+ return [3 /*break*/, 5];
257
+ case 4:
242
258
  logger_1.logger.info("FormoAnalytics: Skipping provider detection (Wagmi mode)");
243
- _b.label = 4;
244
- case 4: return [2 /*return*/, analytics];
259
+ _b.label = 5;
260
+ case 5: return [2 /*return*/, analytics];
245
261
  }
246
262
  });
247
263
  });
@@ -1427,11 +1443,9 @@ var FormoAnalytics = /** @class */ (function () {
1427
1443
  };
1428
1444
  FormoAnalytics.prototype.onLocationChange = function () {
1429
1445
  return __awaiter(this, void 0, void 0, function () {
1430
- var currentUrl;
1431
1446
  return __generator(this, function (_a) {
1432
- currentUrl = (0, storage_1.cookie)().get(constants_1.SESSION_CURRENT_URL_KEY);
1433
- if (currentUrl !== window.location.href) {
1434
- (0, storage_1.cookie)().set(constants_1.SESSION_CURRENT_URL_KEY, window.location.href);
1447
+ if (this._currentUrl !== window.location.href) {
1448
+ this._currentUrl = window.location.href;
1435
1449
  this.trackPageHit();
1436
1450
  }
1437
1451
  return [2 /*return*/];
@@ -1770,10 +1784,9 @@ var FormoAnalytics = /** @class */ (function () {
1770
1784
  *
1771
1785
  * @example
1772
1786
  * ```tsx
1773
- * formo.solana.setWallet(wallet);
1774
- * formo.solana.setConnection(connection);
1787
+ * formo.solana.setStore(client.store);
1775
1788
  * formo.solana.setCluster("devnet");
1776
- * formo.solana.syncWalletState();
1789
+ * // For signatures, use formo.signature() directly
1777
1790
  * ```
1778
1791
  */
1779
1792
  get: function () {
@@ -1,5 +1,4 @@
1
1
  export declare const SESSION_TRAFFIC_SOURCE_KEY = "traffic-source";
2
- export declare const SESSION_CURRENT_URL_KEY = "analytics-current-url";
3
2
  export declare const SESSION_USER_ID_KEY = "user-id";
4
3
  export declare const LOCAL_ANONYMOUS_ID_KEY = "anonymous-id";
5
4
  export declare const CONSENT_OPT_OUT_KEY = "opt-out-tracking";
@@ -1,10 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BLOCKED_ADDRESSES = exports.DEAD_ADDRESS = exports.ZERO_ADDRESS = exports.DEFAULT_PROVIDER_ICON = exports.CONSENT_OPT_OUT_KEY = exports.LOCAL_ANONYMOUS_ID_KEY = exports.SESSION_USER_ID_KEY = exports.SESSION_CURRENT_URL_KEY = exports.SESSION_TRAFFIC_SOURCE_KEY = void 0;
3
+ exports.BLOCKED_ADDRESSES = exports.DEAD_ADDRESS = exports.ZERO_ADDRESS = exports.DEFAULT_PROVIDER_ICON = exports.CONSENT_OPT_OUT_KEY = exports.LOCAL_ANONYMOUS_ID_KEY = exports.SESSION_USER_ID_KEY = exports.SESSION_TRAFFIC_SOURCE_KEY = void 0;
4
4
  exports.SESSION_TRAFFIC_SOURCE_KEY = "traffic-source";
5
5
  // SESSION_WALLET_DETECTED_KEY and SESSION_WALLET_IDENTIFIED_KEY
6
6
  // are now defined in src/session/index.ts
7
- exports.SESSION_CURRENT_URL_KEY = "analytics-current-url";
8
7
  exports.SESSION_USER_ID_KEY = "user-id";
9
8
  exports.LOCAL_ANONYMOUS_ID_KEY = "anonymous-id";
10
9
  // Consent management keys
@@ -17,6 +17,7 @@ declare class EventFactory implements IEventFactory {
17
17
  private getLanguage;
18
18
  private getLibraryVersion;
19
19
  private extractUTMParameters;
20
+ private extractClickIdParameters;
20
21
  private extractReferralParameter;
21
22
  private getTrafficSources;
22
23
  private getScreen;
@@ -87,6 +87,15 @@ var EventFactory = /** @class */ (function () {
87
87
  catch (_a) { }
88
88
  return result;
89
89
  };
90
+ this.extractClickIdParameters = function (urlObj) {
91
+ var result = {};
92
+ for (var _i = 0, CLICK_ID_PARAMS_1 = constants_2.CLICK_ID_PARAMS; _i < CLICK_ID_PARAMS_1.length; _i++) {
93
+ var param = CLICK_ID_PARAMS_1[_i];
94
+ var value = urlObj.searchParams.get(param);
95
+ result[param] = value ? value.trim() : "";
96
+ }
97
+ return result;
98
+ };
90
99
  this.extractReferralParameter = function (urlObj) {
91
100
  var _a, _b, _c;
92
101
  // Strategy: Check query params first, then check path pattern if configured
@@ -119,25 +128,23 @@ var EventFactory = /** @class */ (function () {
119
128
  };
120
129
  this.getTrafficSources = function (url) {
121
130
  var urlObj = new URL(url);
122
- var contextTrafficSources = __assign(__assign({}, _this.extractUTMParameters(url)), { ref: _this.extractReferralParameter(urlObj), referrer: document.referrer });
131
+ var contextTrafficSources = __assign(__assign(__assign({}, _this.extractUTMParameters(url)), _this.extractClickIdParameters(urlObj)), { ref: _this.extractReferralParameter(urlObj), referrer: document.referrer });
123
132
  var storedTrafficSources = (0, storage_1.session)().get(constants_1.SESSION_TRAFFIC_SOURCE_KEY) || {};
124
- var finalTrafficSources = {
125
- ref: contextTrafficSources.ref || (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources.ref) || "",
126
- referrer: contextTrafficSources.referrer || (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources.referrer) || "",
127
- utm_campaign: contextTrafficSources.utm_campaign ||
133
+ var mergedClickIds = {};
134
+ for (var _i = 0, CLICK_ID_PARAMS_2 = constants_2.CLICK_ID_PARAMS; _i < CLICK_ID_PARAMS_2.length; _i++) {
135
+ var p = CLICK_ID_PARAMS_2[_i];
136
+ mergedClickIds[p] =
137
+ contextTrafficSources[p] || (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources[p]) || "";
138
+ }
139
+ var finalTrafficSources = __assign({ ref: contextTrafficSources.ref || (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources.ref) || "", referrer: contextTrafficSources.referrer || (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources.referrer) || "", utm_campaign: contextTrafficSources.utm_campaign ||
128
140
  (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources.utm_campaign) ||
129
- "",
130
- utm_content: contextTrafficSources.utm_content ||
141
+ "", utm_content: contextTrafficSources.utm_content ||
131
142
  (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources.utm_content) ||
132
- "",
133
- utm_medium: contextTrafficSources.utm_medium ||
143
+ "", utm_medium: contextTrafficSources.utm_medium ||
134
144
  (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources.utm_medium) ||
135
- "",
136
- utm_source: contextTrafficSources.utm_source ||
145
+ "", utm_source: contextTrafficSources.utm_source ||
137
146
  (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources.utm_source) ||
138
- "",
139
- utm_term: contextTrafficSources.utm_term || (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources.utm_term) || "",
140
- };
147
+ "", utm_term: contextTrafficSources.utm_term || (storedTrafficSources === null || storedTrafficSources === void 0 ? void 0 : storedTrafficSources.utm_term) || "" }, mergedClickIds);
141
148
  // Store to session
142
149
  var sessionStoredTrafficSources = Object.keys(finalTrafficSources).reduce(function (res, key) {
143
150
  var value = finalTrafficSources[key];
@@ -1,11 +1,17 @@
1
1
  declare const CHANNEL = "web";
2
2
  declare const VERSION = "0";
3
+ /**
4
+ * Paid-attribution click IDs captured from the landing-page URL and persisted
5
+ * across the session alongside UTM parameters. Keep the ClickIdParameters type
6
+ * in src/types/events.ts derived from this array.
7
+ */
8
+ declare const CLICK_ID_PARAMS: readonly ["gclid", "gad_source", "fbclid", "msclkid", "twclid", "li_fat_id", "rdt_cid", "ttclid"];
3
9
  /**
4
10
  * Fields that should be excluded from page event properties parsing
5
11
  * These are either:
6
- * - Already captured in event context (UTM params, referral params)
12
+ * - Already captured in event context (UTM params, referral params, click IDs)
7
13
  * - Semantic event properties that should not be overridden by URL params
8
14
  */
9
15
  declare const PAGE_PROPERTIES_EXCLUDED_FIELDS: Set<string>;
10
- export { CHANNEL, VERSION, PAGE_PROPERTIES_EXCLUDED_FIELDS };
16
+ export { CHANNEL, VERSION, CLICK_ID_PARAMS, PAGE_PROPERTIES_EXCLUDED_FIELDS };
11
17
  //# sourceMappingURL=constants.d.ts.map
@@ -1,17 +1,42 @@
1
1
  "use strict";
2
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
3
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
4
+ if (ar || !(i in from)) {
5
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
6
+ ar[i] = from[i];
7
+ }
8
+ }
9
+ return to.concat(ar || Array.prototype.slice.call(from));
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PAGE_PROPERTIES_EXCLUDED_FIELDS = exports.VERSION = exports.CHANNEL = void 0;
12
+ exports.PAGE_PROPERTIES_EXCLUDED_FIELDS = exports.CLICK_ID_PARAMS = exports.VERSION = exports.CHANNEL = void 0;
4
13
  var CHANNEL = "web";
5
14
  exports.CHANNEL = CHANNEL;
6
15
  var VERSION = "0";
7
16
  exports.VERSION = VERSION;
17
+ /**
18
+ * Paid-attribution click IDs captured from the landing-page URL and persisted
19
+ * across the session alongside UTM parameters. Keep the ClickIdParameters type
20
+ * in src/types/events.ts derived from this array.
21
+ */
22
+ var CLICK_ID_PARAMS = [
23
+ "gclid", // Google Ads
24
+ "gad_source", // Google Ads (newer)
25
+ "fbclid", // Meta (Facebook/Instagram)
26
+ "msclkid", // Microsoft Ads (Bing)
27
+ "twclid", // Twitter/X Ads
28
+ "li_fat_id", // LinkedIn Ads
29
+ "rdt_cid", // Reddit Ads
30
+ "ttclid", // TikTok Ads
31
+ ];
32
+ exports.CLICK_ID_PARAMS = CLICK_ID_PARAMS;
8
33
  /**
9
34
  * Fields that should be excluded from page event properties parsing
10
35
  * These are either:
11
- * - Already captured in event context (UTM params, referral params)
36
+ * - Already captured in event context (UTM params, referral params, click IDs)
12
37
  * - Semantic event properties that should not be overridden by URL params
13
38
  */
14
- var PAGE_PROPERTIES_EXCLUDED_FIELDS = new Set([
39
+ var PAGE_PROPERTIES_EXCLUDED_FIELDS = new Set(__spreadArray(__spreadArray([
15
40
  // Context fields (already captured in event context)
16
41
  'utm_source',
17
42
  'utm_medium',
@@ -21,7 +46,8 @@ var PAGE_PROPERTIES_EXCLUDED_FIELDS = new Set([
21
46
  'ref',
22
47
  'referral',
23
48
  'refcode',
24
- 'referrer',
49
+ 'referrer'
50
+ ], CLICK_ID_PARAMS, true), [
25
51
  // Semantic event properties (should not be overridden by URL params)
26
52
  'category',
27
53
  'name',
@@ -29,6 +55,6 @@ var PAGE_PROPERTIES_EXCLUDED_FIELDS = new Set([
29
55
  'path',
30
56
  'hash',
31
57
  'query',
32
- ]);
58
+ ], false));
33
59
  exports.PAGE_PROPERTIES_EXCLUDED_FIELDS = PAGE_PROPERTIES_EXCLUDED_FIELDS;
34
60
  //# sourceMappingURL=constants.js.map
@@ -4,5 +4,7 @@ export * from "./types";
4
4
  export { parsePrivyProperties } from "./privy";
5
5
  export type { PrivyUser, PrivyLinkedAccount, PrivyAccountType, PrivyProfileProperties, PrivyWalletInfo } from "./privy";
6
6
  export { SolanaManager } from "./solana";
7
- export type { SolanaOptions, SolanaCluster, ISolanaAdapter, SolanaWalletContext, SolanaPublicKey, SolanaConnection, } from "./solana";
7
+ export { SOLANA_CHAIN_IDS, DEFAULT_SOLANA_CHAIN_ID, isSolanaChainId } from "./solana";
8
+ export type { SolanaOptions, SolanaCluster, } from "./solana";
9
+ export type { SolanaClientStore, SolanaClientState, } from "./solana";
8
10
  //# sourceMappingURL=index.d.ts.map
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.SolanaManager = exports.parsePrivyProperties = void 0;
17
+ exports.isSolanaChainId = exports.DEFAULT_SOLANA_CHAIN_ID = exports.SOLANA_CHAIN_IDS = exports.SolanaManager = exports.parsePrivyProperties = void 0;
18
18
  var initialization_1 = require("./initialization");
19
19
  __exportStar(require("./FormoAnalyticsProvider"), exports);
20
20
  __exportStar(require("./FormoAnalytics"), exports);
@@ -24,6 +24,10 @@ Object.defineProperty(exports, "parsePrivyProperties", { enumerable: true, get:
24
24
  // Solana integration exports
25
25
  var solana_1 = require("./solana");
26
26
  Object.defineProperty(exports, "SolanaManager", { enumerable: true, get: function () { return solana_1.SolanaManager; } });
27
+ var solana_2 = require("./solana");
28
+ Object.defineProperty(exports, "SOLANA_CHAIN_IDS", { enumerable: true, get: function () { return solana_2.SOLANA_CHAIN_IDS; } });
29
+ Object.defineProperty(exports, "DEFAULT_SOLANA_CHAIN_ID", { enumerable: true, get: function () { return solana_2.DEFAULT_SOLANA_CHAIN_ID; } });
30
+ Object.defineProperty(exports, "isSolanaChainId", { enumerable: true, get: function () { return solana_2.isSolanaChainId; } });
27
31
  if (typeof window !== "undefined")
28
32
  window.formofy = initialization_1.formofy;
29
33
  //# sourceMappingURL=index.js.map
@@ -1,24 +1,49 @@
1
1
  /**
2
2
  * SolanaManager
3
3
  *
4
- * Manages the lifecycle of the SolanaAdapter, handling lazy initialization
5
- * and pending configuration. This keeps Solana-specific lifecycle logic out of
6
- * the main FormoAnalytics class.
4
+ * Manages the lifecycle of the Solana store integration.
5
+ * Subscribes to framework-kit's zustand store for automatic event capture
6
+ * of wallet connect/disconnect and transaction lifecycle events.
7
+ *
8
+ * For signMessage/signTransaction tracking (not captured by the store),
9
+ * use formo.signature() directly with the address and chainId.
10
+ *
11
+ * For manual event tracking without the store, use the core API directly:
12
+ * formo.transaction(), formo.signature(), formo.connect(), formo.disconnect().
7
13
  */
8
14
  import { FormoAnalytics } from "../FormoAnalytics";
9
- import { SolanaAdapter } from "./SolanaAdapter";
10
- import { ISolanaAdapter, SolanaWalletContext, SolanaConnection, SolanaCluster, SolanaOptions } from "./types";
15
+ import { SolanaCluster, SolanaOptions } from "./types";
16
+ import { SolanaClientStore } from "./storeTypes";
11
17
  export declare class SolanaManager {
12
18
  private formo;
13
- private handler?;
14
- private pendingConnection?;
19
+ private storeHandler?;
15
20
  private pendingCluster?;
16
21
  constructor(formo: FormoAnalytics, options?: SolanaOptions);
17
- get adapter(): SolanaAdapter | undefined;
18
- setWallet(wallet: ISolanaAdapter | SolanaWalletContext | null): void;
19
- setConnection(connection: SolanaConnection | null): void;
22
+ /**
23
+ * Set the framework-kit zustand store for automatic event tracking.
24
+ * This enables autocapture mode — connect/disconnect and transaction events
25
+ * are tracked automatically by subscribing to store state changes.
26
+ *
27
+ * @param store - The framework-kit client store (client.store)
28
+ * @param options - Optional configuration
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * import { createClient } from '@solana-foundation/framework-kit';
33
+ *
34
+ * const client = createClient({ endpoint: '...', walletConnectors: autoDiscover() });
35
+ * formo.solana.setStore(client.store);
36
+ * ```
37
+ */
38
+ setStore(store: SolanaClientStore, options?: {
39
+ cluster?: SolanaCluster;
40
+ }): void;
41
+ /**
42
+ * Update the cluster/network. Only needed if the store endpoint doesn't
43
+ * contain a recognizable cluster name (e.g. custom RPC URLs).
44
+ * In most cases, the cluster is auto-detected from the store's endpoint.
45
+ */
20
46
  setCluster(cluster: SolanaCluster): void;
21
- syncWalletState(): void;
22
47
  cleanup(): void;
23
48
  }
24
49
  //# sourceMappingURL=SolanaManager.d.ts.map
@@ -2,77 +2,75 @@
2
2
  /**
3
3
  * SolanaManager
4
4
  *
5
- * Manages the lifecycle of the SolanaAdapter, handling lazy initialization
6
- * and pending configuration. This keeps Solana-specific lifecycle logic out of
7
- * the main FormoAnalytics class.
5
+ * Manages the lifecycle of the Solana store integration.
6
+ * Subscribes to framework-kit's zustand store for automatic event capture
7
+ * of wallet connect/disconnect and transaction lifecycle events.
8
+ *
9
+ * For signMessage/signTransaction tracking (not captured by the store),
10
+ * use formo.signature() directly with the address and chainId.
11
+ *
12
+ * For manual event tracking without the store, use the core API directly:
13
+ * formo.transaction(), formo.signature(), formo.connect(), formo.disconnect().
8
14
  */
9
15
  Object.defineProperty(exports, "__esModule", { value: true });
10
16
  exports.SolanaManager = void 0;
11
17
  var logger_1 = require("../logger");
12
- var SolanaAdapter_1 = require("./SolanaAdapter");
18
+ var SolanaStoreHandler_1 = require("./SolanaStoreHandler");
13
19
  var SolanaManager = /** @class */ (function () {
14
20
  function SolanaManager(formo, options) {
15
21
  this.formo = formo;
16
- if (options === null || options === void 0 ? void 0 : options.wallet) {
17
- logger_1.logger.info("SolanaManager: Initializing Solana wallet tracking");
18
- this.handler = new SolanaAdapter_1.SolanaAdapter(formo, {
19
- wallet: options.wallet,
20
- connection: options.connection,
22
+ if (options === null || options === void 0 ? void 0 : options.store) {
23
+ logger_1.logger.info("SolanaManager: Initializing store-based Solana tracking");
24
+ this.storeHandler = new SolanaStoreHandler_1.SolanaStoreHandler(formo, options.store, {
21
25
  cluster: options.cluster,
22
26
  });
23
27
  }
24
- else if (options) {
25
- // Store pending values for when wallet is set later
26
- this.pendingConnection = options.connection;
28
+ else if (options === null || options === void 0 ? void 0 : options.cluster) {
29
+ // Store pending cluster for when setStore is called later
27
30
  this.pendingCluster = options.cluster;
28
31
  }
29
32
  }
30
- Object.defineProperty(SolanaManager.prototype, "adapter", {
31
- get: function () {
32
- return this.handler;
33
- },
34
- enumerable: false,
35
- configurable: true
36
- });
37
- SolanaManager.prototype.setWallet = function (wallet) {
38
- if (this.handler) {
39
- this.handler.setWallet(wallet);
40
- }
41
- else if (wallet) {
42
- logger_1.logger.info("SolanaManager: Initializing Solana wallet tracking (lazy)");
43
- this.handler = new SolanaAdapter_1.SolanaAdapter(this.formo, {
44
- wallet: wallet,
45
- connection: this.pendingConnection,
46
- cluster: this.pendingCluster,
47
- });
48
- this.pendingConnection = undefined;
49
- this.pendingCluster = undefined;
50
- }
51
- };
52
- SolanaManager.prototype.setConnection = function (connection) {
53
- if (this.handler) {
54
- this.handler.setConnection(connection);
55
- }
56
- else {
57
- this.pendingConnection = connection !== null && connection !== void 0 ? connection : undefined;
58
- }
33
+ /**
34
+ * Set the framework-kit zustand store for automatic event tracking.
35
+ * This enables autocapture mode — connect/disconnect and transaction events
36
+ * are tracked automatically by subscribing to store state changes.
37
+ *
38
+ * @param store - The framework-kit client store (client.store)
39
+ * @param options - Optional configuration
40
+ *
41
+ * @example
42
+ * ```tsx
43
+ * import { createClient } from '@solana-foundation/framework-kit';
44
+ *
45
+ * const client = createClient({ endpoint: '...', walletConnectors: autoDiscover() });
46
+ * formo.solana.setStore(client.store);
47
+ * ```
48
+ */
49
+ SolanaManager.prototype.setStore = function (store, options) {
50
+ var _a;
51
+ (_a = this.storeHandler) === null || _a === void 0 ? void 0 : _a.cleanup();
52
+ this.storeHandler = new SolanaStoreHandler_1.SolanaStoreHandler(this.formo, store, {
53
+ cluster: (options === null || options === void 0 ? void 0 : options.cluster) || this.pendingCluster,
54
+ });
55
+ this.pendingCluster = undefined;
59
56
  };
57
+ /**
58
+ * Update the cluster/network. Only needed if the store endpoint doesn't
59
+ * contain a recognizable cluster name (e.g. custom RPC URLs).
60
+ * In most cases, the cluster is auto-detected from the store's endpoint.
61
+ */
60
62
  SolanaManager.prototype.setCluster = function (cluster) {
61
- if (this.handler) {
62
- this.handler.setCluster(cluster);
63
+ if (this.storeHandler) {
64
+ this.storeHandler.setCluster(cluster);
63
65
  }
64
66
  else {
65
67
  this.pendingCluster = cluster;
66
68
  }
67
69
  };
68
- SolanaManager.prototype.syncWalletState = function () {
69
- var _a;
70
- (_a = this.handler) === null || _a === void 0 ? void 0 : _a.syncWalletState();
71
- };
72
70
  SolanaManager.prototype.cleanup = function () {
73
71
  var _a;
74
- (_a = this.handler) === null || _a === void 0 ? void 0 : _a.cleanup();
75
- this.handler = undefined;
72
+ (_a = this.storeHandler) === null || _a === void 0 ? void 0 : _a.cleanup();
73
+ this.storeHandler = undefined;
76
74
  };
77
75
  return SolanaManager;
78
76
  }());
@@ -0,0 +1,88 @@
1
+ /**
2
+ * SolanaStoreHandler
3
+ *
4
+ * Handles wallet event tracking by subscribing to framework-kit's zustand store.
5
+ * This provides automatic event capture (autocapture) for Solana wallets without
6
+ * wrapping any wallet methods — similar to how WagmiEventHandler subscribes to
7
+ * TanStack Query's mutation/query caches.
8
+ *
9
+ * Subscribes to:
10
+ * - `state.wallet` — connect/disconnect events
11
+ * - `state.transactions` — transaction lifecycle events (sending → confirmed/failed)
12
+ *
13
+ * @see https://github.com/solana-foundation/framework-kit
14
+ */
15
+ import { FormoAnalytics } from "../FormoAnalytics";
16
+ import { SolanaClientStore } from "./storeTypes";
17
+ import { SolanaCluster } from "./types";
18
+ export declare class SolanaStoreHandler {
19
+ private formo;
20
+ private store;
21
+ private unsubscribers;
22
+ private cluster;
23
+ private chainId;
24
+ /**
25
+ * Track last known wallet status to detect transitions.
26
+ */
27
+ private lastWalletStatus;
28
+ private lastAddress?;
29
+ private lastChainId?;
30
+ /**
31
+ * Track processed transaction state changes to prevent duplicate events.
32
+ * Key format: `${signature}:${status}`
33
+ */
34
+ private processedTransactions;
35
+ /**
36
+ * Track transactions we've emitted STARTED for (status was "sending").
37
+ * Ensures we only emit STARTED once per transaction key.
38
+ */
39
+ private startedTransactions;
40
+ /**
41
+ * Per-transaction sender address captured at STARTED time.
42
+ * Ensures terminal events (confirmed/failed) are attributed correctly
43
+ * even if the wallet disconnects before the transaction settles.
44
+ */
45
+ private transactionSenders;
46
+ /**
47
+ * Whether the cluster was explicitly set (via options or setCluster).
48
+ * When true, auto-detection from the store endpoint is disabled.
49
+ */
50
+ private explicitCluster;
51
+ constructor(formoAnalytics: FormoAnalytics, store: SolanaClientStore, options?: {
52
+ cluster?: SolanaCluster;
53
+ });
54
+ /**
55
+ * Update the cluster/network.
56
+ */
57
+ setCluster(cluster: SolanaCluster): void;
58
+ /**
59
+ * Get the current chain ID.
60
+ */
61
+ getChainId(): number;
62
+ /**
63
+ * Resolve the current chainId from the live store state.
64
+ * This ensures correctness when wallet and cluster change in the same tick
65
+ * (the cluster subscription may not have fired yet).
66
+ */
67
+ private resolveCurrentChainId;
68
+ private setupWalletSubscription;
69
+ private checkInitialWalletState;
70
+ private handleWalletChange;
71
+ private handleConnect;
72
+ private handleDisconnect;
73
+ private setupClusterSubscription;
74
+ private handleClusterChange;
75
+ private setupTransactionSubscription;
76
+ private handleTransactionChanges;
77
+ private handleTransactionStatusChange;
78
+ /**
79
+ * Attempt to detect the Solana cluster from the store's endpoint URL.
80
+ */
81
+ private detectClusterFromStore;
82
+ /**
83
+ * Detect cluster from an RPC endpoint URL.
84
+ */
85
+ private detectClusterFromEndpoint;
86
+ cleanup(): void;
87
+ }
88
+ //# sourceMappingURL=SolanaStoreHandler.d.ts.map