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