@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
@@ -1,12 +1,36 @@
1
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
2
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
3
+ if (ar || !(i in from)) {
4
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
5
+ ar[i] = from[i];
6
+ }
7
+ }
8
+ return to.concat(ar || Array.prototype.slice.call(from));
9
+ };
1
10
  var CHANNEL = "web";
2
11
  var VERSION = "0";
12
+ /**
13
+ * Paid-attribution click IDs captured from the landing-page URL and persisted
14
+ * across the session alongside UTM parameters. Keep the ClickIdParameters type
15
+ * in src/types/events.ts derived from this array.
16
+ */
17
+ var CLICK_ID_PARAMS = [
18
+ "gclid", // Google Ads
19
+ "gad_source", // Google Ads (newer)
20
+ "fbclid", // Meta (Facebook/Instagram)
21
+ "msclkid", // Microsoft Ads (Bing)
22
+ "twclid", // Twitter/X Ads
23
+ "li_fat_id", // LinkedIn Ads
24
+ "rdt_cid", // Reddit Ads
25
+ "ttclid", // TikTok Ads
26
+ ];
3
27
  /**
4
28
  * Fields that should be excluded from page event properties parsing
5
29
  * These are either:
6
- * - Already captured in event context (UTM params, referral params)
30
+ * - Already captured in event context (UTM params, referral params, click IDs)
7
31
  * - Semantic event properties that should not be overridden by URL params
8
32
  */
