@formo/analytics 1.25.0 → 1.27.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 (192) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -4
  3. package/dist/cjs/src/FormoAnalytics.d.ts +27 -15
  4. package/dist/cjs/src/FormoAnalytics.js +198 -257
  5. package/dist/cjs/src/FormoAnalyticsProvider.js +71 -13
  6. package/dist/{esm/src/lib/consent.d.ts → cjs/src/consent/index.d.ts} +1 -1
  7. package/dist/cjs/src/{lib/consent.js → consent/index.js} +1 -1
  8. package/dist/cjs/src/constants/base.d.ts +0 -2
  9. package/dist/cjs/src/constants/base.js +3 -3
  10. package/dist/cjs/src/constants/config.js +1 -1
  11. package/dist/cjs/src/{lib/event → event}/EventFactory.d.ts +2 -2
  12. package/dist/cjs/src/{lib/event → event}/EventFactory.js +9 -9
  13. package/dist/cjs/src/{lib/event → event}/EventManager.d.ts +1 -1
  14. package/dist/cjs/src/{lib/event → event}/EventManager.js +1 -1
  15. package/dist/cjs/src/{lib/event → event}/type.d.ts +1 -1
  16. package/dist/cjs/src/{lib/event → event}/utils.d.ts +1 -1
  17. package/dist/cjs/src/{lib/event → event}/utils.js +1 -1
  18. package/dist/cjs/src/fetch/index.d.ts +11 -0
  19. package/dist/cjs/src/fetch/index.js +126 -0
  20. package/dist/cjs/src/provider/detection.d.ts +58 -0
  21. package/dist/cjs/src/provider/detection.js +103 -0
  22. package/dist/cjs/src/provider/index.d.ts +6 -0
  23. package/dist/cjs/src/provider/index.js +11 -0
  24. package/dist/cjs/src/queue/EventQueue.d.ts +56 -0
  25. package/dist/cjs/src/{lib/queue → queue}/EventQueue.js +161 -52
  26. package/dist/{esm/src/lib → cjs/src}/queue/type.d.ts +1 -1
  27. package/dist/cjs/src/session/index.d.ts +91 -0
  28. package/dist/cjs/src/session/index.js +126 -0
  29. package/dist/cjs/src/{lib/storage → storage}/built-in/blueprint.js +1 -1
  30. package/dist/cjs/src/types/base.d.ts +35 -1
  31. package/dist/cjs/src/types/events.d.ts +5 -3
  32. package/dist/cjs/src/validators/object.js +0 -2
  33. package/dist/cjs/src/version.d.ts +1 -1
  34. package/dist/cjs/src/version.js +1 -1
  35. package/dist/cjs/src/wagmi/WagmiEventHandler.d.ts +93 -0
  36. package/dist/cjs/src/wagmi/WagmiEventHandler.js +669 -0
  37. package/dist/cjs/src/wagmi/index.d.ts +9 -0
  38. package/dist/cjs/src/wagmi/index.js +12 -0
  39. package/dist/cjs/src/wagmi/types.d.ts +146 -0
  40. package/dist/cjs/src/wagmi/types.js +10 -0
  41. package/dist/cjs/src/wagmi/utils.d.ts +74 -0
  42. package/dist/cjs/src/wagmi/utils.js +198 -0
  43. package/dist/esm/src/FormoAnalytics.d.ts +27 -15
  44. package/dist/esm/src/FormoAnalytics.js +88 -147
  45. package/dist/esm/src/FormoAnalyticsProvider.js +68 -10
  46. package/dist/{cjs/src/lib/consent.d.ts → esm/src/consent/index.d.ts} +1 -1
  47. package/dist/esm/src/{lib/consent.js → consent/index.js} +1 -1
  48. package/dist/esm/src/constants/base.d.ts +0 -2
  49. package/dist/esm/src/constants/base.js +2 -2
  50. package/dist/esm/src/constants/config.js +1 -1
  51. package/dist/esm/src/{lib/event → event}/EventFactory.d.ts +2 -2
  52. package/dist/esm/src/{lib/event → event}/EventFactory.js +9 -9
  53. package/dist/esm/src/{lib/event → event}/EventManager.d.ts +1 -1
  54. package/dist/esm/src/{lib/event → event}/EventManager.js +1 -1
  55. package/dist/esm/src/{lib/event → event}/type.d.ts +1 -1
  56. package/dist/esm/src/{lib/event → event}/utils.d.ts +1 -1
  57. package/dist/esm/src/{lib/event → event}/utils.js +1 -1
  58. package/dist/esm/src/fetch/index.d.ts +11 -0
  59. package/dist/esm/src/fetch/index.js +124 -0
  60. package/dist/esm/src/provider/detection.d.ts +58 -0
  61. package/dist/esm/src/provider/detection.js +98 -0
  62. package/dist/esm/src/provider/index.d.ts +6 -0
  63. package/dist/esm/src/provider/index.js +5 -0
  64. package/dist/esm/src/queue/EventQueue.d.ts +56 -0
  65. package/dist/esm/src/{lib/queue → queue}/EventQueue.js +161 -52
  66. package/dist/{cjs/src/lib → esm/src}/queue/type.d.ts +1 -1
  67. package/dist/esm/src/session/index.d.ts +91 -0
  68. package/dist/esm/src/session/index.js +123 -0
  69. package/dist/esm/src/{lib/storage → storage}/built-in/blueprint.js +1 -1
  70. package/dist/esm/src/types/base.d.ts +35 -1
  71. package/dist/esm/src/types/events.d.ts +5 -3
  72. package/dist/esm/src/validators/object.js +0 -2
  73. package/dist/esm/src/version.d.ts +1 -1
  74. package/dist/esm/src/version.js +1 -1
  75. package/dist/esm/src/wagmi/WagmiEventHandler.d.ts +93 -0
  76. package/dist/esm/src/wagmi/WagmiEventHandler.js +666 -0
  77. package/dist/esm/src/wagmi/index.d.ts +9 -0
  78. package/dist/esm/src/wagmi/index.js +8 -0
  79. package/dist/esm/src/wagmi/types.d.ts +146 -0
  80. package/dist/esm/src/wagmi/types.js +9 -0
  81. package/dist/esm/src/wagmi/utils.d.ts +74 -0
  82. package/dist/esm/src/wagmi/utils.js +192 -0
  83. package/dist/index.umd.min.js +1 -1
  84. package/package.json +23 -4
  85. package/dist/cjs/src/lib/fetch.d.ts +0 -3
  86. package/dist/cjs/src/lib/fetch.js +0 -8
  87. package/dist/cjs/src/lib/index.d.ts +0 -7
  88. package/dist/cjs/src/lib/index.js +0 -28
  89. package/dist/cjs/src/lib/queue/EventQueue.d.ts +0 -34
  90. package/dist/esm/src/lib/fetch.d.ts +0 -3
  91. package/dist/esm/src/lib/fetch.js +0 -3
  92. package/dist/esm/src/lib/index.d.ts +0 -7
  93. package/dist/esm/src/lib/index.js +0 -7
  94. package/dist/esm/src/lib/queue/EventQueue.d.ts +0 -34
  95. /package/dist/cjs/src/{lib/browser → browser}/browsers.d.ts +0 -0
  96. /package/dist/cjs/src/{lib/browser → browser}/browsers.js +0 -0
  97. /package/dist/cjs/src/{lib/event → event}/constants.d.ts +0 -0
  98. /package/dist/cjs/src/{lib/event → event}/constants.js +0 -0
  99. /package/dist/cjs/src/{lib/event → event}/index.d.ts +0 -0
  100. /package/dist/cjs/src/{lib/event → event}/index.js +0 -0
  101. /package/dist/cjs/src/{lib/event → event}/type.js +0 -0
  102. /package/dist/cjs/src/{lib/logger → logger}/Logger.d.ts +0 -0
  103. /package/dist/cjs/src/{lib/logger → logger}/Logger.js +0 -0
  104. /package/dist/cjs/src/{lib/logger → logger}/index.d.ts +0 -0
  105. /package/dist/cjs/src/{lib/logger → logger}/index.js +0 -0
  106. /package/dist/cjs/src/{lib/logger → logger}/type.d.ts +0 -0
  107. /package/dist/cjs/src/{lib/logger → logger}/type.js +0 -0
  108. /package/dist/cjs/src/{lib/queue → queue}/index.d.ts +0 -0
  109. /package/dist/cjs/src/{lib/queue → queue}/index.js +0 -0
  110. /package/dist/cjs/src/{lib/queue → queue}/type.js +0 -0
  111. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_curry1.d.ts +0 -0
  112. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_curry1.js +0 -0
  113. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_curry2.d.ts +0 -0
  114. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_curry2.js +0 -0
  115. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_curry3.d.ts +0 -0
  116. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_curry3.js +0 -0
  117. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_has.d.ts +0 -0
  118. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_has.js +0 -0
  119. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_isObject.d.ts +0 -0
  120. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_isObject.js +0 -0
  121. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_isPlaceholder.d.ts +0 -0
  122. /package/dist/cjs/src/{lib/ramda → ramda}/internal/_isPlaceholder.js +0 -0
  123. /package/dist/cjs/src/{lib/ramda → ramda}/mergeDeepRight.d.ts +0 -0
  124. /package/dist/cjs/src/{lib/ramda → ramda}/mergeDeepRight.js +0 -0
  125. /package/dist/cjs/src/{lib/ramda → ramda}/mergeDeepWithKey.d.ts +0 -0
  126. /package/dist/cjs/src/{lib/ramda → ramda}/mergeDeepWithKey.js +0 -0
  127. /package/dist/cjs/src/{lib/ramda → ramda}/mergeWithKey.d.ts +0 -0
  128. /package/dist/cjs/src/{lib/ramda → ramda}/mergeWithKey.js +0 -0
  129. /package/dist/cjs/src/{lib/storage → storage}/StorageManager.d.ts +0 -0
  130. /package/dist/cjs/src/{lib/storage → storage}/StorageManager.js +0 -0
  131. /package/dist/cjs/src/{lib/storage → storage}/built-in/blueprint.d.ts +0 -0
  132. /package/dist/cjs/src/{lib/storage → storage}/built-in/cookie.d.ts +0 -0
  133. /package/dist/cjs/src/{lib/storage → storage}/built-in/cookie.js +0 -0
  134. /package/dist/cjs/src/{lib/storage → storage}/built-in/memory.d.ts +0 -0
  135. /package/dist/cjs/src/{lib/storage → storage}/built-in/memory.js +0 -0
  136. /package/dist/cjs/src/{lib/storage → storage}/built-in/web.d.ts +0 -0
  137. /package/dist/cjs/src/{lib/storage → storage}/built-in/web.js +0 -0
  138. /package/dist/cjs/src/{lib/storage → storage}/constant.d.ts +0 -0
  139. /package/dist/cjs/src/{lib/storage → storage}/constant.js +0 -0
  140. /package/dist/cjs/src/{lib/storage → storage}/index.d.ts +0 -0
  141. /package/dist/cjs/src/{lib/storage → storage}/index.js +0 -0
  142. /package/dist/cjs/src/{lib/storage → storage}/type.d.ts +0 -0
  143. /package/dist/cjs/src/{lib/storage → storage}/type.js +0 -0
  144. /package/dist/esm/src/{lib/browser → browser}/browsers.d.ts +0 -0
  145. /package/dist/esm/src/{lib/browser → browser}/browsers.js +0 -0
  146. /package/dist/esm/src/{lib/event → event}/constants.d.ts +0 -0
  147. /package/dist/esm/src/{lib/event → event}/constants.js +0 -0
  148. /package/dist/esm/src/{lib/event → event}/index.d.ts +0 -0
  149. /package/dist/esm/src/{lib/event → event}/index.js +0 -0
  150. /package/dist/esm/src/{lib/event → event}/type.js +0 -0
  151. /package/dist/esm/src/{lib/logger → logger}/Logger.d.ts +0 -0
  152. /package/dist/esm/src/{lib/logger → logger}/Logger.js +0 -0
  153. /package/dist/esm/src/{lib/logger → logger}/index.d.ts +0 -0
  154. /package/dist/esm/src/{lib/logger → logger}/index.js +0 -0
  155. /package/dist/esm/src/{lib/logger → logger}/type.d.ts +0 -0
  156. /package/dist/esm/src/{lib/logger → logger}/type.js +0 -0
  157. /package/dist/esm/src/{lib/queue → queue}/index.d.ts +0 -0
  158. /package/dist/esm/src/{lib/queue → queue}/index.js +0 -0
  159. /package/dist/esm/src/{lib/queue → queue}/type.js +0 -0
  160. /package/dist/esm/src/{lib/ramda → ramda}/internal/_curry1.d.ts +0 -0
  161. /package/dist/esm/src/{lib/ramda → ramda}/internal/_curry1.js +0 -0
  162. /package/dist/esm/src/{lib/ramda → ramda}/internal/_curry2.d.ts +0 -0
  163. /package/dist/esm/src/{lib/ramda → ramda}/internal/_curry2.js +0 -0
  164. /package/dist/esm/src/{lib/ramda → ramda}/internal/_curry3.d.ts +0 -0
  165. /package/dist/esm/src/{lib/ramda → ramda}/internal/_curry3.js +0 -0
  166. /package/dist/esm/src/{lib/ramda → ramda}/internal/_has.d.ts +0 -0
  167. /package/dist/esm/src/{lib/ramda → ramda}/internal/_has.js +0 -0
  168. /package/dist/esm/src/{lib/ramda → ramda}/internal/_isObject.d.ts +0 -0
  169. /package/dist/esm/src/{lib/ramda → ramda}/internal/_isObject.js +0 -0
  170. /package/dist/esm/src/{lib/ramda → ramda}/internal/_isPlaceholder.d.ts +0 -0
  171. /package/dist/esm/src/{lib/ramda → ramda}/internal/_isPlaceholder.js +0 -0
  172. /package/dist/esm/src/{lib/ramda → ramda}/mergeDeepRight.d.ts +0 -0
  173. /package/dist/esm/src/{lib/ramda → ramda}/mergeDeepRight.js +0 -0
  174. /package/dist/esm/src/{lib/ramda → ramda}/mergeDeepWithKey.d.ts +0 -0
  175. /package/dist/esm/src/{lib/ramda → ramda}/mergeDeepWithKey.js +0 -0
  176. /package/dist/esm/src/{lib/ramda → ramda}/mergeWithKey.d.ts +0 -0
  177. /package/dist/esm/src/{lib/ramda → ramda}/mergeWithKey.js +0 -0
  178. /package/dist/esm/src/{lib/storage → storage}/StorageManager.d.ts +0 -0
  179. /package/dist/esm/src/{lib/storage → storage}/StorageManager.js +0 -0
  180. /package/dist/esm/src/{lib/storage → storage}/built-in/blueprint.d.ts +0 -0
  181. /package/dist/esm/src/{lib/storage → storage}/built-in/cookie.d.ts +0 -0
  182. /package/dist/esm/src/{lib/storage → storage}/built-in/cookie.js +0 -0
  183. /package/dist/esm/src/{lib/storage → storage}/built-in/memory.d.ts +0 -0
  184. /package/dist/esm/src/{lib/storage → storage}/built-in/memory.js +0 -0
  185. /package/dist/esm/src/{lib/storage → storage}/built-in/web.d.ts +0 -0
  186. /package/dist/esm/src/{lib/storage → storage}/built-in/web.js +0 -0
  187. /package/dist/esm/src/{lib/storage → storage}/constant.d.ts +0 -0
  188. /package/dist/esm/src/{lib/storage → storage}/constant.js +0 -0
  189. /package/dist/esm/src/{lib/storage → storage}/index.d.ts +0 -0
  190. /package/dist/esm/src/{lib/storage → storage}/index.js +0 -0
  191. /package/dist/esm/src/{lib/storage → storage}/type.d.ts +0 -0
  192. /package/dist/esm/src/{lib/storage → storage}/type.js +0 -0
