@formo/analytics 1.19.5 → 1.19.7
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.
- package/dist/cjs/src/FormoAnalytics.d.ts +85 -4
- package/dist/cjs/src/FormoAnalytics.js +801 -273
- package/dist/cjs/src/constants/base.d.ts +1 -0
- package/dist/cjs/src/constants/base.js +3 -1
- package/dist/cjs/src/initialization.js +13 -0
- package/dist/cjs/src/lib/event/EventFactory.d.ts +1 -1
- package/dist/cjs/src/lib/event/EventFactory.js +1 -1
- package/dist/cjs/src/types/base.d.ts +1 -0
- package/dist/cjs/src/types/events.d.ts +2 -2
- package/dist/cjs/src/types/provider.d.ts +8 -0
- package/dist/cjs/src/types/provider.js +3 -0
- package/dist/esm/src/FormoAnalytics.d.ts +85 -4
- package/dist/esm/src/FormoAnalytics.js +803 -275
- package/dist/esm/src/constants/base.d.ts +1 -0
- package/dist/esm/src/constants/base.js +2 -0
- package/dist/esm/src/initialization.js +13 -0
- package/dist/esm/src/lib/event/EventFactory.d.ts +1 -1
- package/dist/esm/src/lib/event/EventFactory.js +1 -1
- package/dist/esm/src/types/base.d.ts +1 -0
- package/dist/esm/src/types/events.d.ts +2 -2
- package/dist/esm/src/types/provider.d.ts +8 -0
- package/dist/esm/src/types/provider.js +2 -1
- package/dist/index.umd.min.js +1 -1
- package/package.json +2 -2
|
@@ -46,6 +46,15 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
46
46
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
50
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
51
|
+
if (ar || !(i in from)) {
|
|
52
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
53
|
+
ar[i] = from[i];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
57
|
+
};
|
|
49
58
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
59
|
exports.FormoAnalytics = void 0;
|
|
51
60
|
var mipd_1 = require("mipd");
|
|
@@ -62,8 +71,23 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
62
71
|
var _a, _b;
|
|
63
72
|
this.writeKey = writeKey;
|
|
64
73
|
this.options = options;
|
|
65
|
-
this.
|
|
74
|
+
this._providerListenersMap = new Map();
|
|
75
|
+
/**
|
|
76
|
+
* EIP-6963 provider details discovered through the browser
|
|
77
|
+
* This array contains all available providers with their metadata
|
|
78
|
+
*/
|
|
66
79
|
this._providers = [];
|
|
80
|
+
/**
|
|
81
|
+
* Set of providers that have been tracked with event listeners
|
|
82
|
+
* This is separate from _providers because:
|
|
83
|
+
* - _providers contains all discovered providers (EIP-6963)
|
|
84
|
+
* - _trackedProviders contains only providers that have been set up with listeners
|
|
85
|
+
* - A provider can be discovered but not yet tracked (e.g., during initialization)
|
|
86
|
+
* - A provider can be tracked but later removed from discovery
|
|
87
|
+
*/
|
|
88
|
+
this._trackedProviders = new Set();
|
|
89
|
+
// Set to efficiently track seen providers for deduplication and O(1) lookup
|
|
90
|
+
this._seenProviders = new Set();
|
|
67
91
|
this.currentUserId = "";
|
|
68
92
|
this.config = {
|
|
69
93
|
writeKey: writeKey,
|
|
@@ -92,14 +116,43 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
92
116
|
maxQueueSize: options.maxQueueSize,
|
|
93
117
|
flushInterval: options.flushInterval,
|
|
94
118
|
}));
|
|
95
|
-
//
|
|
96
|
-
var provider =
|
|
119
|
+
// Handle initial provider (injected) as fallback; listeners for EIP-6963 are added later
|
|
120
|
+
var provider = undefined;
|
|
121
|
+
var optProvider = options.provider;
|
|
122
|
+
if (optProvider) {
|
|
123
|
+
provider = optProvider;
|
|
124
|
+
}
|
|
125
|
+
else if (typeof window !== 'undefined' && window.ethereum) {
|
|
126
|
+
provider = window.ethereum;
|
|
127
|
+
}
|
|
97
128
|
if (provider) {
|
|
98
129
|
this.trackProvider(provider);
|
|
99
130
|
}
|
|
100
131
|
this.trackPageHit();
|
|
101
132
|
this.trackPageHits();
|
|
102
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Helper method to check if a provider is different from the currently active one
|
|
136
|
+
* @param provider The provider to check
|
|
137
|
+
* @returns true if there's a provider mismatch, false otherwise
|
|
138
|
+
*/
|
|
139
|
+
FormoAnalytics.prototype.isProviderMismatch = function (provider) {
|
|
140
|
+
// Only consider it a mismatch if we have an active provider AND the provider is different
|
|
141
|
+
// This allows legitimate provider switching while preventing race conditions
|
|
142
|
+
return this._provider != null && this._provider !== provider;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Check if a provider is in a valid state for switching
|
|
146
|
+
* @param provider The provider to validate
|
|
147
|
+
* @returns true if the provider is in a valid state
|
|
148
|
+
*/
|
|
149
|
+
FormoAnalytics.prototype.isProviderInValidState = function (provider) {
|
|
150
|
+
// Basic validation: ensure provider exists and has required methods
|
|
151
|
+
return (provider &&
|
|
152
|
+
typeof provider.request === 'function' &&
|
|
153
|
+
typeof provider.on === 'function' &&
|
|
154
|
+
typeof provider.removeListener === 'function');
|
|
155
|
+
};
|
|
103
156
|
FormoAnalytics.init = function (writeKey, options) {
|
|
104
157
|
return __awaiter(this, void 0, void 0, function () {
|
|
105
158
|
var analytics, _a;
|
|
@@ -117,6 +170,7 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
117
170
|
return [4 /*yield*/, analytics.detectWallets(analytics._providers)];
|
|
118
171
|
case 2:
|
|
119
172
|
_b.sent();
|
|
173
|
+
analytics.trackProviders(analytics._providers);
|
|
120
174
|
return [2 /*return*/, analytics];
|
|
121
175
|
}
|
|
122
176
|
});
|
|
@@ -154,6 +208,7 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
154
208
|
this.currentUserId = undefined;
|
|
155
209
|
(0, lib_1.cookie)().remove(constants_1.LOCAL_ANONYMOUS_ID_KEY);
|
|
156
210
|
(0, lib_1.cookie)().remove(constants_1.SESSION_USER_ID_KEY);
|
|
211
|
+
(0, lib_1.cookie)().remove(constants_1.SESSION_WALLET_DETECTED_KEY);
|
|
157
212
|
};
|
|
158
213
|
/**
|
|
159
214
|
* Emits a connect wallet event.
|
|
@@ -162,25 +217,30 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
162
217
|
* @param {IFormoEventProperties} properties
|
|
163
218
|
* @param {IFormoEventContext} context
|
|
164
219
|
* @param {(...args: unknown[]) => void} callback
|
|
165
|
-
* @throws {Error} If chainId or address is empty
|
|
166
220
|
* @returns {Promise<void>}
|
|
167
221
|
*/
|
|
168
222
|
FormoAnalytics.prototype.connect = function (_a, properties_1, context_1, callback_1) {
|
|
169
223
|
return __awaiter(this, arguments, void 0, function (_b, properties, context, callback) {
|
|
170
|
-
var
|
|
224
|
+
var checksummedAddress;
|
|
171
225
|
var chainId = _b.chainId, address = _b.address;
|
|
172
226
|
return __generator(this, function (_c) {
|
|
173
227
|
switch (_c.label) {
|
|
174
228
|
case 0:
|
|
175
|
-
if (
|
|
176
|
-
lib_1.logger.warn("Connect: Chain ID cannot be
|
|
229
|
+
if (chainId === null || chainId === undefined) {
|
|
230
|
+
lib_1.logger.warn("Connect: Chain ID cannot be null or undefined");
|
|
231
|
+
return [2 /*return*/];
|
|
177
232
|
}
|
|
178
233
|
if (!address) {
|
|
179
234
|
lib_1.logger.warn("Connect: Address cannot be empty");
|
|
235
|
+
return [2 /*return*/];
|
|
180
236
|
}
|
|
181
237
|
this.currentChainId = chainId;
|
|
182
|
-
|
|
183
|
-
|
|
238
|
+
checksummedAddress = this.validateAndChecksumAddress(address);
|
|
239
|
+
if (!checksummedAddress) {
|
|
240
|
+
lib_1.logger.warn("Connect: Invalid address provided (\"".concat(address, "\"). Please provide a valid Ethereum address in checksum format."));
|
|
241
|
+
return [2 /*return*/];
|
|
242
|
+
}
|
|
243
|
+
this.currentAddress = checksummedAddress;
|
|
184
244
|
return [4 /*yield*/, this.trackEvent(constants_1.EventType.CONNECT, {
|
|
185
245
|
chainId: chainId,
|
|
186
246
|
address: this.currentAddress,
|
|
@@ -203,16 +263,24 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
203
263
|
*/
|
|
204
264
|
FormoAnalytics.prototype.disconnect = function (params, properties, context, callback) {
|
|
205
265
|
return __awaiter(this, void 0, void 0, function () {
|
|
206
|
-
var chainId, address;
|
|
266
|
+
var chainId, address, providerInfo, disconnectProperties;
|
|
207
267
|
return __generator(this, function (_a) {
|
|
208
268
|
switch (_a.label) {
|
|
209
269
|
case 0:
|
|
210
270
|
chainId = (params === null || params === void 0 ? void 0 : params.chainId) || this.currentChainId;
|
|
211
271
|
address = (params === null || params === void 0 ? void 0 : params.address) || this.currentAddress;
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
272
|
+
providerInfo = this._provider ? this.getProviderInfo(this._provider) : null;
|
|
273
|
+
lib_1.logger.info("Disconnect: Emitting disconnect event with:", {
|
|
274
|
+
chainId: chainId,
|
|
275
|
+
address: address,
|
|
276
|
+
providerName: providerInfo === null || providerInfo === void 0 ? void 0 : providerInfo.name,
|
|
277
|
+
rdns: providerInfo === null || providerInfo === void 0 ? void 0 : providerInfo.rdns
|
|
278
|
+
});
|
|
279
|
+
disconnectProperties = __assign(__assign({}, (providerInfo && {
|
|
280
|
+
providerName: providerInfo.name,
|
|
281
|
+
rdns: providerInfo.rdns
|
|
282
|
+
})), properties);
|
|
283
|
+
return [4 /*yield*/, this.trackEvent(constants_1.EventType.DISCONNECT, __assign(__assign({}, (chainId && { chainId: chainId })), (address && { address: address })), disconnectProperties, context, callback)];
|
|
216
284
|
case 1:
|
|
217
285
|
_a.sent();
|
|
218
286
|
this.currentAddress = undefined;
|
|
@@ -230,8 +298,6 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
230
298
|
* @param {IFormoEventProperties} properties
|
|
231
299
|
* @param {IFormoEventContext} context
|
|
232
300
|
* @param {(...args: unknown[]) => void} callback
|
|
233
|
-
* @throws {Error} If chainId is empty, zero, or not a valid number
|
|
234
|
-
* @throws {Error} If no address is provided and no previous address is recorded
|
|
235
301
|
* @returns {Promise<void>}
|
|
236
302
|
*/
|
|
237
303
|
FormoAnalytics.prototype.chain = function (_a, properties_1, context_1, callback_1) {
|
|
@@ -241,13 +307,16 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
241
307
|
switch (_c.label) {
|
|
242
308
|
case 0:
|
|
243
309
|
if (!chainId || Number(chainId) === 0) {
|
|
244
|
-
|
|
310
|
+
lib_1.logger.warn("FormoAnalytics::chain: chainId cannot be empty or 0");
|
|
311
|
+
return [2 /*return*/];
|
|
245
312
|
}
|
|
246
313
|
if (isNaN(Number(chainId))) {
|
|
247
|
-
|
|
314
|
+
lib_1.logger.warn("FormoAnalytics::chain: chainId must be a valid decimal number");
|
|
315
|
+
return [2 /*return*/];
|
|
248
316
|
}
|
|
249
317
|
if (!address && !this.currentAddress) {
|
|
250
|
-
|
|
318
|
+
lib_1.logger.warn("FormoAnalytics::chain: address was empty and no previous address has been recorded");
|
|
319
|
+
return [2 /*return*/];
|
|
251
320
|
}
|
|
252
321
|
this.currentChainId = chainId;
|
|
253
322
|
return [4 /*yield*/, this.trackEvent(constants_1.EventType.CHAIN, {
|
|
@@ -327,27 +396,28 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
327
396
|
FormoAnalytics.prototype.identify = function (params, properties, context, callback) {
|
|
328
397
|
return __awaiter(this, void 0, void 0, function () {
|
|
329
398
|
var _i, _a, providerDetail, provider, address_2, err_1, userId, address, providerName, rdns, validAddress, e_1;
|
|
330
|
-
|
|
331
|
-
|
|
399
|
+
var _b;
|
|
400
|
+
return __generator(this, function (_c) {
|
|
401
|
+
switch (_c.label) {
|
|
332
402
|
case 0:
|
|
333
|
-
|
|
403
|
+
_c.trys.push([0, 11, , 12]);
|
|
334
404
|
if (!!params) return [3 /*break*/, 9];
|
|
335
405
|
// If no params provided, auto-identify
|
|
336
406
|
lib_1.logger.info("Auto-identifying with providers:", this._providers.map(function (p) { return p.info.name; }));
|
|
337
407
|
_i = 0, _a = this._providers;
|
|
338
|
-
|
|
408
|
+
_c.label = 1;
|
|
339
409
|
case 1:
|
|
340
410
|
if (!(_i < _a.length)) return [3 /*break*/, 8];
|
|
341
411
|
providerDetail = _a[_i];
|
|
342
412
|
provider = providerDetail.provider;
|
|
343
413
|
if (!provider)
|
|
344
414
|
return [3 /*break*/, 7];
|
|
345
|
-
|
|
415
|
+
_c.label = 2;
|
|
346
416
|
case 2:
|
|
347
|
-
|
|
417
|
+
_c.trys.push([2, 6, , 7]);
|
|
348
418
|
return [4 /*yield*/, this.getAddress(provider)];
|
|
349
419
|
case 3:
|
|
350
|
-
address_2 =
|
|
420
|
+
address_2 = _c.sent();
|
|
351
421
|
if (!address_2) return [3 /*break*/, 5];
|
|
352
422
|
lib_1.logger.info("Auto-identifying", address_2, providerDetail.info.name, providerDetail.info.rdns);
|
|
353
423
|
// NOTE: do not set this.currentAddress without explicit connect or identify
|
|
@@ -358,11 +428,11 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
358
428
|
}, properties, context, callback)];
|
|
359
429
|
case 4:
|
|
360
430
|
// NOTE: do not set this.currentAddress without explicit connect or identify
|
|
361
|
-
|
|
362
|
-
|
|
431
|
+
_c.sent();
|
|
432
|
+
_c.label = 5;
|
|
363
433
|
case 5: return [3 /*break*/, 7];
|
|
364
434
|
case 6:
|
|
365
|
-
err_1 =
|
|
435
|
+
err_1 = _c.sent();
|
|
366
436
|
lib_1.logger.error("Failed to identify provider ".concat(providerDetail.info.name, ":"), err_1);
|
|
367
437
|
return [3 /*break*/, 7];
|
|
368
438
|
case 7:
|
|
@@ -372,24 +442,32 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
372
442
|
case 9:
|
|
373
443
|
userId = params.userId, address = params.address, providerName = params.providerName, rdns = params.rdns;
|
|
374
444
|
lib_1.logger.info("Identify", address, userId, providerName, rdns);
|
|
375
|
-
validAddress =
|
|
376
|
-
if (
|
|
377
|
-
|
|
445
|
+
validAddress = undefined;
|
|
446
|
+
if (address) {
|
|
447
|
+
validAddress = this.validateAndChecksumAddress(address);
|
|
448
|
+
this.currentAddress = validAddress || undefined;
|
|
449
|
+
if (!validAddress) {
|
|
450
|
+
(_b = lib_1.logger.warn) === null || _b === void 0 ? void 0 : _b.call(lib_1.logger, "Invalid address provided to identify:", address);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
this.currentAddress = undefined;
|
|
455
|
+
}
|
|
378
456
|
if (userId) {
|
|
379
457
|
this.currentUserId = userId;
|
|
380
458
|
(0, lib_1.cookie)().set(constants_1.SESSION_USER_ID_KEY, userId);
|
|
381
459
|
}
|
|
382
460
|
return [4 /*yield*/, this.trackEvent(constants_1.EventType.IDENTIFY, {
|
|
383
|
-
address: validAddress
|
|
461
|
+
address: validAddress,
|
|
384
462
|
providerName: providerName,
|
|
385
463
|
userId: userId,
|
|
386
464
|
rdns: rdns,
|
|
387
465
|
}, properties, context, callback)];
|
|
388
466
|
case 10:
|
|
389
|
-
|
|
467
|
+
_c.sent();
|
|
390
468
|
return [3 /*break*/, 12];
|
|
391
469
|
case 11:
|
|
392
|
-
e_1 =
|
|
470
|
+
e_1 = _c.sent();
|
|
393
471
|
lib_1.logger.log("identify error", e_1);
|
|
394
472
|
return [3 /*break*/, 12];
|
|
395
473
|
case 12: return [2 /*return*/];
|
|
@@ -452,138 +530,226 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
452
530
|
FormoAnalytics.prototype.trackProvider = function (provider) {
|
|
453
531
|
lib_1.logger.info("trackProvider", provider);
|
|
454
532
|
try {
|
|
455
|
-
if (provider
|
|
533
|
+
if (!provider)
|
|
534
|
+
return;
|
|
535
|
+
if (this._trackedProviders.has(provider)) {
|
|
456
536
|
lib_1.logger.warn("TrackProvider: Provider already tracked.");
|
|
457
537
|
return;
|
|
458
538
|
}
|
|
459
|
-
this
|
|
460
|
-
this.
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
539
|
+
// Register listeners for this provider first
|
|
540
|
+
this.registerAccountsChangedListener(provider);
|
|
541
|
+
this.registerChainChangedListener(provider);
|
|
542
|
+
this.registerConnectListener(provider);
|
|
543
|
+
this.registerRequestListeners(provider);
|
|
544
|
+
this.registerDisconnectListener(provider);
|
|
545
|
+
// Only add to tracked providers after all listeners are successfully registered
|
|
546
|
+
this._trackedProviders.add(provider);
|
|
547
|
+
}
|
|
548
|
+
catch (error) {
|
|
549
|
+
lib_1.logger.error("Error tracking provider:", error);
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
FormoAnalytics.prototype.trackProviders = function (providers) {
|
|
553
|
+
try {
|
|
554
|
+
for (var _i = 0, providers_1 = providers; _i < providers_1.length; _i++) {
|
|
555
|
+
var eip6963ProviderDetail = providers_1[_i];
|
|
556
|
+
var provider = eip6963ProviderDetail === null || eip6963ProviderDetail === void 0 ? void 0 : eip6963ProviderDetail.provider;
|
|
557
|
+
if (provider && !this._trackedProviders.has(provider)) {
|
|
558
|
+
this.trackProvider(provider);
|
|
467
559
|
}
|
|
468
560
|
}
|
|
469
|
-
this._provider = provider;
|
|
470
|
-
// Register listeners for web3 provider events
|
|
471
|
-
this.registerAccountsChangedListener();
|
|
472
|
-
this.registerChainChangedListener();
|
|
473
|
-
this.registerConnectListener();
|
|
474
|
-
this.registerRequestListeners();
|
|
475
561
|
}
|
|
476
562
|
catch (error) {
|
|
477
|
-
lib_1.logger.error("
|
|
563
|
+
lib_1.logger.error("Failed to track EIP-6963 providers during initialization:", error);
|
|
478
564
|
}
|
|
479
565
|
};
|
|
480
|
-
FormoAnalytics.prototype.
|
|
566
|
+
FormoAnalytics.prototype.addProviderListener = function (provider, event, listener) {
|
|
567
|
+
var map = this._providerListenersMap.get(provider) || {};
|
|
568
|
+
map[event] = listener;
|
|
569
|
+
this._providerListenersMap.set(provider, map);
|
|
570
|
+
};
|
|
571
|
+
FormoAnalytics.prototype.registerAccountsChangedListener = function (provider) {
|
|
481
572
|
var _this = this;
|
|
482
|
-
var _a;
|
|
483
573
|
lib_1.logger.info("registerAccountsChangedListener");
|
|
484
574
|
var listener = function () {
|
|
485
575
|
var args = [];
|
|
486
576
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
487
577
|
args[_i] = arguments[_i];
|
|
488
578
|
}
|
|
489
|
-
return _this.onAccountsChanged(args[0]);
|
|
579
|
+
return _this.onAccountsChanged(provider, args[0]);
|
|
490
580
|
};
|
|
491
|
-
|
|
492
|
-
this.
|
|
581
|
+
provider.on("accountsChanged", listener);
|
|
582
|
+
this.addProviderListener(provider, "accountsChanged", listener);
|
|
493
583
|
};
|
|
494
|
-
FormoAnalytics.prototype.onAccountsChanged = function (accounts) {
|
|
584
|
+
FormoAnalytics.prototype.onAccountsChanged = function (provider, accounts) {
|
|
495
585
|
return __awaiter(this, void 0, void 0, function () {
|
|
496
|
-
var
|
|
497
|
-
|
|
498
|
-
|
|
586
|
+
var error_1, address, nextChainId, wasDisconnected, isProviderSwitch, hadPreviousConnection, error_2, providerInfo, effectiveChainId;
|
|
587
|
+
var _a, _b, _c;
|
|
588
|
+
return __generator(this, function (_d) {
|
|
589
|
+
switch (_d.label) {
|
|
499
590
|
case 0:
|
|
500
591
|
lib_1.logger.info("onAccountsChanged", accounts);
|
|
501
|
-
if (!(accounts.length === 0)) return [3 /*break*/,
|
|
502
|
-
|
|
503
|
-
|
|
592
|
+
if (!(accounts.length === 0)) return [3 /*break*/, 7];
|
|
593
|
+
if (!(this._provider === provider)) return [3 /*break*/, 5];
|
|
594
|
+
lib_1.logger.info("OnAccountsChanged: Detecting disconnect, current state:", {
|
|
595
|
+
currentAddress: this.currentAddress,
|
|
596
|
+
currentChainId: this.currentChainId,
|
|
597
|
+
providerMatch: this._provider === provider
|
|
598
|
+
});
|
|
599
|
+
_d.label = 1;
|
|
504
600
|
case 1:
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
return [
|
|
601
|
+
_d.trys.push([1, 3, , 4]);
|
|
602
|
+
// Pass current state explicitly to ensure we have the data for the disconnect event
|
|
603
|
+
return [4 /*yield*/, this.disconnect({
|
|
604
|
+
chainId: this.currentChainId,
|
|
605
|
+
address: this.currentAddress
|
|
606
|
+
})];
|
|
508
607
|
case 2:
|
|
509
|
-
|
|
510
|
-
|
|
608
|
+
// Pass current state explicitly to ensure we have the data for the disconnect event
|
|
609
|
+
_d.sent();
|
|
610
|
+
return [3 /*break*/, 4];
|
|
611
|
+
case 3:
|
|
612
|
+
error_1 = _d.sent();
|
|
613
|
+
lib_1.logger.error("Failed to disconnect provider on accountsChanged", error_1);
|
|
614
|
+
return [3 /*break*/, 4];
|
|
615
|
+
case 4: return [3 /*break*/, 6];
|
|
616
|
+
case 5:
|
|
617
|
+
lib_1.logger.info("OnAccountsChanged: Ignoring disconnect for non-active provider");
|
|
618
|
+
_d.label = 6;
|
|
619
|
+
case 6: return [2 /*return*/];
|
|
620
|
+
case 7:
|
|
621
|
+
address = this.validateAndChecksumAddress(accounts[0]);
|
|
622
|
+
if (!address) {
|
|
511
623
|
lib_1.logger.warn("onAccountsChanged: Invalid address received", accounts[0]);
|
|
512
624
|
return [2 /*return*/];
|
|
513
625
|
}
|
|
514
|
-
address
|
|
515
|
-
if (address === this.currentAddress) {
|
|
516
|
-
// We have already reported this address
|
|
626
|
+
// If both the provider and address are the same, no-op. Allow provider switches even if address is the same.
|
|
627
|
+
if (this._provider === provider && address === this.currentAddress) {
|
|
517
628
|
return [2 /*return*/];
|
|
518
629
|
}
|
|
519
|
-
|
|
630
|
+
return [4 /*yield*/, this.getCurrentChainId(provider)];
|
|
631
|
+
case 8:
|
|
632
|
+
nextChainId = _d.sent();
|
|
633
|
+
wasDisconnected = !this.currentAddress;
|
|
634
|
+
isProviderSwitch = this._provider && this._provider !== provider;
|
|
635
|
+
lib_1.logger.info("OnAccountsChanged: Provider switching analysis:", {
|
|
636
|
+
currentProvider: ((_b = (_a = this._provider) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name) || 'none',
|
|
637
|
+
newProvider: ((_c = provider === null || provider === void 0 ? void 0 : provider.constructor) === null || _c === void 0 ? void 0 : _c.name) || 'unknown',
|
|
638
|
+
currentAddress: this.currentAddress,
|
|
639
|
+
wasDisconnected: wasDisconnected,
|
|
640
|
+
isProviderMismatch: isProviderSwitch
|
|
641
|
+
});
|
|
642
|
+
if (!isProviderSwitch) return [3 /*break*/, 13];
|
|
643
|
+
hadPreviousConnection = !!this.currentAddress;
|
|
644
|
+
if (!hadPreviousConnection) return [3 /*break*/, 12];
|
|
645
|
+
lib_1.logger.info("OnAccountsChanged: Detected provider switch with existing connection - emitting disconnect for previous provider");
|
|
646
|
+
_d.label = 9;
|
|
647
|
+
case 9:
|
|
648
|
+
_d.trys.push([9, 11, , 12]);
|
|
649
|
+
return [4 /*yield*/, this.disconnect({
|
|
650
|
+
chainId: this.currentChainId,
|
|
651
|
+
address: this.currentAddress
|
|
652
|
+
})];
|
|
653
|
+
case 10:
|
|
654
|
+
_d.sent();
|
|
655
|
+
return [3 /*break*/, 12];
|
|
656
|
+
case 11:
|
|
657
|
+
error_2 = _d.sent();
|
|
658
|
+
lib_1.logger.error("Failed to emit disconnect during provider switch:", error_2);
|
|
659
|
+
return [3 /*break*/, 12];
|
|
660
|
+
case 12:
|
|
661
|
+
// Validate that the new provider is in a valid state before switching
|
|
662
|
+
if (this.isProviderInValidState(provider)) {
|
|
663
|
+
lib_1.logger.info("OnAccountsChanged: Handling provider mismatch - switching providers");
|
|
664
|
+
this.handleProviderMismatch(provider);
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
lib_1.logger.warn("Provider switching blocked: new provider is not in a valid state");
|
|
668
|
+
return [2 /*return*/];
|
|
669
|
+
}
|
|
670
|
+
_d.label = 13;
|
|
671
|
+
case 13:
|
|
672
|
+
// Commit new active provider and state
|
|
673
|
+
this._provider = provider;
|
|
520
674
|
this.currentAddress = address;
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
675
|
+
this.currentChainId = nextChainId;
|
|
676
|
+
providerInfo = this.getProviderInfo(provider);
|
|
677
|
+
lib_1.logger.info("OnAccountsChanged: Detected wallet connection, emitting connect event", {
|
|
678
|
+
chainId: nextChainId,
|
|
679
|
+
address: address,
|
|
680
|
+
wasDisconnected: wasDisconnected,
|
|
681
|
+
isProviderSwitch: isProviderSwitch,
|
|
682
|
+
providerName: providerInfo.name,
|
|
683
|
+
rdns: providerInfo.rdns,
|
|
684
|
+
hasChainId: !!nextChainId
|
|
685
|
+
});
|
|
686
|
+
effectiveChainId = nextChainId || 0;
|
|
687
|
+
if (effectiveChainId === 0) {
|
|
688
|
+
lib_1.logger.info("OnAccountsChanged: Using fallback chainId 0 for connect event");
|
|
689
|
+
}
|
|
690
|
+
this.connect({
|
|
691
|
+
chainId: effectiveChainId,
|
|
692
|
+
address: address
|
|
693
|
+
}, {
|
|
694
|
+
providerName: providerInfo.name,
|
|
695
|
+
rdns: providerInfo.rdns
|
|
696
|
+
}).catch(function (error) {
|
|
697
|
+
lib_1.logger.error("Failed to track connect event during account change:", error);
|
|
698
|
+
});
|
|
526
699
|
return [2 /*return*/];
|
|
527
700
|
}
|
|
528
701
|
});
|
|
529
702
|
});
|
|
530
703
|
};
|
|
531
|
-
FormoAnalytics.prototype.registerChainChangedListener = function () {
|
|
704
|
+
FormoAnalytics.prototype.registerChainChangedListener = function (provider) {
|
|
532
705
|
var _this = this;
|
|
533
|
-
var _a;
|
|
534
706
|
lib_1.logger.info("registerChainChangedListener");
|
|
535
707
|
var listener = function () {
|
|
536
708
|
var args = [];
|
|
537
709
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
538
710
|
args[_i] = arguments[_i];
|
|
539
711
|
}
|
|
540
|
-
return _this.onChainChanged(args[0]);
|
|
712
|
+
return _this.onChainChanged(provider, args[0]);
|
|
541
713
|
};
|
|
542
|
-
|
|
543
|
-
this.
|
|
714
|
+
provider.on("chainChanged", listener);
|
|
715
|
+
this.addProviderListener(provider, "chainChanged", listener);
|
|
544
716
|
};
|
|
545
|
-
FormoAnalytics.prototype.onChainChanged = function (chainIdHex) {
|
|
717
|
+
FormoAnalytics.prototype.onChainChanged = function (provider, chainIdHex) {
|
|
546
718
|
return __awaiter(this, void 0, void 0, function () {
|
|
547
|
-
var
|
|
719
|
+
var nextChainId;
|
|
548
720
|
return __generator(this, function (_a) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
return [2 /*return*/, Promise.resolve()];
|
|
564
|
-
}
|
|
565
|
-
validAddress = (0, address_1.getValidAddress)(address);
|
|
566
|
-
this.currentAddress = validAddress ? (0, utils_1.toChecksumAddress)(validAddress) : undefined;
|
|
567
|
-
_a.label = 2;
|
|
568
|
-
case 2:
|
|
569
|
-
// Proceed only if the address exists
|
|
570
|
-
if (this.currentAddress) {
|
|
571
|
-
return [2 /*return*/, this.chain({
|
|
572
|
-
chainId: this.currentChainId,
|
|
573
|
-
address: this.currentAddress,
|
|
574
|
-
})];
|
|
575
|
-
}
|
|
576
|
-
else {
|
|
577
|
-
lib_1.logger.info("OnChainChanged: Current connected address is null despite fetch attempt");
|
|
578
|
-
}
|
|
579
|
-
return [2 /*return*/];
|
|
721
|
+
lib_1.logger.info("onChainChanged", chainIdHex);
|
|
722
|
+
nextChainId = (0, chain_1.parseChainId)(chainIdHex);
|
|
723
|
+
// Only handle chain changes for the active provider (or if none is set yet)
|
|
724
|
+
if (this.isProviderMismatch(provider)) {
|
|
725
|
+
this.handleProviderMismatch(provider);
|
|
726
|
+
}
|
|
727
|
+
// Chain changes only matter for connected users
|
|
728
|
+
if (!this.currentAddress) {
|
|
729
|
+
lib_1.logger.info("OnChainChanged: No current address, user appears disconnected");
|
|
730
|
+
return [2 /*return*/, Promise.resolve()];
|
|
731
|
+
}
|
|
732
|
+
// Set provider if none exists
|
|
733
|
+
if (!this._provider) {
|
|
734
|
+
this._provider = provider;
|
|
580
735
|
}
|
|
736
|
+
this.currentChainId = nextChainId;
|
|
737
|
+
try {
|
|
738
|
+
// This is just a chain change since we already confirmed currentAddress exists
|
|
739
|
+
return [2 /*return*/, this.chain({
|
|
740
|
+
chainId: this.currentChainId,
|
|
741
|
+
address: this.currentAddress,
|
|
742
|
+
})];
|
|
743
|
+
}
|
|
744
|
+
catch (error) {
|
|
745
|
+
lib_1.logger.error("OnChainChanged: Failed to emit chain event:", error);
|
|
746
|
+
}
|
|
747
|
+
return [2 /*return*/];
|
|
581
748
|
});
|
|
582
749
|
});
|
|
583
750
|
};
|
|
584
|
-
FormoAnalytics.prototype.registerConnectListener = function () {
|
|
751
|
+
FormoAnalytics.prototype.registerConnectListener = function (provider) {
|
|
585
752
|
var _this = this;
|
|
586
|
-
var _a;
|
|
587
753
|
lib_1.logger.info("registerConnectListener");
|
|
588
754
|
var listener = function () {
|
|
589
755
|
var args = [];
|
|
@@ -591,14 +757,51 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
591
757
|
args[_i] = arguments[_i];
|
|
592
758
|
}
|
|
593
759
|
var connection = args[0];
|
|
594
|
-
_this.onConnected(connection);
|
|
760
|
+
_this.onConnected(provider, connection);
|
|
595
761
|
};
|
|
596
|
-
|
|
597
|
-
this.
|
|
762
|
+
provider.on("connect", listener);
|
|
763
|
+
this.addProviderListener(provider, "connect", listener);
|
|
764
|
+
};
|
|
765
|
+
FormoAnalytics.prototype.registerDisconnectListener = function (provider) {
|
|
766
|
+
var _this = this;
|
|
767
|
+
lib_1.logger.info("registerDisconnectListener");
|
|
768
|
+
var listener = function (_error) { return __awaiter(_this, void 0, void 0, function () {
|
|
769
|
+
var e_2;
|
|
770
|
+
return __generator(this, function (_a) {
|
|
771
|
+
switch (_a.label) {
|
|
772
|
+
case 0:
|
|
773
|
+
if (this._provider !== provider)
|
|
774
|
+
return [2 /*return*/];
|
|
775
|
+
lib_1.logger.info("OnDisconnect: Wallet disconnect event received, current state:", {
|
|
776
|
+
currentAddress: this.currentAddress,
|
|
777
|
+
currentChainId: this.currentChainId
|
|
778
|
+
});
|
|
779
|
+
_a.label = 1;
|
|
780
|
+
case 1:
|
|
781
|
+
_a.trys.push([1, 3, , 4]);
|
|
782
|
+
// Pass current state explicitly to ensure we have the data for the disconnect event
|
|
783
|
+
return [4 /*yield*/, this.disconnect({
|
|
784
|
+
chainId: this.currentChainId,
|
|
785
|
+
address: this.currentAddress
|
|
786
|
+
})];
|
|
787
|
+
case 2:
|
|
788
|
+
// Pass current state explicitly to ensure we have the data for the disconnect event
|
|
789
|
+
_a.sent();
|
|
790
|
+
return [3 /*break*/, 4];
|
|
791
|
+
case 3:
|
|
792
|
+
e_2 = _a.sent();
|
|
793
|
+
lib_1.logger.error("Error during disconnect in disconnect listener", e_2);
|
|
794
|
+
return [3 /*break*/, 4];
|
|
795
|
+
case 4: return [2 /*return*/];
|
|
796
|
+
}
|
|
797
|
+
});
|
|
798
|
+
}); };
|
|
799
|
+
provider.on("disconnect", listener);
|
|
800
|
+
this.addProviderListener(provider, "disconnect", listener);
|
|
598
801
|
};
|
|
599
|
-
FormoAnalytics.prototype.onConnected = function (connection) {
|
|
802
|
+
FormoAnalytics.prototype.onConnected = function (provider, connection) {
|
|
600
803
|
return __awaiter(this, void 0, void 0, function () {
|
|
601
|
-
var chainId, address,
|
|
804
|
+
var chainId, address, wasDisconnected, providerInfo, effectiveChainId, e_3;
|
|
602
805
|
return __generator(this, function (_a) {
|
|
603
806
|
switch (_a.label) {
|
|
604
807
|
case 0:
|
|
@@ -606,53 +809,91 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
606
809
|
_a.label = 1;
|
|
607
810
|
case 1:
|
|
608
811
|
_a.trys.push([1, 3, , 4]);
|
|
609
|
-
if (!connection || typeof connection.chainId !== 'string')
|
|
812
|
+
if (!(connection === null || connection === void 0 ? void 0 : connection.chainId) || typeof connection.chainId !== 'string')
|
|
610
813
|
return [2 /*return*/];
|
|
611
814
|
chainId = (0, chain_1.parseChainId)(connection.chainId);
|
|
612
|
-
return [4 /*yield*/, this.getAddress()];
|
|
815
|
+
return [4 /*yield*/, this.getAddress(provider)];
|
|
613
816
|
case 2:
|
|
614
817
|
address = _a.sent();
|
|
615
|
-
if (chainId
|
|
616
|
-
this.
|
|
818
|
+
if (chainId && address) {
|
|
819
|
+
wasDisconnected = !this.currentAddress;
|
|
820
|
+
// Set provider if none exists
|
|
821
|
+
if (!this._provider) {
|
|
822
|
+
this._provider = provider;
|
|
823
|
+
}
|
|
824
|
+
this.currentChainId = chainId;
|
|
825
|
+
this.currentAddress = this.validateAndChecksumAddress(address) || undefined;
|
|
826
|
+
// Always emit connect event for better analytics capture
|
|
827
|
+
if (this.currentAddress) {
|
|
828
|
+
providerInfo = this.getProviderInfo(provider);
|
|
829
|
+
lib_1.logger.info("OnConnected: Detected wallet connection, emitting connect event", {
|
|
830
|
+
chainId: chainId,
|
|
831
|
+
wasDisconnected: wasDisconnected,
|
|
832
|
+
providerName: providerInfo.name,
|
|
833
|
+
rdns: providerInfo.rdns,
|
|
834
|
+
hasChainId: !!chainId
|
|
835
|
+
});
|
|
836
|
+
effectiveChainId = chainId || 0;
|
|
837
|
+
if (effectiveChainId === 0) {
|
|
838
|
+
lib_1.logger.info("OnConnected: Using fallback chainId 0 for connect event");
|
|
839
|
+
}
|
|
840
|
+
this.connect({
|
|
841
|
+
chainId: effectiveChainId,
|
|
842
|
+
address: address
|
|
843
|
+
}, {
|
|
844
|
+
providerName: providerInfo.name,
|
|
845
|
+
rdns: providerInfo.rdns
|
|
846
|
+
}).catch(function (error) {
|
|
847
|
+
lib_1.logger.error("Failed to track connect event during provider connection:", error);
|
|
848
|
+
});
|
|
849
|
+
}
|
|
617
850
|
}
|
|
618
851
|
return [3 /*break*/, 4];
|
|
619
852
|
case 3:
|
|
620
|
-
|
|
621
|
-
lib_1.logger.error("Error handling connect event",
|
|
853
|
+
e_3 = _a.sent();
|
|
854
|
+
lib_1.logger.error("Error handling connect event", e_3);
|
|
622
855
|
return [3 /*break*/, 4];
|
|
623
856
|
case 4: return [2 /*return*/];
|
|
624
857
|
}
|
|
625
858
|
});
|
|
626
859
|
});
|
|
627
860
|
};
|
|
628
|
-
FormoAnalytics.prototype.registerRequestListeners = function () {
|
|
861
|
+
FormoAnalytics.prototype.registerRequestListeners = function (provider) {
|
|
629
862
|
var _this = this;
|
|
630
|
-
var _a;
|
|
631
863
|
lib_1.logger.info("registerRequestListeners");
|
|
632
|
-
if (!
|
|
864
|
+
if (!provider) {
|
|
633
865
|
lib_1.logger.error("Provider not found for request (signature, transaction) tracking");
|
|
634
866
|
return;
|
|
635
867
|
}
|
|
636
|
-
if
|
|
637
|
-
|
|
638
|
-
|
|
868
|
+
// Check if the provider is already wrapped with our SDK's wrapper
|
|
869
|
+
var currentRequest = provider.request;
|
|
870
|
+
if (this.isProviderAlreadyWrapped(provider, currentRequest)) {
|
|
871
|
+
lib_1.logger.info("Provider already wrapped with our SDK; skipping request wrapping.");
|
|
639
872
|
return;
|
|
640
873
|
}
|
|
641
|
-
var request =
|
|
642
|
-
|
|
643
|
-
var response_1,
|
|
874
|
+
var request = provider.request.bind(provider);
|
|
875
|
+
var wrappedRequest = function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
|
|
876
|
+
var capturedChainId_1, _c, response_1, error_3, rpcError, transactionHash_1, error_4, rpcError;
|
|
644
877
|
var _this = this;
|
|
645
878
|
var method = _b.method, params = _b.params;
|
|
646
|
-
return __generator(this, function (
|
|
647
|
-
switch (
|
|
879
|
+
return __generator(this, function (_d) {
|
|
880
|
+
switch (_d.label) {
|
|
648
881
|
case 0:
|
|
649
882
|
if (!(Array.isArray(params) &&
|
|
650
|
-
["eth_signTypedData_v4", "personal_sign"].includes(method))) return [3 /*break*/,
|
|
883
|
+
["eth_signTypedData_v4", "personal_sign"].includes(method))) return [3 /*break*/, 6];
|
|
884
|
+
_c = this.currentChainId;
|
|
885
|
+
if (_c) return [3 /*break*/, 2];
|
|
886
|
+
return [4 /*yield*/, this.getCurrentChainId(provider)];
|
|
887
|
+
case 1:
|
|
888
|
+
_c = (_d.sent());
|
|
889
|
+
_d.label = 2;
|
|
890
|
+
case 2:
|
|
891
|
+
capturedChainId_1 = _c;
|
|
651
892
|
// Fire-and-forget tracking
|
|
652
893
|
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
653
894
|
return __generator(this, function (_a) {
|
|
654
895
|
try {
|
|
655
|
-
this.signature(__assign({ status: types_1.SignatureStatus.REQUESTED }, this.buildSignatureEventPayload(method, params)));
|
|
896
|
+
this.signature(__assign({ status: types_1.SignatureStatus.REQUESTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1)));
|
|
656
897
|
}
|
|
657
898
|
catch (e) {
|
|
658
899
|
lib_1.logger.error("Formo: Failed to track signature request", e);
|
|
@@ -660,127 +901,139 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
660
901
|
return [2 /*return*/];
|
|
661
902
|
});
|
|
662
903
|
}); })();
|
|
663
|
-
|
|
664
|
-
case
|
|
665
|
-
|
|
904
|
+
_d.label = 3;
|
|
905
|
+
case 3:
|
|
906
|
+
_d.trys.push([3, 5, , 6]);
|
|
666
907
|
return [4 /*yield*/, request({ method: method, params: params })];
|
|
667
|
-
case
|
|
668
|
-
response_1 = (
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
908
|
+
case 4:
|
|
909
|
+
response_1 = (_d.sent());
|
|
910
|
+
// Track signature confirmation only for truthy responses
|
|
911
|
+
if (response_1) {
|
|
912
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
913
|
+
return __generator(this, function (_a) {
|
|
914
|
+
try {
|
|
915
|
+
this.signature(__assign({ status: types_1.SignatureStatus.CONFIRMED }, this.buildSignatureEventPayload(method, params, response_1, capturedChainId_1)));
|
|
674
916
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
});
|
|
681
|
-
}
|
|
917
|
+
catch (e) {
|
|
918
|
+
lib_1.logger.error("Formo: Failed to track signature confirmation", e);
|
|
919
|
+
}
|
|
920
|
+
return [2 /*return*/];
|
|
921
|
+
});
|
|
922
|
+
}); })();
|
|
923
|
+
}
|
|
682
924
|
return [2 /*return*/, response_1];
|
|
683
|
-
case
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
this.signature(__assign({ status: types_1.SignatureStatus.REJECTED }, this.buildSignatureEventPayload(method, params)));
|
|
925
|
+
case 5:
|
|
926
|
+
error_3 = _d.sent();
|
|
927
|
+
rpcError = error_3;
|
|
928
|
+
if ((rpcError === null || rpcError === void 0 ? void 0 : rpcError.code) === 4001) {
|
|
929
|
+
// Use the already cast rpcError to avoid duplication
|
|
930
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
931
|
+
return __generator(this, function (_a) {
|
|
932
|
+
try {
|
|
933
|
+
this.signature(__assign({ status: types_1.SignatureStatus.REJECTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1)));
|
|
692
934
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
throw
|
|
701
|
-
case
|
|
935
|
+
catch (e) {
|
|
936
|
+
lib_1.logger.error("Formo: Failed to track signature rejection", e);
|
|
937
|
+
}
|
|
938
|
+
return [2 /*return*/];
|
|
939
|
+
});
|
|
940
|
+
}); })();
|
|
941
|
+
}
|
|
942
|
+
throw error_3;
|
|
943
|
+
case 6:
|
|
702
944
|
if (!(Array.isArray(params) &&
|
|
703
945
|
method === "eth_sendTransaction" &&
|
|
704
|
-
params[0])) return [3 /*break*/,
|
|
946
|
+
params[0])) return [3 /*break*/, 10];
|
|
705
947
|
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
706
|
-
var payload,
|
|
948
|
+
var payload, e_4;
|
|
707
949
|
return __generator(this, function (_a) {
|
|
708
950
|
switch (_a.label) {
|
|
709
951
|
case 0:
|
|
710
952
|
_a.trys.push([0, 2, , 3]);
|
|
711
|
-
return [4 /*yield*/, this.buildTransactionEventPayload(params)];
|
|
953
|
+
return [4 /*yield*/, this.buildTransactionEventPayload(params, provider)];
|
|
712
954
|
case 1:
|
|
713
955
|
payload = _a.sent();
|
|
714
956
|
this.transaction(__assign({ status: types_1.TransactionStatus.STARTED }, payload));
|
|
715
957
|
return [3 /*break*/, 3];
|
|
716
958
|
case 2:
|
|
717
|
-
|
|
718
|
-
lib_1.logger.error("Formo: Failed to track transaction start",
|
|
959
|
+
e_4 = _a.sent();
|
|
960
|
+
lib_1.logger.error("Formo: Failed to track transaction start", e_4);
|
|
719
961
|
return [3 /*break*/, 3];
|
|
720
962
|
case 3: return [2 /*return*/];
|
|
721
963
|
}
|
|
722
964
|
});
|
|
723
965
|
}); })();
|
|
724
|
-
|
|
725
|
-
case
|
|
726
|
-
|
|
966
|
+
_d.label = 7;
|
|
967
|
+
case 7:
|
|
968
|
+
_d.trys.push([7, 9, , 10]);
|
|
727
969
|
return [4 /*yield*/, request({
|
|
728
970
|
method: method,
|
|
729
971
|
params: params,
|
|
730
972
|
})];
|
|
731
|
-
case
|
|
732
|
-
transactionHash_1 = (
|
|
973
|
+
case 8:
|
|
974
|
+
transactionHash_1 = (_d.sent());
|
|
733
975
|
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
734
|
-
var payload,
|
|
976
|
+
var payload, e_5;
|
|
735
977
|
return __generator(this, function (_a) {
|
|
736
978
|
switch (_a.label) {
|
|
737
979
|
case 0:
|
|
738
980
|
_a.trys.push([0, 2, , 3]);
|
|
739
|
-
return [4 /*yield*/, this.buildTransactionEventPayload(params)];
|
|
981
|
+
return [4 /*yield*/, this.buildTransactionEventPayload(params, provider)];
|
|
740
982
|
case 1:
|
|
741
983
|
payload = _a.sent();
|
|
742
984
|
this.transaction(__assign(__assign({ status: types_1.TransactionStatus.BROADCASTED }, payload), { transactionHash: transactionHash_1 }));
|
|
743
985
|
// Start async polling for transaction receipt
|
|
744
|
-
this.pollTransactionReceipt(transactionHash_1, payload);
|
|
986
|
+
this.pollTransactionReceipt(provider, transactionHash_1, payload);
|
|
745
987
|
return [3 /*break*/, 3];
|
|
746
988
|
case 2:
|
|
747
|
-
|
|
748
|
-
lib_1.logger.error("Formo: Failed to track transaction broadcast",
|
|
989
|
+
e_5 = _a.sent();
|
|
990
|
+
lib_1.logger.error("Formo: Failed to track transaction broadcast", e_5);
|
|
749
991
|
return [3 /*break*/, 3];
|
|
750
992
|
case 3: return [2 /*return*/];
|
|
751
993
|
}
|
|
752
994
|
});
|
|
753
995
|
}); })();
|
|
754
996
|
return [2 /*return*/, transactionHash_1];
|
|
755
|
-
case
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
997
|
+
case 9:
|
|
998
|
+
error_4 = _d.sent();
|
|
999
|
+
rpcError = error_4;
|
|
1000
|
+
if ((rpcError === null || rpcError === void 0 ? void 0 : rpcError.code) === 4001) {
|
|
1001
|
+
// Use the already cast rpcError to avoid duplication
|
|
1002
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1003
|
+
var payload, e_6;
|
|
1004
|
+
return __generator(this, function (_a) {
|
|
1005
|
+
switch (_a.label) {
|
|
1006
|
+
case 0:
|
|
1007
|
+
_a.trys.push([0, 2, , 3]);
|
|
1008
|
+
return [4 /*yield*/, this.buildTransactionEventPayload(params, provider)];
|
|
1009
|
+
case 1:
|
|
1010
|
+
payload = _a.sent();
|
|
1011
|
+
this.transaction(__assign({ status: types_1.TransactionStatus.REJECTED }, payload));
|
|
1012
|
+
return [3 /*break*/, 3];
|
|
1013
|
+
case 2:
|
|
1014
|
+
e_6 = _a.sent();
|
|
1015
|
+
lib_1.logger.error("Formo: Failed to track transaction rejection", e_6);
|
|
1016
|
+
return [3 /*break*/, 3];
|
|
1017
|
+
case 3: return [2 /*return*/];
|
|
1018
|
+
}
|
|
1019
|
+
});
|
|
1020
|
+
}); })();
|
|
1021
|
+
}
|
|
1022
|
+
throw error_4;
|
|
1023
|
+
case 10: return [2 /*return*/, request({ method: method, params: params })];
|
|
781
1024
|
}
|
|
782
1025
|
});
|
|
783
1026
|
}); };
|
|
1027
|
+
// Mark the wrapper so we can detect if request is replaced externally and keep a reference on provider
|
|
1028
|
+
wrappedRequest[types_1.WRAPPED_REQUEST_SYMBOL] = true;
|
|
1029
|
+
provider[types_1.WRAPPED_REQUEST_REF_SYMBOL] = wrappedRequest;
|
|
1030
|
+
try {
|
|
1031
|
+
// Attempt to assign the wrapped request function (rely on try-catch for mutability errors)
|
|
1032
|
+
provider.request = wrappedRequest;
|
|
1033
|
+
}
|
|
1034
|
+
catch (e) {
|
|
1035
|
+
lib_1.logger.warn("Failed to wrap provider.request; skipping", e);
|
|
1036
|
+
}
|
|
784
1037
|
};
|
|
785
1038
|
FormoAnalytics.prototype.onLocationChange = function () {
|
|
786
1039
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -834,15 +1087,29 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
834
1087
|
lib_1.logger.info("Track page hit: Skipping event due to tracking configuration");
|
|
835
1088
|
return [2 /*return*/];
|
|
836
1089
|
}
|
|
837
|
-
setTimeout(function () {
|
|
838
|
-
return
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
1090
|
+
setTimeout(function () {
|
|
1091
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1092
|
+
var e_7;
|
|
1093
|
+
return __generator(this, function (_a) {
|
|
1094
|
+
switch (_a.label) {
|
|
1095
|
+
case 0:
|
|
1096
|
+
_a.trys.push([0, 2, , 3]);
|
|
1097
|
+
return [4 /*yield*/, this.trackEvent(constants_1.EventType.PAGE, {
|
|
1098
|
+
category: category,
|
|
1099
|
+
name: name,
|
|
1100
|
+
}, properties, context, callback)];
|
|
1101
|
+
case 1:
|
|
1102
|
+
_a.sent();
|
|
1103
|
+
return [3 /*break*/, 3];
|
|
1104
|
+
case 2:
|
|
1105
|
+
e_7 = _a.sent();
|
|
1106
|
+
lib_1.logger.error("Formo: Failed to track page hit", e_7);
|
|
1107
|
+
return [3 /*break*/, 3];
|
|
1108
|
+
case 3: return [2 /*return*/];
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
}); })();
|
|
1112
|
+
}, 300);
|
|
846
1113
|
return [2 /*return*/];
|
|
847
1114
|
});
|
|
848
1115
|
});
|
|
@@ -907,24 +1174,167 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
907
1174
|
/*
|
|
908
1175
|
Utility functions
|
|
909
1176
|
*/
|
|
1177
|
+
/**
|
|
1178
|
+
* Get provider information for a given provider
|
|
1179
|
+
* @param provider The provider to get info for
|
|
1180
|
+
* @returns Provider information
|
|
1181
|
+
*/
|
|
1182
|
+
FormoAnalytics.prototype.getProviderInfo = function (provider) {
|
|
1183
|
+
// First check if provider is in our EIP-6963 providers list
|
|
1184
|
+
var eip6963Provider = this._providers.find(function (p) { return p.provider === provider; });
|
|
1185
|
+
if (eip6963Provider) {
|
|
1186
|
+
return {
|
|
1187
|
+
name: eip6963Provider.info.name,
|
|
1188
|
+
rdns: eip6963Provider.info.rdns
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
// Fallback to injected provider detection
|
|
1192
|
+
var injectedInfo = this.detectInjectedProviderInfo(provider);
|
|
1193
|
+
return {
|
|
1194
|
+
name: injectedInfo.name,
|
|
1195
|
+
rdns: injectedInfo.rdns
|
|
1196
|
+
};
|
|
1197
|
+
};
|
|
1198
|
+
/**
|
|
1199
|
+
* Attempts to detect information about an injected provider
|
|
1200
|
+
* @param provider The injected provider to analyze
|
|
1201
|
+
* @returns Provider information with fallback values
|
|
1202
|
+
*/
|
|
1203
|
+
FormoAnalytics.prototype.detectInjectedProviderInfo = function (provider) {
|
|
1204
|
+
// Try to detect provider type from common properties
|
|
1205
|
+
var name = 'Injected Provider';
|
|
1206
|
+
var rdns = 'io.injected.provider';
|
|
1207
|
+
// Use WalletProviderFlags interface for type safety
|
|
1208
|
+
var flags = provider;
|
|
1209
|
+
// Check if it's MetaMask
|
|
1210
|
+
if (flags.isMetaMask) {
|
|
1211
|
+
name = 'MetaMask';
|
|
1212
|
+
rdns = 'io.metamask';
|
|
1213
|
+
}
|
|
1214
|
+
// Check if it's Coinbase Wallet
|
|
1215
|
+
else if (flags.isCoinbaseWallet) {
|
|
1216
|
+
name = 'Coinbase Wallet';
|
|
1217
|
+
rdns = 'com.coinbase.wallet';
|
|
1218
|
+
}
|
|
1219
|
+
// Check if it's WalletConnect
|
|
1220
|
+
else if (flags.isWalletConnect) {
|
|
1221
|
+
name = 'WalletConnect';
|
|
1222
|
+
rdns = 'com.walletconnect';
|
|
1223
|
+
}
|
|
1224
|
+
// Check if it's Trust Wallet
|
|
1225
|
+
else if (flags.isTrust) {
|
|
1226
|
+
name = 'Trust Wallet';
|
|
1227
|
+
rdns = 'com.trustwallet';
|
|
1228
|
+
}
|
|
1229
|
+
// Check if it's Brave Wallet
|
|
1230
|
+
else if (flags.isBraveWallet) {
|
|
1231
|
+
name = 'Brave Wallet';
|
|
1232
|
+
rdns = 'com.brave.wallet';
|
|
1233
|
+
}
|
|
1234
|
+
// Check if it's Phantom
|
|
1235
|
+
else if (flags.isPhantom) {
|
|
1236
|
+
name = 'Phantom';
|
|
1237
|
+
rdns = 'app.phantom';
|
|
1238
|
+
}
|
|
1239
|
+
return {
|
|
1240
|
+
name: name,
|
|
1241
|
+
rdns: rdns,
|
|
1242
|
+
uuid: "injected-".concat(rdns.replace(/[^a-zA-Z0-9]/g, '-')),
|
|
1243
|
+
icon: constants_1.DEFAULT_PROVIDER_ICON
|
|
1244
|
+
};
|
|
1245
|
+
};
|
|
910
1246
|
FormoAnalytics.prototype.getProviders = function () {
|
|
911
1247
|
return __awaiter(this, void 0, void 0, function () {
|
|
912
|
-
var store, providers;
|
|
1248
|
+
var store, providers, injected_1, injectedProviderInfo, injectedDetail, uniqueProviders, _i, uniqueProviders_1, detail;
|
|
913
1249
|
var _this = this;
|
|
914
1250
|
return __generator(this, function (_a) {
|
|
915
1251
|
store = (0, mipd_1.createStore)();
|
|
916
1252
|
providers = store.getProviders();
|
|
917
1253
|
store.subscribe(function (providerDetails) {
|
|
918
1254
|
providers = providerDetails;
|
|
919
|
-
|
|
1255
|
+
// Process newly added providers with proper deduplication
|
|
1256
|
+
var newlyAddedDetails = providerDetails.filter(function (detail) {
|
|
1257
|
+
var provider = detail === null || detail === void 0 ? void 0 : detail.provider;
|
|
1258
|
+
return provider && !_this._seenProviders.has(provider);
|
|
1259
|
+
});
|
|
1260
|
+
// Add new providers to the array without overwriting existing ones
|
|
1261
|
+
for (var _i = 0, newlyAddedDetails_1 = newlyAddedDetails; _i < newlyAddedDetails_1.length; _i++) {
|
|
1262
|
+
var detail = newlyAddedDetails_1[_i];
|
|
1263
|
+
_this.safeAddProviderDetail(detail);
|
|
1264
|
+
}
|
|
1265
|
+
// Track listeners for newly discovered providers only
|
|
1266
|
+
var newDetails = providerDetails.filter(function (detail) {
|
|
1267
|
+
var p = detail === null || detail === void 0 ? void 0 : detail.provider;
|
|
1268
|
+
return !!p && !_this._trackedProviders.has(p);
|
|
1269
|
+
});
|
|
1270
|
+
if (newDetails.length > 0) {
|
|
1271
|
+
_this.trackProviders(newDetails);
|
|
1272
|
+
// Detect newly discovered wallets (session de-dupes) with error handling
|
|
1273
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1274
|
+
var e_8;
|
|
1275
|
+
return __generator(this, function (_a) {
|
|
1276
|
+
switch (_a.label) {
|
|
1277
|
+
case 0:
|
|
1278
|
+
_a.trys.push([0, 2, , 3]);
|
|
1279
|
+
return [4 /*yield*/, this.detectWallets(newDetails)];
|
|
1280
|
+
case 1:
|
|
1281
|
+
_a.sent();
|
|
1282
|
+
return [3 /*break*/, 3];
|
|
1283
|
+
case 2:
|
|
1284
|
+
e_8 = _a.sent();
|
|
1285
|
+
lib_1.logger.error("Formo: Failed to detect wallets", e_8);
|
|
1286
|
+
return [3 /*break*/, 3];
|
|
1287
|
+
case 3: return [2 /*return*/];
|
|
1288
|
+
}
|
|
1289
|
+
});
|
|
1290
|
+
}); })();
|
|
1291
|
+
}
|
|
1292
|
+
// Clean up providers that are no longer available
|
|
1293
|
+
_this.cleanupUnavailableProviders();
|
|
920
1294
|
});
|
|
921
1295
|
// Fallback to injected provider if no providers are found
|
|
922
1296
|
if (providers.length === 0) {
|
|
923
|
-
|
|
1297
|
+
injected_1 = typeof window !== 'undefined' ? window.ethereum : undefined;
|
|
1298
|
+
if (injected_1) {
|
|
1299
|
+
// If we have already detected and cached the injected provider, and it's the same instance, return the cached result
|
|
1300
|
+
if (this._injectedProviderDetail &&
|
|
1301
|
+
this._injectedProviderDetail.provider === injected_1) {
|
|
1302
|
+
// Ensure it's tracked
|
|
1303
|
+
if (!this._trackedProviders.has(injected_1)) {
|
|
1304
|
+
this.trackProvider(injected_1);
|
|
1305
|
+
}
|
|
1306
|
+
// Merge with existing providers instead of overwriting
|
|
1307
|
+
if (!this._providers.some(function (existing) { return existing.provider === injected_1; })) {
|
|
1308
|
+
this._providers = __spreadArray(__spreadArray([], this._providers, true), [this._injectedProviderDetail], false);
|
|
1309
|
+
}
|
|
1310
|
+
return [2 /*return*/, this._providers];
|
|
1311
|
+
}
|
|
1312
|
+
// Re-check if the injected provider is already tracked just before tracking
|
|
1313
|
+
if (!this._trackedProviders.has(injected_1)) {
|
|
1314
|
+
this.trackProvider(injected_1);
|
|
1315
|
+
}
|
|
1316
|
+
injectedProviderInfo = this.detectInjectedProviderInfo(injected_1);
|
|
1317
|
+
injectedDetail = {
|
|
1318
|
+
provider: injected_1,
|
|
1319
|
+
info: injectedProviderInfo
|
|
1320
|
+
};
|
|
1321
|
+
// Cache the detected injected provider detail
|
|
1322
|
+
this._injectedProviderDetail = injectedDetail;
|
|
1323
|
+
// Merge with existing providers instead of overwriting
|
|
1324
|
+
this.safeAddProviderDetail(injectedDetail);
|
|
1325
|
+
}
|
|
924
1326
|
return [2 /*return*/, this._providers];
|
|
925
1327
|
}
|
|
926
|
-
|
|
927
|
-
|
|
1328
|
+
uniqueProviders = providers.filter(function (detail) {
|
|
1329
|
+
var provider = detail === null || detail === void 0 ? void 0 : detail.provider;
|
|
1330
|
+
return provider && !_this._seenProviders.has(provider);
|
|
1331
|
+
});
|
|
1332
|
+
// Add to seen providers and instances, ensuring no duplicates in _providers
|
|
1333
|
+
for (_i = 0, uniqueProviders_1 = uniqueProviders; _i < uniqueProviders_1.length; _i++) {
|
|
1334
|
+
detail = uniqueProviders_1[_i];
|
|
1335
|
+
this.safeAddProviderDetail(detail);
|
|
1336
|
+
}
|
|
1337
|
+
return [2 /*return*/, this._providers];
|
|
928
1338
|
});
|
|
929
1339
|
});
|
|
930
1340
|
};
|
|
@@ -937,16 +1347,16 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
937
1347
|
});
|
|
938
1348
|
FormoAnalytics.prototype.detectWallets = function (providers) {
|
|
939
1349
|
return __awaiter(this, void 0, void 0, function () {
|
|
940
|
-
var _i,
|
|
1350
|
+
var _i, providers_2, eip6963ProviderDetail, err_2;
|
|
941
1351
|
return __generator(this, function (_a) {
|
|
942
1352
|
switch (_a.label) {
|
|
943
1353
|
case 0:
|
|
944
1354
|
_a.trys.push([0, 5, , 6]);
|
|
945
|
-
_i = 0,
|
|
1355
|
+
_i = 0, providers_2 = providers;
|
|
946
1356
|
_a.label = 1;
|
|
947
1357
|
case 1:
|
|
948
|
-
if (!(_i <
|
|
949
|
-
eip6963ProviderDetail =
|
|
1358
|
+
if (!(_i < providers_2.length)) return [3 /*break*/, 4];
|
|
1359
|
+
eip6963ProviderDetail = providers_2[_i];
|
|
950
1360
|
return [4 /*yield*/, this.detect({
|
|
951
1361
|
providerName: eip6963ProviderDetail === null || eip6963ProviderDetail === void 0 ? void 0 : eip6963ProviderDetail.info.name,
|
|
952
1362
|
rdns: eip6963ProviderDetail === null || eip6963ProviderDetail === void 0 ? void 0 : eip6963ProviderDetail.info.rdns,
|
|
@@ -976,7 +1386,7 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
976
1386
|
});
|
|
977
1387
|
FormoAnalytics.prototype.getAddress = function (provider) {
|
|
978
1388
|
return __awaiter(this, void 0, void 0, function () {
|
|
979
|
-
var p, accounts,
|
|
1389
|
+
var p, accounts, err_3, code;
|
|
980
1390
|
return __generator(this, function (_a) {
|
|
981
1391
|
switch (_a.label) {
|
|
982
1392
|
case 0:
|
|
@@ -994,15 +1404,15 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
994
1404
|
case 2:
|
|
995
1405
|
accounts = _a.sent();
|
|
996
1406
|
if (accounts && accounts.length > 0) {
|
|
997
|
-
|
|
998
|
-
if (validAddress) {
|
|
999
|
-
return [2 /*return*/, (0, utils_1.toChecksumAddress)(validAddress)];
|
|
1000
|
-
}
|
|
1407
|
+
return [2 /*return*/, this.validateAndChecksumAddress(accounts[0]) || null];
|
|
1001
1408
|
}
|
|
1002
1409
|
return [3 /*break*/, 4];
|
|
1003
1410
|
case 3:
|
|
1004
1411
|
err_3 = _a.sent();
|
|
1005
|
-
|
|
1412
|
+
code = err_3 === null || err_3 === void 0 ? void 0 : err_3.code;
|
|
1413
|
+
if (code !== 4001) {
|
|
1414
|
+
lib_1.logger.error("FormoAnalytics::getAccounts: eth_accounts threw an error", err_3);
|
|
1415
|
+
}
|
|
1006
1416
|
return [2 /*return*/, null];
|
|
1007
1417
|
case 4: return [2 /*return*/, null];
|
|
1008
1418
|
}
|
|
@@ -1011,7 +1421,8 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1011
1421
|
};
|
|
1012
1422
|
FormoAnalytics.prototype.getAccounts = function (provider) {
|
|
1013
1423
|
return __awaiter(this, void 0, void 0, function () {
|
|
1014
|
-
var p, res, err_4;
|
|
1424
|
+
var p, res, err_4, code;
|
|
1425
|
+
var _this = this;
|
|
1015
1426
|
return __generator(this, function (_a) {
|
|
1016
1427
|
switch (_a.label) {
|
|
1017
1428
|
case 0:
|
|
@@ -1027,12 +1438,12 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1027
1438
|
if (!res || res.length === 0)
|
|
1028
1439
|
return [2 /*return*/, null];
|
|
1029
1440
|
return [2 /*return*/, res
|
|
1030
|
-
.map(function (e) { return
|
|
1031
|
-
.filter(function (e) { return e !==
|
|
1032
|
-
.map(utils_1.toChecksumAddress)];
|
|
1441
|
+
.map(function (e) { return _this.validateAndChecksumAddress(e); })
|
|
1442
|
+
.filter(function (e) { return e !== undefined; })];
|
|
1033
1443
|
case 3:
|
|
1034
1444
|
err_4 = _a.sent();
|
|
1035
|
-
|
|
1445
|
+
code = err_4 === null || err_4 === void 0 ? void 0 : err_4.code;
|
|
1446
|
+
if (code !== 4001) {
|
|
1036
1447
|
lib_1.logger.error("FormoAnalytics::getAccounts: eth_accounts threw an error", err_4);
|
|
1037
1448
|
}
|
|
1038
1449
|
return [2 /*return*/, null];
|
|
@@ -1041,31 +1452,32 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1041
1452
|
});
|
|
1042
1453
|
});
|
|
1043
1454
|
};
|
|
1044
|
-
FormoAnalytics.prototype.getCurrentChainId = function () {
|
|
1455
|
+
FormoAnalytics.prototype.getCurrentChainId = function (provider) {
|
|
1045
1456
|
return __awaiter(this, void 0, void 0, function () {
|
|
1046
|
-
var chainIdHex, err_5;
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
switch (_b.label) {
|
|
1457
|
+
var p, chainIdHex, err_5;
|
|
1458
|
+
return __generator(this, function (_a) {
|
|
1459
|
+
switch (_a.label) {
|
|
1050
1460
|
case 0:
|
|
1051
|
-
|
|
1461
|
+
p = provider || this.provider;
|
|
1462
|
+
if (!p) {
|
|
1052
1463
|
lib_1.logger.error("Provider not set for chain ID");
|
|
1464
|
+
return [2 /*return*/, 0];
|
|
1053
1465
|
}
|
|
1054
|
-
|
|
1466
|
+
_a.label = 1;
|
|
1055
1467
|
case 1:
|
|
1056
|
-
|
|
1057
|
-
return [4 /*yield*/,
|
|
1468
|
+
_a.trys.push([1, 3, , 4]);
|
|
1469
|
+
return [4 /*yield*/, p.request({
|
|
1058
1470
|
method: "eth_chainId",
|
|
1059
|
-
})
|
|
1471
|
+
})];
|
|
1060
1472
|
case 2:
|
|
1061
|
-
chainIdHex =
|
|
1473
|
+
chainIdHex = _a.sent();
|
|
1062
1474
|
if (!chainIdHex) {
|
|
1063
1475
|
lib_1.logger.info("Chain id not found");
|
|
1064
1476
|
return [2 /*return*/, 0];
|
|
1065
1477
|
}
|
|
1066
1478
|
return [2 /*return*/, (0, chain_1.parseChainId)(chainIdHex)];
|
|
1067
1479
|
case 3:
|
|
1068
|
-
err_5 =
|
|
1480
|
+
err_5 = _a.sent();
|
|
1069
1481
|
lib_1.logger.error("eth_chainId threw an error:", err_5);
|
|
1070
1482
|
return [2 /*return*/, 0];
|
|
1071
1483
|
case 4: return [2 /*return*/];
|
|
@@ -1073,17 +1485,18 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1073
1485
|
});
|
|
1074
1486
|
});
|
|
1075
1487
|
};
|
|
1076
|
-
FormoAnalytics.prototype.buildSignatureEventPayload = function (method, params, response) {
|
|
1488
|
+
FormoAnalytics.prototype.buildSignatureEventPayload = function (method, params, response, chainId) {
|
|
1489
|
+
var _a;
|
|
1077
1490
|
var rawAddress = method === "personal_sign"
|
|
1078
1491
|
? params[1]
|
|
1079
1492
|
: params[0];
|
|
1080
|
-
var validAddress =
|
|
1493
|
+
var validAddress = this.validateAndChecksumAddress(rawAddress);
|
|
1081
1494
|
if (!validAddress) {
|
|
1082
1495
|
throw new Error("Invalid address in signature payload: ".concat(rawAddress));
|
|
1083
1496
|
}
|
|
1084
1497
|
var basePayload = {
|
|
1085
|
-
chainId: this.currentChainId,
|
|
1086
|
-
address:
|
|
1498
|
+
chainId: (_a = chainId !== null && chainId !== void 0 ? chainId : this.currentChainId) !== null && _a !== void 0 ? _a : undefined,
|
|
1499
|
+
address: validAddress,
|
|
1087
1500
|
};
|
|
1088
1501
|
if (method === "personal_sign") {
|
|
1089
1502
|
var message = Buffer.from(params[0].slice(2), "hex").toString("utf8");
|
|
@@ -1091,7 +1504,7 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1091
1504
|
}
|
|
1092
1505
|
return __assign(__assign(__assign({}, basePayload), { message: params[1] }), (response ? { signatureHash: response } : {}));
|
|
1093
1506
|
};
|
|
1094
|
-
FormoAnalytics.prototype.buildTransactionEventPayload = function (params) {
|
|
1507
|
+
FormoAnalytics.prototype.buildTransactionEventPayload = function (params, provider) {
|
|
1095
1508
|
return __awaiter(this, void 0, void 0, function () {
|
|
1096
1509
|
var _a, data, from, to, value, validAddress, _b;
|
|
1097
1510
|
var _c;
|
|
@@ -1099,20 +1512,20 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1099
1512
|
switch (_d.label) {
|
|
1100
1513
|
case 0:
|
|
1101
1514
|
_a = params[0], data = _a.data, from = _a.from, to = _a.to, value = _a.value;
|
|
1102
|
-
validAddress =
|
|
1515
|
+
validAddress = this.validateAndChecksumAddress(from);
|
|
1103
1516
|
if (!validAddress) {
|
|
1104
1517
|
throw new Error("Invalid address in transaction payload: ".concat(from));
|
|
1105
1518
|
}
|
|
1106
1519
|
_c = {};
|
|
1107
1520
|
_b = this.currentChainId;
|
|
1108
1521
|
if (_b) return [3 /*break*/, 2];
|
|
1109
|
-
return [4 /*yield*/, this.getCurrentChainId()];
|
|
1522
|
+
return [4 /*yield*/, this.getCurrentChainId(provider)];
|
|
1110
1523
|
case 1:
|
|
1111
1524
|
_b = (_d.sent());
|
|
1112
1525
|
_d.label = 2;
|
|
1113
1526
|
case 2: return [2 /*return*/, (_c.chainId = _b,
|
|
1114
1527
|
_c.data = data,
|
|
1115
|
-
_c.address =
|
|
1528
|
+
_c.address = validAddress,
|
|
1116
1529
|
_c.to = to,
|
|
1117
1530
|
_c.value = value,
|
|
1118
1531
|
_c)];
|
|
@@ -1123,19 +1536,18 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1123
1536
|
/**
|
|
1124
1537
|
* Polls for transaction receipt and emits tx.status = CONFIRMED or REVERTED.
|
|
1125
1538
|
*/
|
|
1126
|
-
FormoAnalytics.prototype.pollTransactionReceipt = function (transactionHash_2, payload_1) {
|
|
1127
|
-
return __awaiter(this, arguments, void 0, function (transactionHash, payload, maxAttempts, intervalMs) {
|
|
1128
|
-
var attempts,
|
|
1539
|
+
FormoAnalytics.prototype.pollTransactionReceipt = function (provider_1, transactionHash_2, payload_1) {
|
|
1540
|
+
return __awaiter(this, arguments, void 0, function (provider, transactionHash, payload, maxAttempts, intervalMs) {
|
|
1541
|
+
var attempts, poll;
|
|
1129
1542
|
var _this = this;
|
|
1130
1543
|
if (maxAttempts === void 0) { maxAttempts = 10; }
|
|
1131
1544
|
if (intervalMs === void 0) { intervalMs = 3000; }
|
|
1132
1545
|
return __generator(this, function (_a) {
|
|
1133
1546
|
attempts = 0;
|
|
1134
|
-
provider = this.provider;
|
|
1135
1547
|
if (!provider)
|
|
1136
1548
|
return [2 /*return*/];
|
|
1137
1549
|
poll = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1138
|
-
var receipt,
|
|
1550
|
+
var receipt, e_9;
|
|
1139
1551
|
return __generator(this, function (_a) {
|
|
1140
1552
|
switch (_a.label) {
|
|
1141
1553
|
case 0:
|
|
@@ -1159,8 +1571,8 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1159
1571
|
}
|
|
1160
1572
|
return [3 /*break*/, 3];
|
|
1161
1573
|
case 2:
|
|
1162
|
-
|
|
1163
|
-
lib_1.logger.error("Error polling transaction receipt",
|
|
1574
|
+
e_9 = _a.sent();
|
|
1575
|
+
lib_1.logger.error("Error polling transaction receipt", e_9);
|
|
1164
1576
|
return [3 /*break*/, 3];
|
|
1165
1577
|
case 3:
|
|
1166
1578
|
attempts++;
|
|
@@ -1176,6 +1588,122 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1176
1588
|
});
|
|
1177
1589
|
});
|
|
1178
1590
|
};
|
|
1591
|
+
FormoAnalytics.prototype.removeProviderListeners = function (provider) {
|
|
1592
|
+
var listeners = this._providerListenersMap.get(provider);
|
|
1593
|
+
if (!listeners)
|
|
1594
|
+
return;
|
|
1595
|
+
for (var _i = 0, _a = Object.entries(listeners); _i < _a.length; _i++) {
|
|
1596
|
+
var _b = _a[_i], event_1 = _b[0], fn = _b[1];
|
|
1597
|
+
try {
|
|
1598
|
+
provider.removeListener(event_1, fn);
|
|
1599
|
+
}
|
|
1600
|
+
catch (e) {
|
|
1601
|
+
lib_1.logger.warn("Failed to remove listener for ".concat(String(event_1)), e);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
this._providerListenersMap.delete(provider);
|
|
1605
|
+
};
|
|
1606
|
+
// Explicitly untrack a provider: remove listeners, clear wrapper flag and tracking
|
|
1607
|
+
FormoAnalytics.prototype.untrackProvider = function (provider) {
|
|
1608
|
+
try {
|
|
1609
|
+
this.removeProviderListeners(provider);
|
|
1610
|
+
this._trackedProviders.delete(provider);
|
|
1611
|
+
if (this._provider === provider) {
|
|
1612
|
+
this._provider = undefined;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
catch (e) {
|
|
1616
|
+
lib_1.logger.warn("Failed to untrack provider", e);
|
|
1617
|
+
}
|
|
1618
|
+
};
|
|
1619
|
+
// Debug/monitoring helpers
|
|
1620
|
+
FormoAnalytics.prototype.getTrackedProvidersCount = function () {
|
|
1621
|
+
return this._trackedProviders.size;
|
|
1622
|
+
};
|
|
1623
|
+
/**
|
|
1624
|
+
* Get current provider state for debugging
|
|
1625
|
+
* @returns Object containing current provider state information
|
|
1626
|
+
*/
|
|
1627
|
+
FormoAnalytics.prototype.getProviderState = function () {
|
|
1628
|
+
return {
|
|
1629
|
+
totalProviders: this._providers.length,
|
|
1630
|
+
trackedProviders: this._trackedProviders.size,
|
|
1631
|
+
seenProviders: this._seenProviders.size,
|
|
1632
|
+
activeProvider: !!this._provider,
|
|
1633
|
+
};
|
|
1634
|
+
};
|
|
1635
|
+
/**
|
|
1636
|
+
* Clean up providers that are no longer available
|
|
1637
|
+
* This helps maintain consistent state and prevents memory leaks
|
|
1638
|
+
*/
|
|
1639
|
+
FormoAnalytics.prototype.cleanupUnavailableProviders = function () {
|
|
1640
|
+
// Remove providers that are no longer in the current providers list
|
|
1641
|
+
var currentProviderInstances = new Set(this._providers.map(function (detail) { return detail.provider; }));
|
|
1642
|
+
for (var _i = 0, _a = Array.from(this._trackedProviders); _i < _a.length; _i++) {
|
|
1643
|
+
var provider = _a[_i];
|
|
1644
|
+
if (!currentProviderInstances.has(provider)) {
|
|
1645
|
+
lib_1.logger.info("Cleaning up unavailable provider: ".concat(provider.constructor.name));
|
|
1646
|
+
this.untrackProvider(provider);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
};
|
|
1650
|
+
/**
|
|
1651
|
+
* Helper method to check if a provider is already wrapped
|
|
1652
|
+
* @param provider The provider to check
|
|
1653
|
+
* @param currentRequest The current request function
|
|
1654
|
+
* @returns true if the provider is already wrapped
|
|
1655
|
+
*/
|
|
1656
|
+
FormoAnalytics.prototype.isProviderAlreadyWrapped = function (provider, currentRequest) {
|
|
1657
|
+
return !!(currentRequest &&
|
|
1658
|
+
typeof currentRequest === 'function' &&
|
|
1659
|
+
currentRequest[types_1.WRAPPED_REQUEST_SYMBOL] &&
|
|
1660
|
+
provider[types_1.WRAPPED_REQUEST_REF_SYMBOL] === currentRequest);
|
|
1661
|
+
};
|
|
1662
|
+
/**
|
|
1663
|
+
* Handle provider mismatch by switching to the new provider and invalidating old tokens
|
|
1664
|
+
* @param provider The new provider to switch to
|
|
1665
|
+
*/
|
|
1666
|
+
FormoAnalytics.prototype.handleProviderMismatch = function (provider) {
|
|
1667
|
+
// If this is a different provider, allow the switch
|
|
1668
|
+
if (this._provider) {
|
|
1669
|
+
// Clear any provider-specific state when switching
|
|
1670
|
+
this.currentChainId = undefined;
|
|
1671
|
+
this.currentAddress = undefined;
|
|
1672
|
+
}
|
|
1673
|
+
this._provider = provider;
|
|
1674
|
+
};
|
|
1675
|
+
/**
|
|
1676
|
+
* Helper method to validate and checksum an address
|
|
1677
|
+
* @param address The address to validate and checksum
|
|
1678
|
+
* @returns The checksummed address or undefined if invalid
|
|
1679
|
+
*/
|
|
1680
|
+
FormoAnalytics.prototype.validateAndChecksumAddress = function (address) {
|
|
1681
|
+
var validAddress = (0, address_1.getValidAddress)(address);
|
|
1682
|
+
return validAddress ? (0, utils_1.toChecksumAddress)(validAddress) : undefined;
|
|
1683
|
+
};
|
|
1684
|
+
/**
|
|
1685
|
+
* Helper method to safely add a provider detail to _providers array, ensuring no duplicates
|
|
1686
|
+
* @param detail The provider detail to add
|
|
1687
|
+
* @returns true if the provider was added, false if it was already present
|
|
1688
|
+
*/
|
|
1689
|
+
FormoAnalytics.prototype.safeAddProviderDetail = function (detail) {
|
|
1690
|
+
var provider = detail === null || detail === void 0 ? void 0 : detail.provider;
|
|
1691
|
+
if (!provider)
|
|
1692
|
+
return false;
|
|
1693
|
+
// Check if provider already exists in _providers array
|
|
1694
|
+
var alreadyExists = this._providers.some(function (existing) { return existing.provider === provider; });
|
|
1695
|
+
if (!alreadyExists) {
|
|
1696
|
+
// Add to providers array and mark as seen
|
|
1697
|
+
this._providers = __spreadArray(__spreadArray([], this._providers, true), [detail], false);
|
|
1698
|
+
this._seenProviders.add(provider);
|
|
1699
|
+
return true;
|
|
1700
|
+
}
|
|
1701
|
+
else {
|
|
1702
|
+
// Ensure provider is marked as seen even if it already exists in _providers
|
|
1703
|
+
this._seenProviders.add(provider);
|
|
1704
|
+
return false;
|
|
1705
|
+
}
|
|
1706
|
+
};
|
|
1179
1707
|
return FormoAnalytics;
|
|
1180
1708
|
}());
|
|
1181
1709
|
exports.FormoAnalytics = FormoAnalytics;
|