@formo/analytics 1.29.1 → 1.30.1
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 +20 -3
- package/dist/cjs/src/FormoAnalytics.js +102 -9
- package/dist/cjs/src/FormoAnalyticsProvider.d.ts +8 -2
- package/dist/cjs/src/core.d.ts +10 -0
- package/dist/cjs/src/core.js +36 -0
- package/dist/cjs/src/event/EventFactory.d.ts +1 -1
- package/dist/cjs/src/event/EventFactory.js +3 -3
- 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/index.d.ts +1 -8
- package/dist/cjs/src/index.js +1 -12
- 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 -8
- 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 +20 -3
- package/dist/esm/src/FormoAnalytics.js +105 -12
- package/dist/esm/src/FormoAnalyticsProvider.d.ts +8 -2
- package/dist/esm/src/core.d.ts +10 -0
- package/dist/esm/src/core.js +13 -0
- package/dist/esm/src/event/EventFactory.d.ts +1 -1
- package/dist/esm/src/event/EventFactory.js +3 -3
- 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/index.d.ts +1 -8
- package/dist/esm/src/index.js +1 -6
- 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 -8
- 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 +18 -18
|
@@ -18,6 +18,8 @@ declare class EventManager implements IEventManager {
|
|
|
18
18
|
* @param event Incoming event data
|
|
19
19
|
*/
|
|
20
20
|
addEvent(event: APIEvent, address?: Address, userId?: string): Promise<void>;
|
|
21
|
+
/** Drop any buffered events (consent withdrawal / teardown). */
|
|
22
|
+
clear(): void;
|
|
21
23
|
}
|
|
22
24
|
export { EventManager };
|
|
23
25
|
//# sourceMappingURL=EventManager.d.ts.map
|
|
@@ -93,6 +93,10 @@ var EventManager = /** @class */ (function () {
|
|
|
93
93
|
});
|
|
94
94
|
});
|
|
95
95
|
};
|
|
96
|
+
/** Drop any buffered events (consent withdrawal / teardown). */
|
|
97
|
+
EventManager.prototype.clear = function () {
|
|
98
|
+
this.eventQueue.clear();
|
|
99
|
+
};
|
|
96
100
|
return EventManager;
|
|
97
101
|
}());
|
|
98
102
|
export { EventManager };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Address, APIEvent, IFormoEvent } from "../types";
|
|
2
2
|
export interface IEventManager {
|
|
3
3
|
addEvent(event: APIEvent, address?: Address, userId?: string): Promise<void>;
|
|
4
|
+
clear(): void;
|
|
4
5
|
}
|
|
5
6
|
export interface IEventFactory {
|
|
6
7
|
create(event: APIEvent, address?: Address, userId?: string): Promise<IFormoEvent>;
|
|
@@ -11,7 +11,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
11
11
|
};
|
|
12
12
|
import { generateNativeUUID } from "../utils";
|
|
13
13
|
import { cookie } from "../storage";
|
|
14
|
-
import { getIdentityCookieDomain } from "../storage/cookiePolicy";
|
|
14
|
+
import { getIdentityCookieDomain, getIdentityCookieSecurity, } from "../storage/cookiePolicy";
|
|
15
15
|
var generateAnonymousId = function (key, crossSubdomainCookies) {
|
|
16
16
|
var storedAnonymousId = cookie().get(key);
|
|
17
17
|
var anonymousId = (storedAnonymousId && typeof storedAnonymousId === "string"
|
|
@@ -23,7 +23,7 @@ var generateAnonymousId = function (key, crossSubdomainCookies) {
|
|
|
23
23
|
// domain. Note: host-only cookies on other hosts (e.g. a cookie set on
|
|
24
24
|
// example.com is not visible from app.example.com) cannot be migrated
|
|
25
25
|
// until the user revisits that host.
|
|
26
|
-
cookie().set(key, anonymousId, __assign({ expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365).toUTCString(), path: "/" }, (domain ? { domain: domain } : {})));
|
|
26
|
+
cookie().set(key, anonymousId, __assign(__assign({ expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365).toUTCString(), path: "/" }, getIdentityCookieSecurity()), (domain ? { domain: domain } : {})));
|
|
27
27
|
return anonymousId;
|
|
28
28
|
};
|
|
29
29
|
export { generateAnonymousId };
|
package/dist/esm/src/index.d.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
+
export * from "./core";
|
|
1
2
|
export * from "./FormoAnalyticsProvider";
|
|
2
|
-
export * from "./FormoAnalytics";
|
|
3
|
-
export * from "./types";
|
|
4
|
-
export { parsePrivyProperties } from "./privy";
|
|
5
|
-
export type { PrivyUser, PrivyLinkedAccount, PrivyAccountType, PrivyProfileProperties, PrivyWalletInfo } from "./privy";
|
|
6
|
-
export { SolanaManager } from "./solana";
|
|
7
|
-
export { SOLANA_CHAIN_IDS, DEFAULT_SOLANA_CHAIN_ID, isSolanaChainId } from "./solana";
|
|
8
|
-
export type { SolanaOptions, SolanaCluster, } from "./solana";
|
|
9
|
-
export type { SolanaClientStore, SolanaClientState, } from "./solana";
|
|
10
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/esm/src/index.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { formofy } from "./initialization";
|
|
2
|
+
export * from "./core";
|
|
2
3
|
export * from "./FormoAnalyticsProvider";
|
|
3
|
-
export * from "./FormoAnalytics";
|
|
4
|
-
export * from "./types";
|
|
5
|
-
export { parsePrivyProperties } from "./privy";
|
|
6
|
-
// Solana integration exports
|
|
7
|
-
export { SolanaManager } from "./solana";
|
|
8
|
-
export { SOLANA_CHAIN_IDS, DEFAULT_SOLANA_CHAIN_ID, isSolanaChainId } from "./solana";
|
|
9
4
|
if (typeof window !== "undefined")
|
|
10
5
|
window.formofy = formofy;
|
|
11
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -11,6 +11,7 @@ type Options = {
|
|
|
11
11
|
retryCount?: number;
|
|
12
12
|
errorHandler?: any;
|
|
13
13
|
maxQueueSize?: number;
|
|
14
|
+
canSend?: () => boolean;
|
|
14
15
|
};
|
|
15
16
|
export declare class EventQueue implements IEventQueue {
|
|
16
17
|
private writeKey;
|
|
@@ -21,12 +22,19 @@ export declare class EventQueue implements IEventQueue {
|
|
|
21
22
|
private flushIntervalMs;
|
|
22
23
|
private flushed;
|
|
23
24
|
private maxQueueSize;
|
|
25
|
+
private queueByteSize;
|
|
24
26
|
private errorHandler;
|
|
25
27
|
private retryCount;
|
|
26
28
|
private pendingFlush;
|
|
27
29
|
private payloadHashes;
|
|
30
|
+
private canSend?;
|
|
28
31
|
constructor(writeKey: string, options: Options);
|
|
29
32
|
private generateMessageId;
|
|
33
|
+
/**
|
|
34
|
+
* Drop all queued data and cancel the flush timer. Called on consent
|
|
35
|
+
* withdrawal / SDK teardown so nothing buffered can be sent later.
|
|
36
|
+
*/
|
|
37
|
+
clear(): void;
|
|
30
38
|
enqueue(event: IFormoEvent, callback?: (...args: any) => void): Promise<void>;
|
|
31
39
|
flush(callback?: (...args: any) => void, drainAll?: boolean): Promise<void | IFormoEventFlushPayload[]>;
|
|
32
40
|
/**
|
|
@@ -81,6 +81,7 @@ var EventQueue = /** @class */ (function () {
|
|
|
81
81
|
function EventQueue(writeKey, options) {
|
|
82
82
|
var _this = this;
|
|
83
83
|
this.queue = [];
|
|
84
|
+
this.queueByteSize = 0; // running total of queued items' byteSize
|
|
84
85
|
this.payloadHashes = new Set();
|
|
85
86
|
this.onPageLeave = function (callback) {
|
|
86
87
|
// To ensure the callback is only called once even if more than one events
|
|
@@ -136,6 +137,7 @@ var EventQueue = /** @class */ (function () {
|
|
|
136
137
|
this.queue = [];
|
|
137
138
|
this.writeKey = writeKey;
|
|
138
139
|
this.apiHost = options.apiHost;
|
|
140
|
+
this.canSend = options.canSend;
|
|
139
141
|
this.retryCount = clampNumber(options.retryCount || DEFAULT_RETRY, MAX_RETRY, MIN_RETRY);
|
|
140
142
|
this.flushAt = clampNumber(options.flushAt || DEFAULT_FLUSH_AT, MAX_FLUSH_AT, MIN_FLUSH_AT);
|
|
141
143
|
this.maxQueueSize = clampNumber(options.maxQueueSize || DEFAULT_QUEUE_SIZE, MAX_QUEUE_SIZE, MIN_QUEUE_SIZE);
|
|
@@ -169,13 +171,31 @@ var EventQueue = /** @class */ (function () {
|
|
|
169
171
|
});
|
|
170
172
|
});
|
|
171
173
|
};
|
|
174
|
+
/**
|
|
175
|
+
* Drop all queued data and cancel the flush timer. Called on consent
|
|
176
|
+
* withdrawal / SDK teardown so nothing buffered can be sent later.
|
|
177
|
+
*/
|
|
178
|
+
EventQueue.prototype.clear = function () {
|
|
179
|
+
if (this.timer) {
|
|
180
|
+
clearTimeout(this.timer);
|
|
181
|
+
this.timer = null;
|
|
182
|
+
}
|
|
183
|
+
this.queue = [];
|
|
184
|
+
this.queueByteSize = 0;
|
|
185
|
+
this.payloadHashes.clear();
|
|
186
|
+
};
|
|
172
187
|
EventQueue.prototype.enqueue = function (event, callback) {
|
|
173
188
|
return __awaiter(this, void 0, void 0, function () {
|
|
174
|
-
var message_id, hasReachedFlushAt, hasReachedQueueSize;
|
|
189
|
+
var message_id, queueItem, hasReachedFlushAt, hasReachedQueueSize;
|
|
175
190
|
return __generator(this, function (_a) {
|
|
176
191
|
switch (_a.label) {
|
|
177
192
|
case 0:
|
|
178
193
|
callback = callback || noop;
|
|
194
|
+
// Refuse to buffer anything once consent is withdrawn.
|
|
195
|
+
if (this.canSend && !this.canSend()) {
|
|
196
|
+
this.clear();
|
|
197
|
+
return [2 /*return*/];
|
|
198
|
+
}
|
|
179
199
|
return [4 /*yield*/, this.generateMessageId(event)];
|
|
180
200
|
case 1:
|
|
181
201
|
message_id = _a.sent();
|
|
@@ -184,10 +204,18 @@ var EventQueue = /** @class */ (function () {
|
|
|
184
204
|
logger.warn("Event already enqueued, try again after ".concat(millisecondsToSecond(this.flushIntervalMs), " seconds."));
|
|
185
205
|
return [2 /*return*/];
|
|
186
206
|
}
|
|
187
|
-
|
|
207
|
+
queueItem = {
|
|
188
208
|
message: __assign(__assign({}, event), { message_id: message_id }),
|
|
189
209
|
callback: callback,
|
|
190
|
-
|
|
210
|
+
byteSize: 0,
|
|
211
|
+
};
|
|
212
|
+
// Measure once here (message only — JSON.stringify drops the
|
|
213
|
+
// callback function anyway), then track the total incrementally.
|
|
214
|
+
queueItem.byteSize = JSON.stringify({
|
|
215
|
+
message: queueItem.message,
|
|
216
|
+
}).length;
|
|
217
|
+
this.queue.push(queueItem);
|
|
218
|
+
this.queueByteSize += queueItem.byteSize;
|
|
191
219
|
logger.log("Event enqueued: ".concat(getActionDescriptor(event.type, event.properties)));
|
|
192
220
|
if (!this.flushed) {
|
|
193
221
|
this.flushed = true;
|
|
@@ -195,8 +223,7 @@ var EventQueue = /** @class */ (function () {
|
|
|
195
223
|
return [2 /*return*/];
|
|
196
224
|
}
|
|
197
225
|
hasReachedFlushAt = this.queue.length >= this.flushAt;
|
|
198
|
-
hasReachedQueueSize = this.
|
|
199
|
-
this.maxQueueSize;
|
|
226
|
+
hasReachedQueueSize = this.queueByteSize >= this.maxQueueSize;
|
|
200
227
|
if (hasReachedFlushAt || hasReachedQueueSize) {
|
|
201
228
|
this.flush();
|
|
202
229
|
return [2 /*return*/];
|
|
@@ -222,6 +249,13 @@ var EventQueue = /** @class */ (function () {
|
|
|
222
249
|
clearTimeout(this.timer);
|
|
223
250
|
this.timer = null;
|
|
224
251
|
}
|
|
252
|
+
// Final consent gate: a timer/pagehide flush may have been scheduled
|
|
253
|
+
// before opt-out. Drop everything rather than send post-withdrawal.
|
|
254
|
+
if (this.canSend && !this.canSend()) {
|
|
255
|
+
this.clear();
|
|
256
|
+
callback();
|
|
257
|
+
return [2 /*return*/, Promise.resolve()];
|
|
258
|
+
}
|
|
225
259
|
if (!this.queue.length) {
|
|
226
260
|
callback();
|
|
227
261
|
return [2 /*return*/, Promise.resolve()];
|
|
@@ -235,11 +269,17 @@ var EventQueue = /** @class */ (function () {
|
|
|
235
269
|
case 2:
|
|
236
270
|
items = this.queue.splice(0, drainAll ? this.queue.length : this.flushAt);
|
|
237
271
|
// Only remove hashes for flushed items so duplicate detection remains
|
|
238
|
-
// active for events still in the queue.
|
|
272
|
+
// active for events still in the queue. Also decrement the running
|
|
273
|
+
// byte total by exactly what left the queue.
|
|
239
274
|
for (_i = 0, items_1 = items; _i < items_1.length; _i++) {
|
|
240
275
|
item = items_1[_i];
|
|
241
276
|
this.payloadHashes.delete(item.message.message_id);
|
|
277
|
+
this.queueByteSize -= item.byteSize;
|
|
242
278
|
}
|
|
279
|
+
// Re-anchor to the exact invariant when the queue empties, so any
|
|
280
|
+
// accumulated drift can never wedge the size gate.
|
|
281
|
+
if (this.queue.length === 0)
|
|
282
|
+
this.queueByteSize = 0;
|
|
243
283
|
sentAt = new Date().toISOString();
|
|
244
284
|
data = items.map(function (item) { return (__assign(__assign({}, item.message), { sent_at: sentAt })); });
|
|
245
285
|
batches = this.splitIntoBatches(items, data);
|
|
@@ -342,6 +382,12 @@ var EventQueue = /** @class */ (function () {
|
|
|
342
382
|
case 1:
|
|
343
383
|
if (!(_i < batches_1.length)) return [3 /*break*/, 6];
|
|
344
384
|
batch = batches_1[_i];
|
|
385
|
+
// Consent can be withdrawn while a flush is already in flight:
|
|
386
|
+
// batches were spliced before opt-out, and split batches / retry
|
|
387
|
+
// backoff span seconds. Re-check before every send and abandon
|
|
388
|
+
// the remaining batches if consent was revoked mid-flush.
|
|
389
|
+
if (this.canSend && !this.canSend())
|
|
390
|
+
return [3 /*break*/, 6];
|
|
345
391
|
_a.label = 2;
|
|
346
392
|
case 2:
|
|
347
393
|
_a.trys.push([2, 4, , 5]);
|
|
@@ -4,7 +4,19 @@
|
|
|
4
4
|
* Handles tracking of detected wallets and identified wallet-address pairs
|
|
5
5
|
* using cookies to maintain state across page loads within a session.
|
|
6
6
|
*/
|
|
7
|
+
var __assign = (this && this.__assign) || function () {
|
|
8
|
+
__assign = Object.assign || function(t) {
|
|
9
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
10
|
+
s = arguments[i];
|
|
11
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
12
|
+
t[p] = s[p];
|
|
13
|
+
}
|
|
14
|
+
return t;
|
|
15
|
+
};
|
|
16
|
+
return __assign.apply(this, arguments);
|
|
17
|
+
};
|
|
7
18
|
import { cookie } from "../storage";
|
|
19
|
+
import { getIdentityCookieSecurity } from "../storage/cookiePolicy";
|
|
8
20
|
import { logger } from "../logger";
|
|
9
21
|
/**
|
|
10
22
|
* Cookie keys for session tracking
|
|
@@ -63,11 +75,9 @@ var FormoAnalyticsSession = /** @class */ (function () {
|
|
|
63
75
|
if (rdnses.length > MAX_SESSION_ENTRIES) {
|
|
64
76
|
rdnses.splice(0, rdnses.length - MAX_SESSION_ENTRIES);
|
|
65
77
|
}
|
|
66
|
-
cookie().set(SESSION_WALLET_DETECTED_KEY, rdnses.join(","), {
|
|
78
|
+
cookie().set(SESSION_WALLET_DETECTED_KEY, rdnses.join(","), __assign({
|
|
67
79
|
// Expires by the end of the day
|
|
68
|
-
expires: new Date(Date.now() + 86400 * 1000).toUTCString(),
|
|
69
|
-
path: "/",
|
|
70
|
-
});
|
|
80
|
+
expires: new Date(Date.now() + 86400 * 1000).toUTCString(), path: "/" }, getIdentityCookieSecurity()));
|
|
71
81
|
}
|
|
72
82
|
};
|
|
73
83
|
/**
|
|
@@ -107,11 +117,9 @@ var FormoAnalyticsSession = /** @class */ (function () {
|
|
|
107
117
|
identifiedWallets.splice(0, identifiedWallets.length - MAX_SESSION_ENTRIES);
|
|
108
118
|
}
|
|
109
119
|
var newValue = identifiedWallets.join(",");
|
|
110
|
-
cookie().set(SESSION_WALLET_IDENTIFIED_KEY, newValue, {
|
|
120
|
+
cookie().set(SESSION_WALLET_IDENTIFIED_KEY, newValue, __assign({
|
|
111
121
|
// Expires by the end of the day
|
|
112
|
-
expires: new Date(Date.now() + 86400 * 1000).toUTCString(),
|
|
113
|
-
path: "/",
|
|
114
|
-
});
|
|
122
|
+
expires: new Date(Date.now() + 86400 * 1000).toUTCString(), path: "/" }, getIdentityCookieSecurity()));
|
|
115
123
|
logger.debug("Session: Marked wallet as identified", {
|
|
116
124
|
identifiedKey: identifiedKey,
|
|
117
125
|
hasRdns: !!rdns,
|
|
@@ -7,4 +7,20 @@
|
|
|
7
7
|
* @param crossSubdomain Whether cookies should be shared across subdomains.
|
|
8
8
|
*/
|
|
9
9
|
export declare function getIdentityCookieDomain(crossSubdomain?: boolean): string;
|
|
10
|
+
/**
|
|
11
|
+
* Security attributes for identity/session cookies (user-id,
|
|
12
|
+
* active-wallet, wallet-detected/identified).
|
|
13
|
+
*
|
|
14
|
+
* - `sameSite: "lax"` — first-party analytics identity. Lax keeps the
|
|
15
|
+
* cookie on top-level navigations (so attribution survives a click-in
|
|
16
|
+
* from another site) while blocking it on cross-site subrequests.
|
|
17
|
+
* Strict would silently drop identity on inbound navigation.
|
|
18
|
+
* - `secure` — only on HTTPS. Setting Secure over plain HTTP (local dev)
|
|
19
|
+
* makes the browser reject the cookie outright, so it must be
|
|
20
|
+
* conditional.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getIdentityCookieSecurity(): {
|
|
23
|
+
sameSite: "lax";
|
|
24
|
+
secure: boolean;
|
|
25
|
+
};
|
|
10
26
|
//# sourceMappingURL=cookiePolicy.d.ts.map
|
|
@@ -21,4 +21,22 @@ export function getIdentityCookieDomain(crossSubdomain) {
|
|
|
21
21
|
var domain = getApexDomain();
|
|
22
22
|
return domain ? ".".concat(domain) : "";
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Security attributes for identity/session cookies (user-id,
|
|
26
|
+
* active-wallet, wallet-detected/identified).
|
|
27
|
+
*
|
|
28
|
+
* - `sameSite: "lax"` — first-party analytics identity. Lax keeps the
|
|
29
|
+
* cookie on top-level navigations (so attribution survives a click-in
|
|
30
|
+
* from another site) while blocking it on cross-site subrequests.
|
|
31
|
+
* Strict would silently drop identity on inbound navigation.
|
|
32
|
+
* - `secure` — only on HTTPS. Setting Secure over plain HTTP (local dev)
|
|
33
|
+
* makes the browser reject the cookie outright, so it must be
|
|
34
|
+
* conditional.
|
|
35
|
+
*/
|
|
36
|
+
export function getIdentityCookieSecurity() {
|
|
37
|
+
var _a;
|
|
38
|
+
var isHttps = typeof window !== "undefined" &&
|
|
39
|
+
((_a = window.location) === null || _a === void 0 ? void 0 : _a.protocol) === "https:";
|
|
40
|
+
return { sameSite: "lax", secure: isHttps };
|
|
41
|
+
}
|
|
24
42
|
//# sourceMappingURL=cookiePolicy.js.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { LogLevel } from "../logger";
|
|
2
2
|
import { IFormoEventContext, IFormoEventProperties, SignatureStatus, TransactionStatus } from "./events";
|
|
3
3
|
import { EIP1193Provider } from "./provider";
|
|
4
|
-
import { ReactNode } from "react";
|
|
5
4
|
import { SolanaOptions } from "../solana/types";
|
|
6
5
|
export type Nullable<T> = T | null;
|
|
7
6
|
export type ChainID = number;
|
|
@@ -40,7 +39,6 @@ export interface IFormoAnalytics {
|
|
|
40
39
|
chainId?: ChainID;
|
|
41
40
|
address: Address;
|
|
42
41
|
message: string;
|
|
43
|
-
signatureHash?: string;
|
|
44
42
|
}, properties?: IFormoEventProperties, context?: IFormoEventContext, callback?: (...args: unknown[]) => void): Promise<void>;
|
|
45
43
|
transaction(params: {
|
|
46
44
|
status: TransactionStatus;
|
|
@@ -222,10 +220,4 @@ export interface Options {
|
|
|
222
220
|
errorHandler?: (err: Error) => void;
|
|
223
221
|
ready?: (formo: IFormoAnalytics) => void;
|
|
224
222
|
}
|
|
225
|
-
export interface FormoAnalyticsProviderProps {
|
|
226
|
-
writeKey: string;
|
|
227
|
-
options?: Options;
|
|
228
|
-
disabled?: boolean;
|
|
229
|
-
children: ReactNode;
|
|
230
|
-
}
|
|
231
223
|
//# sourceMappingURL=base.d.ts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "1.
|
|
1
|
+
export declare const version = "1.30.1";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/esm/src/version.js
CHANGED
|
@@ -170,6 +170,11 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
170
170
|
chainId: chainId,
|
|
171
171
|
});
|
|
172
172
|
if (!(status === "disconnected" && prevStatus === "connected")) return [3 /*break*/, 4];
|
|
173
|
+
// Clear central chain state regardless of autocapture so a later
|
|
174
|
+
// event can't carry a stale excluded/!excluded chainId.
|
|
175
|
+
this.formo.syncWalletState({
|
|
176
|
+
chainId: this.trackingState.lastChainId,
|
|
177
|
+
});
|
|
173
178
|
if (!this.formo.isAutocaptureEnabled("disconnect")) return [3 /*break*/, 3];
|
|
174
179
|
return [4 /*yield*/, this.formo.disconnect({
|
|
175
180
|
chainId: this.trackingState.lastChainId,
|
|
@@ -187,6 +192,9 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
187
192
|
if (!(address && chainId !== undefined)) return [3 /*break*/, 6];
|
|
188
193
|
this.trackingState.lastAddress = address;
|
|
189
194
|
this.trackingState.lastChainId = chainId;
|
|
195
|
+
// Sync central state unconditionally so tracking.excludeChains
|
|
196
|
+
// is enforced even when connect autocapture is disabled.
|
|
197
|
+
this.formo.syncWalletState({ chainId: chainId, address: address });
|
|
190
198
|
if (!this.formo.isAutocaptureEnabled("connect")) return [3 /*break*/, 6];
|
|
191
199
|
connectorName = this.getConnectorName(state);
|
|
192
200
|
return [4 /*yield*/, this.formo.connect({ chainId: chainId, address: address }, __assign({}, (connectorName && { providerName: connectorName })))];
|
|
@@ -235,6 +243,9 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
235
243
|
address: address,
|
|
236
244
|
});
|
|
237
245
|
this.trackingState.lastChainId = chainId;
|
|
246
|
+
// Sync central state unconditionally so a chain switch to an
|
|
247
|
+
// excluded chain is honored even when chain autocapture is disabled.
|
|
248
|
+
this.formo.syncWalletState({ chainId: chainId, address: address });
|
|
238
249
|
if (!this.formo.isAutocaptureEnabled("chain")) return [3 /*break*/, 4];
|
|
239
250
|
_a.label = 1;
|
|
240
251
|
case 1:
|
|
@@ -356,14 +367,21 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
356
367
|
logger.warn("WagmiEventHandler: Transaction receipt query but no hash found");
|
|
357
368
|
return;
|
|
358
369
|
}
|
|
359
|
-
// Retrieve stored transaction details from BROADCASTED event
|
|
360
|
-
// Normalize hash to lowercase for consistent lookup
|
|
370
|
+
// Retrieve stored transaction details from the BROADCASTED event.
|
|
371
|
+
// Normalize hash to lowercase for consistent lookup.
|
|
361
372
|
var normalizedHash = transactionHash.toLowerCase();
|
|
362
373
|
var pendingTx = this.pendingTransactions.get(normalizedHash);
|
|
363
|
-
//
|
|
364
|
-
//
|
|
365
|
-
//
|
|
366
|
-
|
|
374
|
+
// Only emit receipt-derived events for a hash we actually observed
|
|
375
|
+
// being broadcast through this handler. The QueryClient is supplied
|
|
376
|
+
// by the host app and its cache can be written by app code or other
|
|
377
|
+
// deps, so without this gate a forged waitForTransactionReceipt
|
|
378
|
+
// entry could fabricate a confirmed/reverted transaction for an
|
|
379
|
+
// arbitrary hash. No pendingTx → not our broadcast → ignore.
|
|
380
|
+
if (!pendingTx) {
|
|
381
|
+
logger.debug("WagmiEventHandler: Receipt for unobserved tx hash; ignoring", { transactionHash: transactionHash });
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
var address = pendingTx.address;
|
|
367
385
|
if (!address) {
|
|
368
386
|
logger.warn("WagmiEventHandler: Transaction receipt query but no address available");
|
|
369
387
|
return;
|
|
@@ -371,9 +389,13 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
371
389
|
try {
|
|
372
390
|
// Extract receipt data
|
|
373
391
|
var receipt = state.data;
|
|
374
|
-
//
|
|
375
|
-
//
|
|
376
|
-
|
|
392
|
+
// Only act on an explicit on-chain outcome. A missing/unknown
|
|
393
|
+
// status must NOT be treated as a confirmation.
|
|
394
|
+
if ((receipt === null || receipt === void 0 ? void 0 : receipt.status) !== "success" && (receipt === null || receipt === void 0 ? void 0 : receipt.status) !== "reverted") {
|
|
395
|
+
logger.debug("WagmiEventHandler: Receipt without explicit success/reverted status; ignoring", { transactionHash: transactionHash, status: receipt === null || receipt === void 0 ? void 0 : receipt.status });
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
var txStatus = receipt.status === "reverted"
|
|
377
399
|
? TransactionStatus.REVERTED
|
|
378
400
|
: TransactionStatus.CONFIRMED;
|
|
379
401
|
logger.info("WagmiEventHandler: Tracking transaction confirmation", {
|
|
@@ -452,15 +474,13 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
452
474
|
return;
|
|
453
475
|
}
|
|
454
476
|
try {
|
|
455
|
-
// Map Wagmi mutation status to Formo signature status
|
|
477
|
+
// Map Wagmi mutation status to Formo signature status.
|
|
456
478
|
var status_1;
|
|
457
|
-
var signatureHash = void 0;
|
|
458
479
|
if (state.status === "pending") {
|
|
459
480
|
status_1 = SignatureStatus.REQUESTED;
|
|
460
481
|
}
|
|
461
482
|
else if (state.status === "success") {
|
|
462
483
|
status_1 = SignatureStatus.CONFIRMED;
|
|
463
|
-
signatureHash = state.data;
|
|
464
484
|
}
|
|
465
485
|
else if (state.status === "error") {
|
|
466
486
|
status_1 = SignatureStatus.REJECTED;
|
|
@@ -468,13 +488,11 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
468
488
|
else {
|
|
469
489
|
return; // Ignore idle state
|
|
470
490
|
}
|
|
471
|
-
// Extract message from variables
|
|
472
491
|
var message = void 0;
|
|
473
492
|
if (mutationType === "signMessage") {
|
|
474
493
|
message = variables.message || "";
|
|
475
494
|
}
|
|
476
495
|
else {
|
|
477
|
-
// For signTypedData, stringify the typed data
|
|
478
496
|
message = JSON.stringify(variables.message || variables.types || {});
|
|
479
497
|
}
|
|
480
498
|
logger.info("WagmiEventHandler: Tracking signature event", {
|
|
@@ -483,7 +501,12 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
483
501
|
address: address,
|
|
484
502
|
chainId: chainId,
|
|
485
503
|
});
|
|
486
|
-
this.formo.signature(
|
|
504
|
+
this.formo.signature({
|
|
505
|
+
status: status_1,
|
|
506
|
+
chainId: chainId,
|
|
507
|
+
address: address,
|
|
508
|
+
message: message,
|
|
509
|
+
});
|
|
487
510
|
}
|
|
488
511
|
catch (error) {
|
|
489
512
|
logger.error("WagmiEventHandler: Error handling signature mutation:", error);
|