@formo/analytics 1.29.0 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/FormoAnalytics.d.ts +52 -3
- package/dist/cjs/src/FormoAnalytics.js +262 -51
- package/dist/cjs/src/constants/base.d.ts +9 -0
- package/dist/cjs/src/constants/base.js +10 -1
- package/dist/cjs/src/constants/config.d.ts +3 -58
- package/dist/cjs/src/constants/config.js +3 -73
- package/dist/cjs/src/event/EventFactory.d.ts +1 -1
- package/dist/cjs/src/event/EventFactory.js +12 -6
- package/dist/cjs/src/event/EventManager.d.ts +2 -0
- package/dist/cjs/src/event/EventManager.js +4 -0
- package/dist/cjs/src/event/type.d.ts +1 -0
- package/dist/cjs/src/event/utils.js +1 -1
- package/dist/cjs/src/queue/EventQueue.d.ts +8 -0
- package/dist/cjs/src/queue/EventQueue.js +52 -6
- package/dist/cjs/src/queue/type.d.ts +1 -0
- package/dist/cjs/src/session/index.js +16 -8
- package/dist/cjs/src/storage/cookiePolicy.d.ts +16 -0
- package/dist/cjs/src/storage/cookiePolicy.js +19 -0
- package/dist/cjs/src/types/base.d.ts +0 -1
- package/dist/cjs/src/types/events.d.ts +0 -1
- package/dist/cjs/src/version.d.ts +1 -1
- package/dist/cjs/src/version.js +1 -1
- package/dist/cjs/src/wagmi/WagmiEventHandler.js +38 -15
- package/dist/esm/src/FormoAnalytics.d.ts +52 -3
- package/dist/esm/src/FormoAnalytics.js +265 -54
- package/dist/esm/src/constants/base.d.ts +9 -0
- package/dist/esm/src/constants/base.js +9 -0
- package/dist/esm/src/constants/config.d.ts +3 -58
- package/dist/esm/src/constants/config.js +3 -73
- package/dist/esm/src/event/EventFactory.d.ts +1 -1
- package/dist/esm/src/event/EventFactory.js +12 -6
- package/dist/esm/src/event/EventManager.d.ts +2 -0
- package/dist/esm/src/event/EventManager.js +4 -0
- package/dist/esm/src/event/type.d.ts +1 -0
- package/dist/esm/src/event/utils.js +2 -2
- package/dist/esm/src/queue/EventQueue.d.ts +8 -0
- package/dist/esm/src/queue/EventQueue.js +52 -6
- package/dist/esm/src/queue/type.d.ts +1 -0
- package/dist/esm/src/session/index.js +16 -8
- package/dist/esm/src/storage/cookiePolicy.d.ts +16 -0
- package/dist/esm/src/storage/cookiePolicy.js +18 -0
- package/dist/esm/src/types/base.d.ts +0 -1
- package/dist/esm/src/types/events.d.ts +0 -1
- package/dist/esm/src/version.d.ts +1 -1
- package/dist/esm/src/version.js +1 -1
- package/dist/esm/src/wagmi/WagmiEventHandler.js +38 -15
- package/dist/index.umd.min.js +1 -1
- package/package.json +13 -23
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "1.
|
|
1
|
+
export declare const version = "1.30.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/cjs/src/version.js
CHANGED
|
@@ -3,5 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.version = void 0;
|
|
4
4
|
// This file is auto-generated by scripts/update-version.js during npm version
|
|
5
5
|
// Do not edit manually - it will be overwritten
|
|
6
|
-
exports.version = '1.
|
|
6
|
+
exports.version = '1.30.0';
|
|
7
7
|
//# sourceMappingURL=version.js.map
|
|
@@ -173,6 +173,11 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
173
173
|
chainId: chainId,
|
|
174
174
|
});
|
|
175
175
|
if (!(status === "disconnected" && prevStatus === "connected")) return [3 /*break*/, 4];
|
|
176
|
+
// Clear central chain state regardless of autocapture so a later
|
|
177
|
+
// event can't carry a stale excluded/!excluded chainId.
|
|
178
|
+
this.formo.syncWalletState({
|
|
179
|
+
chainId: this.trackingState.lastChainId,
|
|
180
|
+
});
|
|
176
181
|
if (!this.formo.isAutocaptureEnabled("disconnect")) return [3 /*break*/, 3];
|
|
177
182
|
return [4 /*yield*/, this.formo.disconnect({
|
|
178
183
|
chainId: this.trackingState.lastChainId,
|
|
@@ -190,6 +195,9 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
190
195
|
if (!(address && chainId !== undefined)) return [3 /*break*/, 6];
|
|
191
196
|
this.trackingState.lastAddress = address;
|
|
192
197
|
this.trackingState.lastChainId = chainId;
|
|
198
|
+
// Sync central state unconditionally so tracking.excludeChains
|
|
199
|
+
// is enforced even when connect autocapture is disabled.
|
|
200
|
+
this.formo.syncWalletState({ chainId: chainId, address: address });
|
|
193
201
|
if (!this.formo.isAutocaptureEnabled("connect")) return [3 /*break*/, 6];
|
|
194
202
|
connectorName = this.getConnectorName(state);
|
|
195
203
|
return [4 /*yield*/, this.formo.connect({ chainId: chainId, address: address }, __assign({}, (connectorName && { providerName: connectorName })))];
|
|
@@ -238,6 +246,9 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
238
246
|
address: address,
|
|
239
247
|
});
|
|
240
248
|
this.trackingState.lastChainId = chainId;
|
|
249
|
+
// Sync central state unconditionally so a chain switch to an
|
|
250
|
+
// excluded chain is honored even when chain autocapture is disabled.
|
|
251
|
+
this.formo.syncWalletState({ chainId: chainId, address: address });
|
|
241
252
|
if (!this.formo.isAutocaptureEnabled("chain")) return [3 /*break*/, 4];
|
|
242
253
|
_a.label = 1;
|
|
243
254
|
case 1:
|
|
@@ -359,14 +370,21 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
359
370
|
logger_1.logger.warn("WagmiEventHandler: Transaction receipt query but no hash found");
|
|
360
371
|
return;
|
|
361
372
|
}
|
|
362
|
-
// Retrieve stored transaction details from BROADCASTED event
|
|
363
|
-
// Normalize hash to lowercase for consistent lookup
|
|
373
|
+
// Retrieve stored transaction details from the BROADCASTED event.
|
|
374
|
+
// Normalize hash to lowercase for consistent lookup.
|
|
364
375
|
var normalizedHash = transactionHash.toLowerCase();
|
|
365
376
|
var pendingTx = this.pendingTransactions.get(normalizedHash);
|
|
366
|
-
//
|
|
367
|
-
//
|
|
368
|
-
//
|
|
369
|
-
|
|
377
|
+
// Only emit receipt-derived events for a hash we actually observed
|
|
378
|
+
// being broadcast through this handler. The QueryClient is supplied
|
|
379
|
+
// by the host app and its cache can be written by app code or other
|
|
380
|
+
// deps, so without this gate a forged waitForTransactionReceipt
|
|
381
|
+
// entry could fabricate a confirmed/reverted transaction for an
|
|
382
|
+
// arbitrary hash. No pendingTx → not our broadcast → ignore.
|
|
383
|
+
if (!pendingTx) {
|
|
384
|
+
logger_1.logger.debug("WagmiEventHandler: Receipt for unobserved tx hash; ignoring", { transactionHash: transactionHash });
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
var address = pendingTx.address;
|
|
370
388
|
if (!address) {
|
|
371
389
|
logger_1.logger.warn("WagmiEventHandler: Transaction receipt query but no address available");
|
|
372
390
|
return;
|
|
@@ -374,9 +392,13 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
374
392
|
try {
|
|
375
393
|
// Extract receipt data
|
|
376
394
|
var receipt = state.data;
|
|
377
|
-
//
|
|
378
|
-
//
|
|
379
|
-
|
|
395
|
+
// Only act on an explicit on-chain outcome. A missing/unknown
|
|
396
|
+
// status must NOT be treated as a confirmation.
|
|
397
|
+
if ((receipt === null || receipt === void 0 ? void 0 : receipt.status) !== "success" && (receipt === null || receipt === void 0 ? void 0 : receipt.status) !== "reverted") {
|
|
398
|
+
logger_1.logger.debug("WagmiEventHandler: Receipt without explicit success/reverted status; ignoring", { transactionHash: transactionHash, status: receipt === null || receipt === void 0 ? void 0 : receipt.status });
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
var txStatus = receipt.status === "reverted"
|
|
380
402
|
? events_1.TransactionStatus.REVERTED
|
|
381
403
|
: events_1.TransactionStatus.CONFIRMED;
|
|
382
404
|
logger_1.logger.info("WagmiEventHandler: Tracking transaction confirmation", {
|
|
@@ -455,15 +477,13 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
455
477
|
return;
|
|
456
478
|
}
|
|
457
479
|
try {
|
|
458
|
-
// Map Wagmi mutation status to Formo signature status
|
|
480
|
+
// Map Wagmi mutation status to Formo signature status.
|
|
459
481
|
var status_1;
|
|
460
|
-
var signatureHash = void 0;
|
|
461
482
|
if (state.status === "pending") {
|
|
462
483
|
status_1 = events_1.SignatureStatus.REQUESTED;
|
|
463
484
|
}
|
|
464
485
|
else if (state.status === "success") {
|
|
465
486
|
status_1 = events_1.SignatureStatus.CONFIRMED;
|
|
466
|
-
signatureHash = state.data;
|
|
467
487
|
}
|
|
468
488
|
else if (state.status === "error") {
|
|
469
489
|
status_1 = events_1.SignatureStatus.REJECTED;
|
|
@@ -471,13 +491,11 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
471
491
|
else {
|
|
472
492
|
return; // Ignore idle state
|
|
473
493
|
}
|
|
474
|
-
// Extract message from variables
|
|
475
494
|
var message = void 0;
|
|
476
495
|
if (mutationType === "signMessage") {
|
|
477
496
|
message = variables.message || "";
|
|
478
497
|
}
|
|
479
498
|
else {
|
|
480
|
-
// For signTypedData, stringify the typed data
|
|
481
499
|
message = JSON.stringify(variables.message || variables.types || {});
|
|
482
500
|
}
|
|
483
501
|
logger_1.logger.info("WagmiEventHandler: Tracking signature event", {
|
|
@@ -486,7 +504,12 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
486
504
|
address: address,
|
|
487
505
|
chainId: chainId,
|
|
488
506
|
});
|
|
489
|
-
this.formo.signature(
|
|
507
|
+
this.formo.signature({
|
|
508
|
+
status: status_1,
|
|
509
|
+
chainId: chainId,
|
|
510
|
+
address: address,
|
|
511
|
+
message: message,
|
|
512
|
+
});
|
|
490
513
|
}
|
|
491
514
|
catch (error) {
|
|
492
515
|
logger_1.logger.error("WagmiEventHandler: Error handling signature mutation:", error);
|
|
@@ -54,6 +54,10 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
54
54
|
private crossSubdomainCookies;
|
|
55
55
|
/** In-memory URL used to deduplicate SPA pageview events. */
|
|
56
56
|
private _currentUrl;
|
|
57
|
+
/** Page-hit hooks installed in trackPageHits() so cleanup() can undo them. */
|
|
58
|
+
private _onPopStateListener?;
|
|
59
|
+
private _onLocationChangeListener?;
|
|
60
|
+
private _pageHooksDisposed;
|
|
57
61
|
config: Config;
|
|
58
62
|
currentChainId?: ChainID;
|
|
59
63
|
currentAddress?: Address;
|
|
@@ -132,18 +136,16 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
132
136
|
* @param {ChainID} params.chainId
|
|
133
137
|
* @param {Address} params.address
|
|
134
138
|
* @param {string} params.message
|
|
135
|
-
* @param {string} params.signatureHash - only provided if status is confirmed
|
|
136
139
|
* @param {IFormoEventProperties} properties
|
|
137
140
|
* @param {IFormoEventContext} context
|
|
138
141
|
* @param {(...args: unknown[]) => void} callback
|
|
139
142
|
* @returns {Promise<void>}
|
|
140
143
|
*/
|
|
141
|
-
signature({ status, chainId, address, message,
|
|
144
|
+
signature({ status, chainId, address, message, }: {
|
|
142
145
|
status: SignatureStatus;
|
|
143
146
|
chainId?: ChainID;
|
|
144
147
|
address: Address;
|
|
145
148
|
message: string;
|
|
146
|
-
signatureHash?: string;
|
|
147
149
|
}, properties?: IFormoEventProperties, context?: IFormoEventContext, callback?: (...args: unknown[]) => void): Promise<void>;
|
|
148
150
|
/**
|
|
149
151
|
* Emits a transaction event.
|
|
@@ -272,6 +274,12 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
272
274
|
private registerRequestListeners;
|
|
273
275
|
private onLocationChange;
|
|
274
276
|
private trackPageHits;
|
|
277
|
+
/**
|
|
278
|
+
* Wrap history.pushState / replaceState exactly once per `history` object,
|
|
279
|
+
* regardless of how many SDK instances are constructed. Uses a Symbol
|
|
280
|
+
* marker so we recognize our own wrapper across module reloads in HMR.
|
|
281
|
+
*/
|
|
282
|
+
private static installHistoryHooksOnce;
|
|
275
283
|
private trackPageHit;
|
|
276
284
|
private trackEvent;
|
|
277
285
|
/**
|
|
@@ -312,6 +320,15 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
312
320
|
private getCurrentChainId;
|
|
313
321
|
private buildSignatureEventPayload;
|
|
314
322
|
private buildTransactionEventPayload;
|
|
323
|
+
/**
|
|
324
|
+
* Persist an EVM address discovered through autocapture (signature / transaction)
|
|
325
|
+
* as the current EVM address when none is currently set. This lets subsequent
|
|
326
|
+
* track()/page() calls carry the address even when the underlying wallet never
|
|
327
|
+
* fires an EIP-1193 `accountsChanged` event (embedded wallets, smart accounts,
|
|
328
|
+
* social-login wrappers). If `accountsChanged` later fires it overwrites this
|
|
329
|
+
* value in the normal way; existing connections are never clobbered.
|
|
330
|
+
*/
|
|
331
|
+
private backfillActiveWallet;
|
|
315
332
|
/**
|
|
316
333
|
* Polls for transaction receipt and emits tx.status = CONFIRMED or REVERTED.
|
|
317
334
|
*/
|
|
@@ -362,11 +379,43 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
362
379
|
* Clear per-chain state for a given namespace (or chainId) and sync derived state.
|
|
363
380
|
*/
|
|
364
381
|
private clearChainState;
|
|
382
|
+
/**
|
|
383
|
+
* Sync validated wallet/chain state into the SDK's central state
|
|
384
|
+
* WITHOUT emitting an event.
|
|
385
|
+
*
|
|
386
|
+
* Integrations (e.g. the wagmi handler) must call this on every
|
|
387
|
+
* connect / chain-change / disconnect — even when the corresponding
|
|
388
|
+
* autocapture event is disabled. Otherwise `currentChainId` stays
|
|
389
|
+
* stale/undefined and `shouldTrack()`'s `tracking.excludeChains`
|
|
390
|
+
* check (which keys off `currentChainId`, not the event payload) can
|
|
391
|
+
* be bypassed, letting wallet activity on an excluded chain still be
|
|
392
|
+
* collected.
|
|
393
|
+
*
|
|
394
|
+
* - valid `address` present → record per-chain + derived state
|
|
395
|
+
* - `address` absent → clear chain state (disconnect)
|
|
396
|
+
*/
|
|
397
|
+
syncWalletState(params: {
|
|
398
|
+
chainId?: ChainID;
|
|
399
|
+
address?: Address;
|
|
400
|
+
}): void;
|
|
365
401
|
/**
|
|
366
402
|
* Synchronize currentAddress/currentChainId from the active namespace.
|
|
367
403
|
* Last-connected-chain-wins: _activeNamespace takes precedence.
|
|
368
404
|
*/
|
|
369
405
|
private syncDerivedState;
|
|
406
|
+
/**
|
|
407
|
+
* Persist (or clear) the current wallet snapshot in a cookie so that the
|
|
408
|
+
* SDK can repopulate `currentAddress`/`currentChainId` at init on the next
|
|
409
|
+
* page load — closing the gap between page-show and wagmi/EIP-1193
|
|
410
|
+
* reconnection during which track()/page() events would otherwise ship
|
|
411
|
+
* with an empty address.
|
|
412
|
+
*/
|
|
413
|
+
private persistActiveWallet;
|
|
414
|
+
/**
|
|
415
|
+
* Seed `currentAddress`/`currentChainId` from the persisted snapshot, if
|
|
416
|
+
* any. Called once during construction before the first page hit fires.
|
|
417
|
+
*/
|
|
418
|
+
private loadActiveWallet;
|
|
370
419
|
/**
|
|
371
420
|
* Helper method to clear the active provider state
|
|
372
421
|
* Centralizes provider clearing logic for consistency
|