@@ -0,0 +1,666 @@
1
+ /**
2
+ * WagmiEventHandler
3
+ *
4
+ * Handles wallet event tracking by hooking into Wagmi v2's config.subscribe()
5
+ * and TanStack Query's MutationCache. This replaces the EIP-1193 provider
6
+ * wrapping approach when Wagmi mode is enabled.
7
+ */
8
+ var __assign = (this && this.__assign) || function () {
9
+ __assign = Object.assign || function(t) {
10
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
11
+ s = arguments[i];
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
13
+ t[p] = s[p];
14
+ }
15
+ return t;
16
+ };
17
+ return __assign.apply(this, arguments);
18
+ };
19
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
20
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
21
+ return new (P || (P = Promise))(function (resolve, reject) {
22
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
23
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
24
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
25
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
26
+ });
27
+ };
28
+ var __generator = (this && this.__generator) || function (thisArg, body) {
29
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
30
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
31
+ function verb(n) { return function (v) { return step([n, v]); }; }
32
+ function step(op) {
33
+ if (f) throw new TypeError("Generator is already executing.");
34
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
35
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
36
+ if (y = 0, t) op = [op[0] & 2, t.value];
37
+ switch (op[0]) {
38
+ case 0: case 1: t = op; break;
39
+ case 4: _.label++; return { value: op[1], done: false };
40
+ case 5: _.label++; y = op[1]; op = [0]; continue;
41
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
42
+ default:
43
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
44
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
45
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
46
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
47
+ if (t[2]) _.ops.pop();
48
+ _.trys.pop(); continue;
49
+ }
50
+ op = body.call(thisArg, _);
51
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
52
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
53
+ }
54
+ };
55
+ import { SignatureStatus, TransactionStatus } from "../types/events";
56
+ import { logger } from "../logger";
57
+ import { encodeWriteContractData, extractFunctionArgs, buildSafeFunctionArgs, } from "./utils";
58
+ /**
59
+ * Built-in transaction fields that could collide with function args.
60
+ * Defined at module level to avoid recreating on every method call.
61
+ */
62
+ var RESERVED_FIELDS = new Set([
63
+ "status",
64
+ "chainId",
65
+ "address",
66
+ "data",
67
+ "to",
68
+ "value",
69
+ "transactionHash",
70
+ "function_name",
71
+ "function_args",
72
+ ]);
73
+ /**
74
+ * Clean up old entries from a Set to prevent memory leaks.
75
+ * Removes oldest entries when size exceeds maxSize.
76
+ *
77
+ * @param set - The Set to clean up
78
+ * @param maxSize - Maximum allowed size before cleanup (default: 1000)
79
+ * @param removeCount - Number of entries to remove (default: 500)
80
+ */
81
+ function cleanupOldEntries(set, maxSize, removeCount) {
82
+ if (maxSize === void 0) { maxSize = 1000; }
83
+ if (removeCount === void 0) { removeCount = 500; }
84
+ if (set.size > maxSize) {
85
+ var entries = Array.from(set);
86
+ for (var i = 0; i < removeCount && i < entries.length; i++) {
87
+ set.delete(entries[i]);
88
+ }
89
+ }
90
+ }
91
+ var WagmiEventHandler = /** @class */ (function () {
92
+ function WagmiEventHandler(formoAnalytics, wagmiConfig, queryClient) {
93
+ this.unsubscribers = [];
94
+ this.trackingState = {
95
+ isProcessing: false,
96
+ };
97
+ /**
98
+ * Track processed mutation states to prevent duplicate event emissions
99
+ * Key format: `${mutationId}:${status}`
100
+ */
101
+ this.processedMutations = new Set();
102
+ /**
103
+ * Track processed query states to prevent duplicate event emissions
104
+ * Key format: `${queryHash}:${status}`
105
+ */
106
+ this.processedQueries = new Set();
107
+ /**
108
+ * Store transaction details from BROADCASTED events for use in CONFIRMED/REVERTED
109
+ * Key: transactionHash, Value: transaction details including the original sender address
110
+ */
111
+ this.pendingTransactions = new Map();
112
+ this.formo = formoAnalytics;
113
+ this.wagmiConfig = wagmiConfig;
114
+ this.queryClient = queryClient;
115
+ logger.info("WagmiEventHandler: Initializing Wagmi integration");
116
+ // Set up connection/disconnection/chain listeners
117
+ this.setupConnectionListeners();
118
+ // Set up mutation and query tracking if QueryClient is provided
119
+ if (this.queryClient) {
120
+ this.setupMutationTracking();
121
+ this.setupQueryTracking();
122
+ }
123
+ else {
124
+ logger.warn("WagmiEventHandler: QueryClient not provided, signature and transaction events will not be tracked");
125
+ }
126
+ }
127
+ /**
128
+ * Set up listeners for wallet connection, disconnection, and chain changes
129
+ */
130
+ WagmiEventHandler.prototype.setupConnectionListeners = function () {
131
+ var _this = this;
132
+ logger.info("WagmiEventHandler: Setting up connection listeners");
133
+ // Subscribe to status changes (connect/disconnect)
134
+ var statusUnsubscribe = this.wagmiConfig.subscribe(function (state) { return state.status; }, function (status, prevStatus) {
135
+ _this.handleStatusChange(status, prevStatus);
136
+ });
137
+ this.unsubscribers.push(statusUnsubscribe);
138
+ // Subscribe to chain ID changes
139
+ var chainIdUnsubscribe = this.wagmiConfig.subscribe(function (state) { return state.chainId; }, function (chainId, prevChainId) {
140
+ _this.handleChainChange(chainId, prevChainId);
141
+ });
142
+ this.unsubscribers.push(chainIdUnsubscribe);
143
+ logger.info("WagmiEventHandler: Connection listeners set up successfully");
144
+ };
145
+ /**
146
+ * Handle status changes (connect/disconnect)
147
+ */
148
+ WagmiEventHandler.prototype.handleStatusChange = function (status, prevStatus) {
149
+ return __awaiter(this, void 0, void 0, function () {
150
+ var state, address, chainId, connectorName, error_1;
151
+ return __generator(this, function (_a) {
152
+ switch (_a.label) {
153
+ case 0:
154
+ // Prevent concurrent processing
155
+ if (this.trackingState.isProcessing) {
156
+ logger.debug("WagmiEventHandler: Already processing status change, skipping");
157
+ return [2 /*return*/];
158
+ }
159
+ this.trackingState.isProcessing = true;
160
+ _a.label = 1;
161
+ case 1:
162
+ _a.trys.push([1, 7, 8, 9]);
163
+ state = this.getState();
164
+ address = this.getConnectedAddress(state);
165
+ chainId = state.chainId;
166
+ logger.info("WagmiEventHandler: Status changed", {
167
+ status: status,
168
+ prevStatus: prevStatus,
169
+ address: address,
170
+ chainId: chainId,
171
+ });
172
+ if (!(status === "disconnected" && prevStatus === "connected")) return [3 /*break*/, 4];
173
+ if (!this.formo.isAutocaptureEnabled("disconnect")) return [3 /*break*/, 3];
174
+ return [4 /*yield*/, this.formo.disconnect({
175
+ chainId: this.trackingState.lastChainId,
176
+ address: this.trackingState.lastAddress,
177
+ })];
178
+ case 2:
179
+ _a.sent();
180
+ _a.label = 3;
181
+ case 3:
182
+ this.trackingState.lastAddress = undefined;
183
+ this.trackingState.lastChainId = undefined;
184
+ _a.label = 4;
185
+ case 4:
186
+ if (!(status === "connected" && prevStatus !== "connected")) return [3 /*break*/, 6];
187
+ if (!(address && chainId !== undefined)) return [3 /*break*/, 6];
188
+ this.trackingState.lastAddress = address;
189
+ this.trackingState.lastChainId = chainId;
190
+ if (!this.formo.isAutocaptureEnabled("connect")) return [3 /*break*/, 6];
191
+ connectorName = this.getConnectorName(state);
192
+ return [4 /*yield*/, this.formo.connect({ chainId: chainId, address: address }, __assign({}, (connectorName && { providerName: connectorName })))];
193
+ case 5:
194
+ _a.sent();
195
+ _a.label = 6;
196
+ case 6:
197
+ this.trackingState.lastStatus = status;
198
+ return [3 /*break*/, 9];
199
+ case 7:
200
+ error_1 = _a.sent();
201
+ logger.error("WagmiEventHandler: Error handling status change:", error_1);
202
+ return [3 /*break*/, 9];
203
+ case 8:
204
+ this.trackingState.isProcessing = false;
205
+ return [7 /*endfinally*/];
206
+ case 9: return [2 /*return*/];
207
+ }
208
+ });
209
+ });
210
+ };
211
+ /**
212
+ * Handle chain ID changes
213
+ */
214
+ WagmiEventHandler.prototype.handleChainChange = function (chainId, prevChainId) {
215
+ return __awaiter(this, void 0, void 0, function () {
216
+ var state, address, error_2;
217
+ return __generator(this, function (_a) {
218
+ switch (_a.label) {
219
+ case 0:
220
+ if (chainId === prevChainId || chainId === undefined) {
221
+ return [2 /*return*/];
222
+ }
223
+ state = this.getState();
224
+ if (state.status !== "connected") {
225
+ return [2 /*return*/];
226
+ }
227
+ address = this.getConnectedAddress(state);
228
+ if (!address) {
229
+ logger.warn("WagmiEventHandler: Chain changed but no address found");
230
+ return [2 /*return*/];
231
+ }
232
+ logger.info("WagmiEventHandler: Chain changed", {
233
+ chainId: chainId,
234
+ prevChainId: prevChainId,
235
+ address: address,
236
+ });
237
+ this.trackingState.lastChainId = chainId;
238
+ if (!this.formo.isAutocaptureEnabled("chain")) return [3 /*break*/, 4];
239
+ _a.label = 1;
240
+ case 1:
241
+ _a.trys.push([1, 3, , 4]);
242
+ return [4 /*yield*/, this.formo.chain({ chainId: chainId, address: address })];
243
+ case 2:
244
+ _a.sent();
245
+ return [3 /*break*/, 4];
246
+ case 3:
247
+ error_2 = _a.sent();
248
+ logger.error("WagmiEventHandler: Error tracking chain change:", error_2);
249
+ return [3 /*break*/, 4];
250
+ case 4: return [2 /*return*/];
251
+ }
252
+ });
253
+ });
254
+ };
255
+ /**
256
+ * Set up mutation tracking for signatures and transactions
257
+ */
258
+ WagmiEventHandler.prototype.setupMutationTracking = function () {
259
+ var _this = this;
260
+ if (!this.queryClient) {
261
+ return;
262
+ }
263
+ logger.info("WagmiEventHandler: Setting up mutation tracking");
264
+ var mutationCache = this.queryClient.getMutationCache();
265
+ var unsubscribe = mutationCache.subscribe(function (event) {
266
+ _this.handleMutationEvent(event);
267
+ });
268
+ this.unsubscribers.push(unsubscribe);
269
+ logger.info("WagmiEventHandler: Mutation tracking set up successfully");
270
+ };
271
+ /**
272
+ * Set up query tracking for transaction confirmations
273
+ * Listens for waitForTransactionReceipt queries to detect CONFIRMED status
274
+ */
275
+ WagmiEventHandler.prototype.setupQueryTracking = function () {
276
+ var _this = this;
277
+ if (!this.queryClient) {
278
+ return;
279
+ }
280
+ logger.info("WagmiEventHandler: Setting up query tracking");
281
+ var queryCache = this.queryClient.getQueryCache();
282
+ var unsubscribe = queryCache.subscribe(function (event) {
283
+ _this.handleQueryEvent(event);
284
+ });
285
+ this.unsubscribers.push(unsubscribe);
286
+ logger.info("WagmiEventHandler: Query tracking set up successfully");
287
+ };
288
+ /**
289
+ * Handle query cache events (transaction confirmations)
290
+ */
291
+ WagmiEventHandler.prototype.handleQueryEvent = function (event) {
292
+ if (event.type !== "updated") {
293
+ return;
294
+ }
295
+ var query = event.query;
296
+ var queryKey = query.queryKey;
297
+ if (!queryKey || queryKey.length === 0) {
298
+ return;
299
+ }
300
+ var queryType = queryKey[0];
301
+ // Only handle waitForTransactionReceipt queries
302
+ if (queryType !== "waitForTransactionReceipt") {
303
+ return;
304
+ }
305
+ var state = query.state;
306
+ // Extract receipt status early to include in deduplication key
307
+ // This ensures CONFIRMED vs REVERTED outcomes are processed separately
308
+ var receipt = state.data;
309
+ var receiptStatus = receipt === null || receipt === void 0 ? void 0 : receipt.status;
310
+ // Create a unique key for this query state to prevent duplicate processing
311
+ // Include receipt status to distinguish between CONFIRMED and REVERTED outcomes
312
+ var queryStateKey = "".concat(query.queryHash, ":").concat(state.status, ":").concat(receiptStatus || "");
313
+ // Skip if we've already processed this query state
314
+ if (this.processedQueries.has(queryStateKey)) {
315
+ logger.debug("WagmiEventHandler: Skipping duplicate query event", {
316
+ queryType: queryType,
317
+ queryHash: query.queryHash,
318
+ status: state.status,
319
+ receiptStatus: receiptStatus,
320
+ });
321
+ return;
322
+ }
323
+ // Mark this query state as processed
324
+ this.processedQueries.add(queryStateKey);
325
+ logger.debug("WagmiEventHandler: Query event", {
326
+ queryType: queryType,
327
+ queryHash: query.queryHash,
328
+ status: state.status,
329
+ });
330
+ // Handle transaction receipt queries
331
+ this.handleTransactionReceiptQuery(query);
332
+ // Clean up old processed queries to prevent memory leaks
333
+ cleanupOldEntries(this.processedQueries);
334
+ };
335
+ /**
336
+ * Handle waitForTransactionReceipt query completion
337
+ * Emits CONFIRMED or REVERTED transaction status
338
+ */
339
+ WagmiEventHandler.prototype.handleTransactionReceiptQuery = function (query) {
340
+ var _a;
341
+ if (!this.formo.isAutocaptureEnabled("transaction")) {
342
+ return;
343
+ }
344
+ var state = query.state;
345
+ var queryKey = query.queryKey;
346
+ // Only handle successful queries (transaction confirmed on chain)
347
+ if (state.status !== "success") {
348
+ return;
349
+ }
350
+ // Extract hash and chainId from query key
351
+ // Query key format: ['waitForTransactionReceipt', { hash, chainId, ... }]
352
+ var params = queryKey[1];
353
+ var transactionHash = params === null || params === void 0 ? void 0 : params.hash;
354
+ var chainId = (params === null || params === void 0 ? void 0 : params.chainId) || this.trackingState.lastChainId;
355
+ if (!transactionHash) {
356
+ logger.warn("WagmiEventHandler: Transaction receipt query but no hash found");
357
+ return;
358
+ }
359
+ // Retrieve stored transaction details from BROADCASTED event
360
+ // Normalize hash to lowercase for consistent lookup
361
+ var normalizedHash = transactionHash.toLowerCase();
362
+ var pendingTx = this.pendingTransactions.get(normalizedHash);
363
+ // Use the original sender address from BROADCASTED event if available,
364
+ // otherwise fall back to current connected address.
365
+ // This handles wallet switches between broadcast and confirmation.
366
+ var address = (pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.address) || this.trackingState.lastAddress;
367
+ if (!address) {
368
+ logger.warn("WagmiEventHandler: Transaction receipt query but no address available");
369
+ return;
370
+ }
371
+ try {
372
+ // Extract receipt data
373
+ var receipt = state.data;
374
+ // Determine transaction status from receipt
375
+ // receipt.status is 'success' or 'reverted' in viem
376
+ var txStatus = (receipt === null || receipt === void 0 ? void 0 : receipt.status) === "reverted"
377
+ ? TransactionStatus.REVERTED
378
+ : TransactionStatus.CONFIRMED;
379
+ logger.info("WagmiEventHandler: Tracking transaction confirmation", {
380
+ status: txStatus,
381
+ transactionHash: transactionHash,
382
+ address: address,
383
+ chainId: chainId,
384
+ blockNumber: (_a = receipt === null || receipt === void 0 ? void 0 : receipt.blockNumber) === null || _a === void 0 ? void 0 : _a.toString(),
385
+ });
386
+ this.formo.transaction(__assign(__assign(__assign(__assign(__assign({ status: txStatus, chainId: chainId || 0, address: address, transactionHash: transactionHash }, ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.data) && { data: pendingTx.data })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.to) && { to: pendingTx.to })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.value) && { value: pendingTx.value })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.function_name) && { function_name: pendingTx.function_name })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.function_args) && { function_args: pendingTx.function_args })),
387
+ // Spread function args as additional properties (only colliding keys are prefixed)
388
+ pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.safeFunctionArgs);
389
+ // Clean up the pending transaction after confirmation
390
+ this.pendingTransactions.delete(normalizedHash);
391
+ }
392
+ catch (error) {
393
+ logger.error("WagmiEventHandler: Error handling transaction receipt query:", error);
394
+ }
395
+ };
396
+ /**
397
+ * Handle mutation cache events (signatures, transactions)
398
+ */
399
+ WagmiEventHandler.prototype.handleMutationEvent = function (event) {
400
+ if (event.type !== "updated") {
401
+ return;
402
+ }
403
+ var mutation = event.mutation;
404
+ var mutationKey = mutation.options.mutationKey;
405
+ if (!mutationKey || mutationKey.length === 0) {
406
+ return;
407
+ }
408
+ var mutationType = mutationKey[0];
409
+ var state = mutation.state;
410
+ // Create a unique key for this mutation state to prevent duplicate processing
411
+ var mutationStateKey = "".concat(mutation.mutationId, ":").concat(state.status);
412
+ // Skip if we've already processed this mutation state
413
+ if (this.processedMutations.has(mutationStateKey)) {
414
+ logger.debug("WagmiEventHandler: Skipping duplicate mutation event", {
415
+ mutationType: mutationType,
416
+ mutationId: mutation.mutationId,
417
+ status: state.status,
418
+ });
419
+ return;
420
+ }
421
+ // Mark this mutation state as processed
422
+ this.processedMutations.add(mutationStateKey);
423
+ logger.debug("WagmiEventHandler: Mutation event", {
424
+ mutationType: mutationType,
425
+ mutationId: mutation.mutationId,
426
+ status: state.status,
427
+ });
428
+ // Handle signature mutations
429
+ if (mutationType === "signMessage" || mutationType === "signTypedData") {
430
+ this.handleSignatureMutation(mutationType, mutation);
431
+ }
432
+ // Handle transaction mutations
433
+ if (mutationType === "sendTransaction" || mutationType === "writeContract") {
434
+ this.handleTransactionMutation(mutationType, mutation);
435
+ }
436
+ // Clean up old processed mutations to prevent memory leaks
437
+ cleanupOldEntries(this.processedMutations);
438
+ };
439
+ /**
440
+ * Handle signature mutations (signMessage, signTypedData)
441
+ */
442
+ WagmiEventHandler.prototype.handleSignatureMutation = function (mutationType, mutation) {
443
+ if (!this.formo.isAutocaptureEnabled("signature")) {
444
+ return;
445
+ }
446
+ var state = mutation.state;
447
+ var variables = state.variables || {};
448
+ var chainId = this.trackingState.lastChainId;
449
+ var address = this.trackingState.lastAddress;
450
+ if (!address) {
451
+ logger.warn("WagmiEventHandler: Signature event but no address available");
452
+ return;
453
+ }
454
+ try {
455
+ // Map Wagmi mutation status to Formo signature status
456
+ var status_1;
457
+ var signatureHash = void 0;
458
+ if (state.status === "pending") {
459
+ status_1 = SignatureStatus.REQUESTED;
460
+ }
461
+ else if (state.status === "success") {
462
+ status_1 = SignatureStatus.CONFIRMED;
463
+ signatureHash = state.data;
464
+ }
465
+ else if (state.status === "error") {
466
+ status_1 = SignatureStatus.REJECTED;
467
+ }
468
+ else {
469
+ return; // Ignore idle state
470
+ }
471
+ // Extract message from variables
472
+ var message = void 0;
473
+ if (mutationType === "signMessage") {
474
+ message = variables.message || "";
475
+ }
476
+ else {
477
+ // For signTypedData, stringify the typed data
478
+ message = JSON.stringify(variables.message || variables.types || {});
479
+ }
480
+ logger.info("WagmiEventHandler: Tracking signature event", {
481
+ status: status_1,
482
+ mutationType: mutationType,
483
+ address: address,
484
+ chainId: chainId,
485
+ });
486
+ this.formo.signature(__assign({ status: status_1, chainId: chainId, address: address, message: message }, (signatureHash && { signatureHash: signatureHash })));
487
+ }
488
+ catch (error) {
489
+ logger.error("WagmiEventHandler: Error handling signature mutation:", error);
490
+ }
491
+ };
492
+ /**
493
+ * Handle transaction mutations (sendTransaction, writeContract)
494
+ */
495
+ WagmiEventHandler.prototype.handleTransactionMutation = function (mutationType, mutation) {
496
+ var _a;
497
+ if (!this.formo.isAutocaptureEnabled("transaction")) {
498
+ return;
499
+ }
500
+ var state = mutation.state;
501
+ var variables = state.variables || {};
502
+ var chainId = this.trackingState.lastChainId || variables.chainId;
503
+ // For sendTransaction, user's address is the 'from'
504
+ // For writeContract, variables.address is the contract address, not the user
505
+ // variables.account can be a string address or an Account object with an address property
506
+ var accountValue = variables.account;
507
+ var accountAddress = typeof accountValue === "string"
508
+ ? accountValue
509
+ : accountValue === null || accountValue === void 0 ? void 0 : accountValue.address;
510
+ var userAddress = this.trackingState.lastAddress || accountAddress || variables.from;
511
+ if (!userAddress) {
512
+ logger.warn("WagmiEventHandler: Transaction event but no address available");
513
+ return;
514
+ }
515
+ try {
516
+ // Map Wagmi mutation status to Formo transaction status
517
+ var status_2;
518
+ var transactionHash = void 0;
519
+ if (state.status === "pending") {
520
+ status_2 = TransactionStatus.STARTED;
521
+ }
522
+ else if (state.status === "success") {
523
+ status_2 = TransactionStatus.BROADCASTED;
524
+ transactionHash = state.data;
525
+ }
526
+ else if (state.status === "error") {
527
+ status_2 = TransactionStatus.REJECTED;
528
+ }
529
+ else {
530
+ return; // Ignore idle state
531
+ }
532
+ // Extract transaction details based on mutation type
533
+ var data = void 0;
534
+ var to = void 0;
535
+ var function_name = void 0;
536
+ var function_args = void 0;
537
+ var value = (_a = variables.value) === null || _a === void 0 ? void 0 : _a.toString();
538
+ if (mutationType === "writeContract") {
539
+ // For writeContract, extract function info and encode data
540
+ var abi = variables.abi, fnName = variables.functionName, args = variables.args, contractAddress = variables.address;
541
+ to = contractAddress;
542
+ function_name = fnName;
543
+ if (abi && fnName) {
544
+ // Extract function arguments as a name-value map
545
+ function_args = extractFunctionArgs(abi, fnName, args);
546
+ // Encode the function data synchronously if viem is available
547
+ var encodedData = encodeWriteContractData(abi, fnName, args);
548
+ if (encodedData) {
549
+ data = encodedData;
550
+ logger.debug("WagmiEventHandler: Encoded writeContract data", data.substring(0, 10));
551
+ }
552
+ }
553
+ }
554
+ else {
555
+ // For sendTransaction, use variables directly
556
+ // Only data is available, function_name and function_args are not sent
557
+ data = variables.data;
558
+ to = variables.to;
559
+ }
560
+ logger.info("WagmiEventHandler: Tracking transaction event", {
561
+ status: status_2,
562
+ mutationType: mutationType,
563
+ address: userAddress,
564
+ chainId: chainId,
565
+ transactionHash: transactionHash,
566
+ function_name: function_name,
567
+ });
568
+ // Build safeFunctionArgs with collision handling and struct flattening
569
+ var safeFunctionArgs = buildSafeFunctionArgs(function_args, RESERVED_FIELDS);
570
+ // Store transaction details for BROADCASTED status to use in CONFIRMED/REVERTED
571
+ // Normalize hash to lowercase for consistent lookup
572
+ // Include the sender address to handle wallet switches between broadcast and confirmation
573
+ if (status_2 === TransactionStatus.BROADCASTED && transactionHash) {
574
+ var normalizedHash = transactionHash.toLowerCase();
575
+ var txDetails = __assign(__assign(__assign(__assign(__assign(__assign({ address: userAddress }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })), (safeFunctionArgs && { safeFunctionArgs: safeFunctionArgs }));
576
+ this.pendingTransactions.set(normalizedHash, txDetails);
577
+ logger.debug("WagmiEventHandler: Stored pending transaction for confirmation", {
578
+ transactionHash: normalizedHash,
579
+ });
580
+ // Clean up old pending transactions to prevent memory leaks (keep max 100)
581
+ // Remove oldest 50 entries when limit exceeded to handle high-throughput scenarios
582
+ if (this.pendingTransactions.size > 100) {
583
+ var keys = Array.from(this.pendingTransactions.keys());
584
+ for (var i = 0; i < 50 && i < keys.length; i++) {
585
+ this.pendingTransactions.delete(keys[i]);
586
+ }
587
+ }
588
+ }
589
+ this.formo.transaction(__assign(__assign(__assign(__assign(__assign(__assign({ status: status_2, chainId: chainId || 0, address: userAddress }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (transactionHash && { transactionHash: transactionHash })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })),
590
+ // Spread function args as additional properties (only colliding keys are prefixed)
591
+ safeFunctionArgs);
592
+ }
593
+ catch (error) {
594
+ logger.error("WagmiEventHandler: Error handling transaction mutation:", error);
595
+ }
596
+ };
597
+ /**
598
+ * Get the current Wagmi state
599
+ * Supports both getState() method and direct state property access
600
+ * for compatibility with different Wagmi wrappers (RainbowKit, etc.)
601
+ */
602
+ WagmiEventHandler.prototype.getState = function () {
603
+ // Try getState() method first (standard Wagmi API)
604
+ if (typeof this.wagmiConfig.getState === "function") {
605
+ return this.wagmiConfig.getState();
606
+ }
607
+ // Fall back to direct state property (RainbowKit and some Wagmi setups)
608
+ if (this.wagmiConfig.state) {
609
+ return this.wagmiConfig.state;
610
+ }
611
+ // Return a default disconnected state if neither is available
612
+ logger.warn("WagmiEventHandler: Unable to get state from config, returning default state");
613
+ return {
614
+ status: "disconnected",
615
+ connections: new Map(),
616
+ current: undefined,
617
+ chainId: undefined,
618
+ };
619
+ };
620
+ /**
621
+ * Get the currently connected address from Wagmi state
622
+ */
623
+ WagmiEventHandler.prototype.getConnectedAddress = function (state) {
624
+ if (!state.current) {
625
+ return undefined;
626
+ }
627
+ var connection = state.connections.get(state.current);
628
+ if (!connection || connection.accounts.length === 0) {
629
+ return undefined;
630
+ }
631
+ return connection.accounts[0];
632
+ };
633
+ /**
634
+ * Get the connector name from Wagmi state
635
+ */
636
+ WagmiEventHandler.prototype.getConnectorName = function (state) {
637
+ if (!state.current) {
638
+ return undefined;
639
+ }
640
+ var connection = state.connections.get(state.current);
641
+ return connection === null || connection === void 0 ? void 0 : connection.connector.name;
642
+ };
643
+ /**
644
+ * Clean up all subscriptions
645
+ */
646
+ WagmiEventHandler.prototype.cleanup = function () {
647
+ logger.info("WagmiEventHandler: Cleaning up subscriptions");
648
+ for (var _i = 0, _a = this.unsubscribers; _i < _a.length; _i++) {
649
+ var unsubscribe = _a[_i];
650
+ try {
651
+ unsubscribe();
652
+ }
653
+ catch (error) {
654
+ logger.error("WagmiEventHandler: Error during cleanup:", error);
655
+ }
656
+ }
657
+ this.unsubscribers = [];
658
+ this.processedMutations.clear();
659
+ this.processedQueries.clear();
660
+ this.pendingTransactions.clear();
661
+ logger.info("WagmiEventHandler: Cleanup complete");
662
+ };
663
+ return WagmiEventHandler;
664
+ }());
665
+ export { WagmiEventHandler };
666
+ //# sourceMappingURL=WagmiEventHandler.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Wagmi integration module
3
+ *
4
+ * Provides integration with Wagmi v2 for wallet event tracking.
5
+ * This module exports the WagmiEventHandler and related types.
6
+ */
7
+ export { WagmiEventHandler } from "./WagmiEventHandler";
8
+ export type { WagmiState, WagmiConnection, WagmiConnector, WagmiConfig, MutationState, Mutation, MutationCacheEvent, MutationCache, QueryClient, UnsubscribeFn, WagmiMutationKey, WagmiTrackingState, } from "./types";
9
+ //# sourceMappingURL=index.d.ts.map