9
- var PAGE_PROPERTIES_EXCLUDED_FIELDS = new Set([
33
+ var PAGE_PROPERTIES_EXCLUDED_FIELDS = new Set(__spreadArray(__spreadArray([
10
34
  // Context fields (already captured in event context)
11
35
  'utm_source',
12
36
  'utm_medium',
@@ -16,7 +40,8 @@ var PAGE_PROPERTIES_EXCLUDED_FIELDS = new Set([
16
40
  'ref',
17
41
  'referral',
18
42
  'refcode',
19
- 'referrer',
43
+ 'referrer'
44
+ ], CLICK_ID_PARAMS, true), [
20
45
  // Semantic event properties (should not be overridden by URL params)
21
46
  'category',
22
47
  'name',
@@ -24,6 +49,6 @@ var PAGE_PROPERTIES_EXCLUDED_FIELDS = new Set([
24
49
  'path',
25
50
  'hash',
26
51
  'query',
27
- ]);
28
- export { CHANNEL, VERSION, PAGE_PROPERTIES_EXCLUDED_FIELDS };
52
+ ], false));
53
+ export { CHANNEL, VERSION, CLICK_ID_PARAMS, PAGE_PROPERTIES_EXCLUDED_FIELDS };
29
54
  //# 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
@@ -5,6 +5,7 @@ export * from "./types";
5
5
  export { parsePrivyProperties } from "./privy";
6
6
  // Solana integration exports
7
7
  export { SolanaManager } from "./solana";
8
+ export { SOLANA_CHAIN_IDS, DEFAULT_SOLANA_CHAIN_ID, isSolanaChainId } from "./solana";
8
9
  if (typeof window !== "undefined")
9
10
  window.formofy = formofy;
10
11
  //# 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
@@ -1,75 +1,73 @@
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 { logger } from "../logger";
9
- import { SolanaAdapter } from "./SolanaAdapter";
15
+ import { SolanaStoreHandler } from "./SolanaStoreHandler";
10
16
  var SolanaManager = /** @class */ (function () {
11
17
  function SolanaManager(formo, options) {
12
18
  this.formo = formo;
13
- if (options === null || options === void 0 ? void 0 : options.wallet) {
14
- logger.info("SolanaManager: Initializing Solana wallet tracking");
15
- this.handler = new SolanaAdapter(formo, {
16
- wallet: options.wallet,
17
- connection: options.connection,
19
+ if (options === null || options === void 0 ? void 0 : options.store) {
20
+ logger.info("SolanaManager: Initializing store-based Solana tracking");
21
+ this.storeHandler = new SolanaStoreHandler(formo, options.store, {
18
22
  cluster: options.cluster,
19
23
  });
20
24
  }
21
- else if (options) {
22
- // Store pending values for when wallet is set later
23
- this.pendingConnection = options.connection;
25
+ else if (options === null || options === void 0 ? void 0 : options.cluster) {
26
+ // Store pending cluster for when setStore is called later
24
27
  this.pendingCluster = options.cluster;
25
28
  }
26
29
  }
27
- Object.defineProperty(SolanaManager.prototype, "adapter", {
28
- get: function () {
29
- return this.handler;
30
- },
31
- enumerable: false,
32
- configurable: true
33
- });
34
- SolanaManager.prototype.setWallet = function (wallet) {
35
- if (this.handler) {
36
- this.handler.setWallet(wallet);
37
- }
38
- else if (wallet) {
39
- logger.info("SolanaManager: Initializing Solana wallet tracking (lazy)");
40
- this.handler = new SolanaAdapter(this.formo, {
41
- wallet: wallet,
42
- connection: this.pendingConnection,
43
- cluster: this.pendingCluster,
44
- });
45
- this.pendingConnection = undefined;
46
- this.pendingCluster = undefined;
47
- }
48
- };
49
- SolanaManager.prototype.setConnection = function (connection) {
50
- if (this.handler) {
51
- this.handler.setConnection(connection);
52
- }
53
- else {
54
- this.pendingConnection = connection !== null && connection !== void 0 ? connection : undefined;
55
- }
30
+ /**
31
+ * Set the framework-kit zustand store for automatic event tracking.
32
+ * This enables autocapture mode — connect/disconnect and transaction events
33
+ * are tracked automatically by subscribing to store state changes.
34
+ *
35
+ * @param store - The framework-kit client store (client.store)
36
+ * @param options - Optional configuration
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * import { createClient } from '@solana-foundation/framework-kit';
41
+ *
42
+ * const client = createClient({ endpoint: '...', walletConnectors: autoDiscover() });
43
+ * formo.solana.setStore(client.store);
44
+ * ```
45
+ */
46
+ SolanaManager.prototype.setStore = function (store, options) {
47
+ var _a;
48
+ (_a = this.storeHandler) === null || _a === void 0 ? void 0 : _a.cleanup();
49
+ this.storeHandler = new SolanaStoreHandler(this.formo, store, {
50
+ cluster: (options === null || options === void 0 ? void 0 : options.cluster) || this.pendingCluster,
51
+ });
52
+ this.pendingCluster = undefined;
56
53
  };
54
+ /**
55
+ * Update the cluster/network. Only needed if the store endpoint doesn't
56
+ * contain a recognizable cluster name (e.g. custom RPC URLs).
57
+ * In most cases, the cluster is auto-detected from the store's endpoint.
58
+ */
57
59
  SolanaManager.prototype.setCluster = function (cluster) {
58
- if (this.handler) {
59
- this.handler.setCluster(cluster);
60
+ if (this.storeHandler) {
61
+ this.storeHandler.setCluster(cluster);
60
62
  }
61
63
  else {
62
64
  this.pendingCluster = cluster;
63
65
  }
64
66
  };
65
- SolanaManager.prototype.syncWalletState = function () {
66
- var _a;
67
- (_a = this.handler) === null || _a === void 0 ? void 0 : _a.syncWalletState();
68
- };
69
67
  SolanaManager.prototype.cleanup = function () {
70
68
  var _a;
71
- (_a = this.handler) === null || _a === void 0 ? void 0 : _a.cleanup();
72
- this.handler = undefined;
69
+ (_a = this.storeHandler) === null || _a === void 0 ? void 0 : _a.cleanup();
70
+ this.storeHandler = undefined;
73
71
  };
74
72
  return SolanaManager;
75
73
  }());
@@ -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