@formo/analytics 1.28.1 → 1.28.3
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 +3 -2
- package/dist/cjs/src/FormoAnalytics.js +19 -11
- package/dist/cjs/src/FormoAnalyticsProvider.js +1 -0
- package/dist/cjs/src/consent/index.js +12 -10
- package/dist/cjs/src/event/EventFactory.d.ts +1 -1
- package/dist/cjs/src/event/EventFactory.js +9 -9
- package/dist/cjs/src/event/utils.d.ts +2 -3
- package/dist/cjs/src/event/utils.js +24 -24
- package/dist/cjs/src/queue/EventQueue.d.ts +1 -1
- package/dist/cjs/src/queue/EventQueue.js +21 -20
- package/dist/cjs/src/session/index.d.ts +0 -9
- package/dist/cjs/src/session/index.js +7 -0
- package/dist/cjs/src/solana/SolanaAdapter.d.ts +3 -4
- package/dist/cjs/src/solana/SolanaAdapter.js +42 -29
- package/dist/cjs/src/storage/StorageManager.js +11 -3
- package/dist/cjs/src/storage/built-in/cookie.js +29 -3
- package/dist/cjs/src/storage/cookiePolicy.d.ts +10 -0
- package/dist/cjs/src/storage/cookiePolicy.js +27 -0
- package/dist/cjs/src/types/base.d.ts +12 -0
- package/dist/cjs/src/types/events.d.ts +0 -1
- package/dist/cjs/src/utils/address.js +4 -6
- package/dist/cjs/src/utils/domain.d.ts +27 -0
- package/dist/cjs/src/utils/domain.js +74 -0
- package/dist/cjs/src/utils/generate.js +23 -11
- package/dist/cjs/src/utils/index.d.ts +0 -1
- package/dist/cjs/src/utils/index.js +0 -1
- package/dist/cjs/src/validators/network.js +7 -2
- package/dist/cjs/src/version.d.ts +1 -1
- package/dist/cjs/src/version.js +1 -1
- package/dist/cjs/src/wagmi/WagmiEventHandler.js +12 -9
- package/dist/esm/src/FormoAnalytics.d.ts +3 -2
- package/dist/esm/src/FormoAnalytics.js +19 -11
- package/dist/esm/src/FormoAnalyticsProvider.js +1 -0
- package/dist/esm/src/consent/index.js +12 -10
- package/dist/esm/src/event/EventFactory.d.ts +1 -1
- package/dist/esm/src/event/EventFactory.js +9 -9
- package/dist/esm/src/event/utils.d.ts +2 -3
- package/dist/esm/src/event/utils.js +25 -24
- package/dist/esm/src/queue/EventQueue.d.ts +1 -1
- package/dist/esm/src/queue/EventQueue.js +21 -20
- package/dist/esm/src/session/index.d.ts +0 -9
- package/dist/esm/src/session/index.js +7 -0
- package/dist/esm/src/solana/SolanaAdapter.d.ts +3 -4
- package/dist/esm/src/solana/SolanaAdapter.js +42 -29
- package/dist/esm/src/storage/StorageManager.js +11 -3
- package/dist/esm/src/storage/built-in/cookie.js +29 -3
- package/dist/esm/src/storage/cookiePolicy.d.ts +10 -0
- package/dist/esm/src/storage/cookiePolicy.js +24 -0
- package/dist/esm/src/types/base.d.ts +12 -0
- package/dist/esm/src/types/events.d.ts +0 -1
- package/dist/esm/src/utils/address.js +4 -6
- package/dist/esm/src/utils/domain.d.ts +27 -0
- package/dist/esm/src/utils/domain.js +70 -0
- package/dist/esm/src/utils/generate.js +23 -11
- package/dist/esm/src/utils/index.d.ts +0 -1
- package/dist/esm/src/utils/index.js +0 -1
- package/dist/esm/src/validators/network.js +7 -2
- package/dist/esm/src/version.d.ts +1 -1
- package/dist/esm/src/version.js +1 -1
- package/dist/esm/src/wagmi/WagmiEventHandler.js +12 -9
- package/dist/index.umd.min.js +1 -1
- package/package.json +1 -1
- package/dist/cjs/src/utils/builderCode.d.ts +0 -30
- package/dist/cjs/src/utils/builderCode.js +0 -143
- package/dist/esm/src/utils/builderCode.d.ts +0 -30
- package/dist/esm/src/utils/builderCode.js +0 -140
|
@@ -58,7 +58,6 @@ exports.WagmiEventHandler = void 0;
|
|
|
58
58
|
var events_1 = require("../types/events");
|
|
59
59
|
var logger_1 = require("../logger");
|
|
60
60
|
var utils_1 = require("./utils");
|
|
61
|
-
var builderCode_1 = require("../utils/builderCode");
|
|
62
61
|
/**
|
|
63
62
|
* Built-in transaction fields that could collide with function args.
|
|
64
63
|
* Defined at module level to avoid recreating on every method call.
|
|
@@ -73,7 +72,6 @@ var RESERVED_FIELDS = new Set([
|
|
|
73
72
|
"transactionHash",
|
|
74
73
|
"function_name",
|
|
75
74
|
"function_args",
|
|
76
|
-
"builder_codes",
|
|
77
75
|
]);
|
|
78
76
|
/**
|
|
79
77
|
* Clean up old entries from a Set to prevent memory leaks.
|
|
@@ -388,7 +386,7 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
388
386
|
chainId: chainId,
|
|
389
387
|
blockNumber: (_a = receipt === null || receipt === void 0 ? void 0 : receipt.blockNumber) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
390
388
|
});
|
|
391
|
-
this.formo.transaction(__assign(__assign(__assign(__assign(__assign(
|
|
389
|
+
this.formo.transaction(__assign(__assign(__assign(__assign(__assign({ status: txStatus, chainId: chainId || 0, address: address, transactionHash: transactionHash }, ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.data) && { data: pendingTx.data })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.to) && { to: pendingTx.to })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.value) && { value: pendingTx.value })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.function_name) && { function_name: pendingTx.function_name })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.function_args) && { function_args: pendingTx.function_args })),
|
|
392
390
|
// Spread function args as additional properties (only colliding keys are prefixed)
|
|
393
391
|
pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.safeFunctionArgs);
|
|
394
392
|
// Clean up the pending transaction after confirmation
|
|
@@ -551,7 +549,7 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
551
549
|
// Encode the function data synchronously if viem is available
|
|
552
550
|
var encodedData = (0, utils_1.encodeWriteContractData)(abi, fnName, args);
|
|
553
551
|
if (encodedData) {
|
|
554
|
-
// Include dataSuffix (ERC-8021 builder code) so
|
|
552
|
+
// Include dataSuffix (e.g. ERC-8021 builder code) so full calldata is sent to server
|
|
555
553
|
data = (0, utils_1.concatCalldataWithSuffix)(encodedData, dataSuffix);
|
|
556
554
|
logger_1.logger.debug("WagmiEventHandler: Encoded writeContract data", data.substring(0, 10));
|
|
557
555
|
}
|
|
@@ -563,9 +561,14 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
563
561
|
data = variables.data;
|
|
564
562
|
to = variables.to;
|
|
565
563
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
564
|
+
logger_1.logger.info("WagmiEventHandler: Tracking transaction event", {
|
|
565
|
+
status: status_2,
|
|
566
|
+
mutationType: mutationType,
|
|
567
|
+
address: userAddress,
|
|
568
|
+
chainId: chainId,
|
|
569
|
+
transactionHash: transactionHash,
|
|
570
|
+
function_name: function_name,
|
|
571
|
+
});
|
|
569
572
|
// Build safeFunctionArgs with collision handling and struct flattening
|
|
570
573
|
var safeFunctionArgs = (0, utils_1.buildSafeFunctionArgs)(function_args, RESERVED_FIELDS);
|
|
571
574
|
// Store transaction details for BROADCASTED status to use in CONFIRMED/REVERTED
|
|
@@ -573,7 +576,7 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
573
576
|
// Include the sender address to handle wallet switches between broadcast and confirmation
|
|
574
577
|
if (status_2 === events_1.TransactionStatus.BROADCASTED && transactionHash) {
|
|
575
578
|
var normalizedHash = transactionHash.toLowerCase();
|
|
576
|
-
var txDetails = __assign(__assign(__assign(__assign(__assign(__assign(
|
|
579
|
+
var txDetails = __assign(__assign(__assign(__assign(__assign(__assign({ address: userAddress }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })), (safeFunctionArgs && { safeFunctionArgs: safeFunctionArgs }));
|
|
577
580
|
this.pendingTransactions.set(normalizedHash, txDetails);
|
|
578
581
|
logger_1.logger.debug("WagmiEventHandler: Stored pending transaction for confirmation", {
|
|
579
582
|
transactionHash: normalizedHash,
|
|
@@ -587,7 +590,7 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
587
590
|
}
|
|
588
591
|
}
|
|
589
592
|
}
|
|
590
|
-
this.formo.transaction(__assign(__assign(__assign(__assign(__assign(__assign(
|
|
593
|
+
this.formo.transaction(__assign(__assign(__assign(__assign(__assign(__assign({ status: status_2, chainId: chainId || 0, address: userAddress }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (transactionHash && { transactionHash: transactionHash })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })),
|
|
591
594
|
// Spread function args as additional properties (only colliding keys are prefixed)
|
|
592
595
|
safeFunctionArgs);
|
|
593
596
|
}
|
|
@@ -45,6 +45,8 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
45
45
|
* When true, EIP-1193 provider wrapping is skipped
|
|
46
46
|
*/
|
|
47
47
|
private isWagmiMode;
|
|
48
|
+
/** Instance-level flag so multiple SDK instances don't interfere. */
|
|
49
|
+
private crossSubdomainCookies;
|
|
48
50
|
config: Config;
|
|
49
51
|
currentChainId?: ChainID;
|
|
50
52
|
currentAddress?: Address;
|
|
@@ -150,7 +152,7 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
150
152
|
* @param {(...args: unknown[]) => void} callback
|
|
151
153
|
* @returns {Promise<void>}
|
|
152
154
|
*/
|
|
153
|
-
transaction({ status, chainId, address, data, to, value, transactionHash, function_name, function_args,
|
|
155
|
+
transaction({ status, chainId, address, data, to, value, transactionHash, function_name, function_args, }: {
|
|
154
156
|
status: TransactionStatus;
|
|
155
157
|
chainId: ChainID;
|
|
156
158
|
address: Address;
|
|
@@ -160,7 +162,6 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
160
162
|
transactionHash?: string;
|
|
161
163
|
function_name?: string;
|
|
162
164
|
function_args?: Record<string, unknown>;
|
|
163
|
-
builder_codes?: string;
|
|
164
165
|
}, properties?: IFormoEventProperties, context?: IFormoEventContext, callback?: (...args: unknown[]) => void): Promise<void>;
|
|
165
166
|
/**
|
|
166
167
|
* Emits an identify event with current wallet address and provider info.
|
|
@@ -57,6 +57,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
57
57
|
import { createStore } from "mipd";
|
|
58
58
|
import { EVENTS_API_HOST, EventType, LOCAL_ANONYMOUS_ID_KEY, SESSION_CURRENT_URL_KEY, SESSION_USER_ID_KEY, CONSENT_OPT_OUT_KEY, } from "./constants";
|
|
59
59
|
import { cookie, initStorageManager } from "./storage";
|
|
60
|
+
import { getIdentityCookieDomain } from "./storage/cookiePolicy";
|
|
60
61
|
import { EventManager } from "./event";
|
|
61
62
|
import { EventQueue } from "./queue";
|
|
62
63
|
import { logger, Logger } from "./logger";
|
|
@@ -65,7 +66,6 @@ import { detectInjectedProviderInfo, isValidProvider } from "./provider";
|
|
|
65
66
|
import { FormoAnalyticsSession, SESSION_WALLET_DETECTED_KEY, SESSION_WALLET_IDENTIFIED_KEY, } from "./session";
|
|
66
67
|
import { SignatureStatus, TransactionStatus, WRAPPED_REQUEST_SYMBOL, WRAPPED_REQUEST_REF_SYMBOL, } from "./types";
|
|
67
68
|
import { validateAddress, validateAndChecksumAddress } from "./utils/address";
|
|
68
|
-
import { extractBuilderCodes } from "./utils/builderCode";
|
|
69
69
|
import { isLocalhost } from "./validators";
|
|
70
70
|
import { parseChainId } from "./utils/chain";
|
|
71
71
|
import { WagmiEventHandler } from "./wagmi";
|
|
@@ -82,7 +82,7 @@ var PROVIDER_SWITCH_REASONS = {
|
|
|
82
82
|
var FormoAnalytics = /** @class */ (function () {
|
|
83
83
|
function FormoAnalytics(writeKey, options) {
|
|
84
84
|
if (options === void 0) { options = {}; }
|
|
85
|
-
var _a, _b;
|
|
85
|
+
var _a, _b, _c;
|
|
86
86
|
this.writeKey = writeKey;
|
|
87
87
|
this.options = options;
|
|
88
88
|
// Per-chain namespace state — isolates EVM and Solana connection state
|
|
@@ -121,6 +121,9 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
121
121
|
this.options = options;
|
|
122
122
|
// Check if Wagmi mode is enabled
|
|
123
123
|
this.isWagmiMode = !!options.wagmi;
|
|
124
|
+
this.crossSubdomainCookies = (_a = options.crossSubdomainCookies) !== null && _a !== void 0 ? _a : true;
|
|
125
|
+
// Normalize so downstream consumers (EventFactory) read the resolved value.
|
|
126
|
+
options.crossSubdomainCookies = this.crossSubdomainCookies;
|
|
124
127
|
this.session = new FormoAnalyticsSession();
|
|
125
128
|
this.currentUserId =
|
|
126
129
|
cookie().get(SESSION_USER_ID_KEY) || undefined;
|
|
@@ -135,8 +138,8 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
135
138
|
this.isAutocaptureEnabled = this.isAutocaptureEnabled.bind(this);
|
|
136
139
|
// Initialize logger with configuration from options
|
|
137
140
|
Logger.init({
|
|
138
|
-
enabled: ((
|
|
139
|
-
enabledLevels: ((
|
|
141
|
+
enabled: ((_b = options.logger) === null || _b === void 0 ? void 0 : _b.enabled) || false,
|
|
142
|
+
enabledLevels: ((_c = options.logger) === null || _c === void 0 ? void 0 : _c.levels) || [],
|
|
140
143
|
});
|
|
141
144
|
this.eventManager = new EventManager(new EventQueue(this.config.writeKey, {
|
|
142
145
|
apiHost: options.apiHost || EVENTS_API_HOST,
|
|
@@ -465,10 +468,10 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
465
468
|
*/
|
|
466
469
|
FormoAnalytics.prototype.transaction = function (_a, properties_1, context_1, callback_1) {
|
|
467
470
|
return __awaiter(this, arguments, void 0, function (_b, properties, context, callback) {
|
|
468
|
-
var status = _b.status, chainId = _b.chainId, address = _b.address, data = _b.data, to = _b.to, value = _b.value, transactionHash = _b.transactionHash, function_name = _b.function_name, function_args = _b.function_args
|
|
471
|
+
var status = _b.status, chainId = _b.chainId, address = _b.address, data = _b.data, to = _b.to, value = _b.value, transactionHash = _b.transactionHash, function_name = _b.function_name, function_args = _b.function_args;
|
|
469
472
|
return __generator(this, function (_c) {
|
|
470
473
|
switch (_c.label) {
|
|
471
|
-
case 0: return [4 /*yield*/, this.trackEvent(EventType.TRANSACTION, __assign(__assign(__assign(
|
|
474
|
+
case 0: return [4 /*yield*/, this.trackEvent(EventType.TRANSACTION, __assign(__assign(__assign({ status: status, chainId: chainId, address: address, data: data, to: to, value: value }, (transactionHash && { transactionHash: transactionHash })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })), properties, context, callback)];
|
|
472
475
|
case 1:
|
|
473
476
|
_c.sent();
|
|
474
477
|
return [2 /*return*/];
|
|
@@ -506,7 +509,7 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
506
509
|
*/
|
|
507
510
|
FormoAnalytics.prototype.identify = function (params, properties, context, callback) {
|
|
508
511
|
return __awaiter(this, void 0, void 0, function () {
|
|
509
|
-
var _i, _a, providerDetail, provider, address_1, validAddress_1, err_1, address, providerName, userId, rdns, validAddress, isAlreadyIdentified, e_1;
|
|
512
|
+
var _i, _a, providerDetail, provider, address_1, validAddress_1, err_1, address, providerName, userId, rdns, validAddress, domain, isAlreadyIdentified, e_1;
|
|
510
513
|
var _b, _c;
|
|
511
514
|
return __generator(this, function (_d) {
|
|
512
515
|
switch (_d.label) {
|
|
@@ -585,7 +588,8 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
585
588
|
}
|
|
586
589
|
if (userId) {
|
|
587
590
|
this.currentUserId = userId;
|
|
588
|
-
|
|
591
|
+
domain = getIdentityCookieDomain(this.crossSubdomainCookies);
|
|
592
|
+
cookie().set(SESSION_USER_ID_KEY, userId, __assign({ path: "/" }, (domain ? { domain: domain } : {})));
|
|
589
593
|
}
|
|
590
594
|
isAlreadyIdentified = this.session.isWalletIdentified(validAddress, rdns || "");
|
|
591
595
|
logger.debug("Identify: Checking deduplication", {
|
|
@@ -1900,7 +1904,7 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1900
1904
|
};
|
|
1901
1905
|
FormoAnalytics.prototype.buildTransactionEventPayload = function (params, provider) {
|
|
1902
1906
|
return __awaiter(this, void 0, void 0, function () {
|
|
1903
|
-
var _a, data, from, to, value, validAddress,
|
|
1907
|
+
var _a, data, from, to, value, validAddress, _b;
|
|
1904
1908
|
var _c;
|
|
1905
1909
|
return __generator(this, function (_d) {
|
|
1906
1910
|
switch (_d.label) {
|
|
@@ -1910,7 +1914,6 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1910
1914
|
if (!validAddress) {
|
|
1911
1915
|
throw new Error("Invalid address in transaction payload: ".concat(from));
|
|
1912
1916
|
}
|
|
1913
|
-
builder_codes = extractBuilderCodes(data);
|
|
1914
1917
|
_c = {};
|
|
1915
1918
|
_b = this._evmChainId;
|
|
1916
1919
|
if (_b) return [3 /*break*/, 2];
|
|
@@ -1918,7 +1921,12 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
1918
1921
|
case 1:
|
|
1919
1922
|
_b = (_d.sent());
|
|
1920
1923
|
_d.label = 2;
|
|
1921
|
-
case 2: return [2 /*return*/,
|
|
1924
|
+
case 2: return [2 /*return*/, (_c.chainId = _b,
|
|
1925
|
+
_c.data = data,
|
|
1926
|
+
_c.address = validAddress,
|
|
1927
|
+
_c.to = to,
|
|
1928
|
+
_c.value = value,
|
|
1929
|
+
_c)];
|
|
1922
1930
|
}
|
|
1923
1931
|
});
|
|
1924
1932
|
});
|
|
@@ -95,6 +95,7 @@ var InitializedAnalytics = function (_a) {
|
|
|
95
95
|
var serializableOptions = {
|
|
96
96
|
tracking: options.tracking,
|
|
97
97
|
autocapture: options.autocapture,
|
|
98
|
+
crossSubdomainCookies: options.crossSubdomainCookies,
|
|
98
99
|
apiHost: options.apiHost,
|
|
99
100
|
flushAt: options.flushAt,
|
|
100
101
|
flushInterval: options.flushInterval,
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* Formo projects on the same domain.
|
|
8
8
|
*/
|
|
9
9
|
import { secureHash } from '../utils/hash';
|
|
10
|
+
import { getApexDomain } from '../utils/domain';
|
|
10
11
|
/**
|
|
11
12
|
* Generate a project-specific cookie key to avoid conflicts between different Formo projects
|
|
12
13
|
* Uses hashed writeKey for privacy and security
|
|
@@ -36,7 +37,14 @@ export function setConsentFlag(projectId, key, value) {
|
|
|
36
37
|
var expires = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toUTCString(); // 1 year (GDPR compliant)
|
|
37
38
|
var isSecure = ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.protocol) === 'https:';
|
|
38
39
|
// Enhanced privacy settings: Secure (HTTPS), SameSite=Strict for consent cookies
|
|
39
|
-
|
|
40
|
+
var domain = getApexDomain();
|
|
41
|
+
var domainAttr = domain ? "; domain=.".concat(domain) : '';
|
|
42
|
+
// Expire any legacy host-only cookie (pre-domain-attribute versions) so it
|
|
43
|
+
// doesn't shadow the new domain-wide cookie in document.cookie reads.
|
|
44
|
+
if (domain) {
|
|
45
|
+
document.cookie = "".concat(projectSpecificKey, "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;");
|
|
46
|
+
}
|
|
47
|
+
document.cookie = "".concat(projectSpecificKey, "=").concat(encodeURIComponent(value), "; expires=").concat(expires, "; path=/").concat(domainAttr, "; SameSite=Strict").concat(isSecure ? '; Secure' : '');
|
|
40
48
|
}
|
|
41
49
|
}
|
|
42
50
|
/**
|
|
@@ -83,15 +91,9 @@ function deleteCookieDirectly(cookieName) {
|
|
|
83
91
|
// Clear from current domain/path
|
|
84
92
|
document.cookie = "".concat(cookieName, "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;");
|
|
85
93
|
// Try to clear from parent domain if it's a proper multi-level domain
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// Only try parent domain deletion for proper domains with multiple parts
|
|
90
|
-
// Skip localhost and single-level domains
|
|
91
|
-
if (parts.length >= 2 && hostname !== 'localhost') {
|
|
92
|
-
var domain = parts.slice(-2).join('.');
|
|
93
|
-
document.cookie = "".concat(cookieName, "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.").concat(domain, ";");
|
|
94
|
-
}
|
|
94
|
+
var domain = getApexDomain();
|
|
95
|
+
if (domain) {
|
|
96
|
+
document.cookie = "".concat(cookieName, "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.").concat(domain, ";");
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
//# sourceMappingURL=index.js.map
|
|
@@ -35,7 +35,7 @@ declare class EventFactory implements IEventFactory {
|
|
|
35
35
|
generateDisconnectEvent(chainId?: ChainID, address?: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
|
|
36
36
|
generateChainChangedEvent(chainId: ChainID, address: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
|
|
37
37
|
generateSignatureEvent(status: SignatureStatus, chainId: ChainID, address: Address, message: string, signatureHash?: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
|
|
38
|
-
generateTransactionEvent(status: TransactionStatus, chainId: ChainID, address: Address, data?: string, to?: string, value?: string, transactionHash?: string, function_name?: string, function_args?: Record<string, unknown>,
|
|
38
|
+
generateTransactionEvent(status: TransactionStatus, chainId: ChainID, address: Address, data?: string, to?: string, value?: string, transactionHash?: string, function_name?: string, function_args?: Record<string, unknown>, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
|
|
39
39
|
generateTrackEvent(event: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
|
|
40
40
|
create(event: APIEvent, address?: Address, userId?: string): Promise<IFormoEvent>;
|
|
41
41
|
}
|
|
@@ -289,22 +289,22 @@ var EventFactory = /** @class */ (function () {
|
|
|
289
289
|
return __awaiter(this, void 0, void 0, function () {
|
|
290
290
|
var commonEventData, eventChainId, validAddress, processedEvent;
|
|
291
291
|
var _a;
|
|
292
|
-
var _b;
|
|
293
|
-
return __generator(this, function (
|
|
294
|
-
switch (
|
|
292
|
+
var _b, _c;
|
|
293
|
+
return __generator(this, function (_d) {
|
|
294
|
+
switch (_d.label) {
|
|
295
295
|
case 0:
|
|
296
296
|
_a = {};
|
|
297
297
|
return [4 /*yield*/, this.generateContext(context)];
|
|
298
298
|
case 1:
|
|
299
|
-
commonEventData = (_a.context =
|
|
299
|
+
commonEventData = (_a.context = _d.sent(),
|
|
300
300
|
_a.original_timestamp = getCurrentTimeFormatted(),
|
|
301
301
|
_a.user_id = formoEvent.user_id,
|
|
302
302
|
_a.type = formoEvent.type,
|
|
303
303
|
_a.channel = CHANNEL,
|
|
304
304
|
_a.version = VERSION,
|
|
305
305
|
_a);
|
|
306
|
-
commonEventData.anonymous_id = generateAnonymousId(LOCAL_ANONYMOUS_ID_KEY);
|
|
307
|
-
eventChainId = (
|
|
306
|
+
commonEventData.anonymous_id = generateAnonymousId(LOCAL_ANONYMOUS_ID_KEY, (_b = this.options) === null || _b === void 0 ? void 0 : _b.crossSubdomainCookies);
|
|
307
|
+
eventChainId = (_c = formoEvent.properties) === null || _c === void 0 ? void 0 : _c.chainId;
|
|
308
308
|
validAddress = this.validateEventAddress(formoEvent.address, eventChainId);
|
|
309
309
|
commonEventData.address = validAddress;
|
|
310
310
|
processedEvent = mergeDeepRight(formoEvent, commonEventData);
|
|
@@ -413,12 +413,12 @@ var EventFactory = /** @class */ (function () {
|
|
|
413
413
|
});
|
|
414
414
|
});
|
|
415
415
|
};
|
|
416
|
-
EventFactory.prototype.generateTransactionEvent = function (status, chainId, address, data, to, value, transactionHash, function_name, function_args,
|
|
416
|
+
EventFactory.prototype.generateTransactionEvent = function (status, chainId, address, data, to, value, transactionHash, function_name, function_args, properties, context) {
|
|
417
417
|
return __awaiter(this, void 0, void 0, function () {
|
|
418
418
|
var transactionEvent;
|
|
419
419
|
return __generator(this, function (_a) {
|
|
420
420
|
transactionEvent = {
|
|
421
|
-
properties: __assign(__assign(__assign(__assign(__assign(__assign(__assign(
|
|
421
|
+
properties: __assign(__assign(__assign(__assign(__assign(__assign(__assign({ status: status, chainId: chainId }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (transactionHash && { transactionHash: transactionHash })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })), properties),
|
|
422
422
|
address: address,
|
|
423
423
|
type: "transaction",
|
|
424
424
|
};
|
|
@@ -497,7 +497,7 @@ var EventFactory = /** @class */ (function () {
|
|
|
497
497
|
case 14:
|
|
498
498
|
formoEvent = _b.sent();
|
|
499
499
|
return [3 /*break*/, 19];
|
|
500
|
-
case 15: return [4 /*yield*/, this.generateTransactionEvent(event.status, event.chainId, event.address, event.data, event.to, event.value, event.transactionHash, event.function_name, event.function_args, event.
|
|
500
|
+
case 15: return [4 /*yield*/, this.generateTransactionEvent(event.status, event.chainId, event.address, event.data, event.to, event.value, event.transactionHash, event.function_name, event.function_args, event.properties, event.context)];
|
|
501
501
|
case 16:
|
|
502
502
|
formoEvent = _b.sent();
|
|
503
503
|
return [3 /*break*/, 19];
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AnonymousID } from "../types";
|
|
2
|
-
declare const generateAnonymousId: (key: string) => AnonymousID;
|
|
3
|
-
|
|
4
|
-
export { generateAnonymousId, getCookieDomain };
|
|
2
|
+
declare const generateAnonymousId: (key: string, crossSubdomainCookies?: boolean) => AnonymousID;
|
|
3
|
+
export { generateAnonymousId };
|
|
5
4
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
1
12
|
import { generateNativeUUID } from "../utils";
|
|
2
13
|
import { cookie } from "../storage";
|
|
3
|
-
|
|
14
|
+
import { getIdentityCookieDomain } from "../storage/cookiePolicy";
|
|
15
|
+
var generateAnonymousId = function (key, crossSubdomainCookies) {
|
|
4
16
|
var storedAnonymousId = cookie().get(key);
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
var anonymousId = (storedAnonymousId && typeof storedAnonymousId === "string"
|
|
18
|
+
? storedAnonymousId
|
|
19
|
+
: generateNativeUUID());
|
|
20
|
+
var domain = getIdentityCookieDomain(crossSubdomainCookies);
|
|
21
|
+
// Re-set the cookie with the configured scope. When crossSubdomainCookies
|
|
22
|
+
// is true, this migrates legacy host-only cookies on the current host to the apex
|
|
23
|
+
// domain. Note: host-only cookies on other hosts (e.g. a cookie set on
|
|
24
|
+
// example.com is not visible from app.example.com) cannot be migrated
|
|
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 } : {})));
|
|
27
|
+
return anonymousId;
|
|
14
28
|
};
|
|
15
|
-
|
|
16
|
-
if (hostname === void 0) { hostname = window.location.hostname; }
|
|
17
|
-
// Special cases
|
|
18
|
-
if (hostname.includes("localhost") ||
|
|
19
|
-
/^\d{1,3}(\.\d{1,3}){3}$/.test(hostname)) {
|
|
20
|
-
// Localhost or IP address
|
|
21
|
-
return "";
|
|
22
|
-
}
|
|
23
|
-
var parts = hostname.split(".");
|
|
24
|
-
if (parts.includes("www"))
|
|
25
|
-
parts.splice(parts.indexOf("www"), 1);
|
|
26
|
-
return ".".concat(parts.join("."));
|
|
27
|
-
}
|
|
28
|
-
export { generateAnonymousId, getCookieDomain };
|
|
29
|
+
export { generateAnonymousId };
|
|
29
30
|
//# sourceMappingURL=utils.js.map
|
|
@@ -28,7 +28,7 @@ export declare class EventQueue implements IEventQueue {
|
|
|
28
28
|
constructor(writeKey: string, options: Options);
|
|
29
29
|
private generateMessageId;
|
|
30
30
|
enqueue(event: IFormoEvent, callback?: (...args: any) => void): Promise<void>;
|
|
31
|
-
flush(callback?: (...args: any) => void): Promise<void | IFormoEventFlushPayload[]>;
|
|
31
|
+
flush(callback?: (...args: any) => void, drainAll?: boolean): Promise<void | IFormoEventFlushPayload[]>;
|
|
32
32
|
/**
|
|
33
33
|
* Returns the UTF-8 byte length of a string. The browser's keepalive limit
|
|
34
34
|
* is enforced on the wire (UTF-8 bytes), not on JS string length (UTF-16
|
|
@@ -118,12 +118,12 @@ var EventQueue = /** @class */ (function () {
|
|
|
118
118
|
});
|
|
119
119
|
// Catches the page being hidden, including scenarios like closing the tab.
|
|
120
120
|
document.addEventListener("pagehide", function () {
|
|
121
|
-
isAccessible = document.visibilityState
|
|
121
|
+
isAccessible = document.visibilityState !== "hidden";
|
|
122
122
|
handleOnLeave();
|
|
123
123
|
});
|
|
124
124
|
// Catches visibility changes, such as switching tabs or minimizing the browser.
|
|
125
125
|
document.addEventListener("visibilitychange", function () {
|
|
126
|
-
isAccessible =
|
|
126
|
+
isAccessible = document.visibilityState !== "hidden";
|
|
127
127
|
if (document.visibilityState === "hidden") {
|
|
128
128
|
handleOnLeave();
|
|
129
129
|
}
|
|
@@ -149,7 +149,7 @@ var EventQueue = /** @class */ (function () {
|
|
|
149
149
|
switch (_a.label) {
|
|
150
150
|
case 0:
|
|
151
151
|
if (!(isAccessible === false)) return [3 /*break*/, 2];
|
|
152
|
-
return [4 /*yield*/, this.flush()];
|
|
152
|
+
return [4 /*yield*/, this.flush(undefined, true)];
|
|
153
153
|
case 1:
|
|
154
154
|
_a.sent();
|
|
155
155
|
_a.label = 2;
|
|
@@ -179,10 +179,8 @@ var EventQueue = /** @class */ (function () {
|
|
|
179
179
|
return [4 /*yield*/, this.generateMessageId(event)];
|
|
180
180
|
case 1:
|
|
181
181
|
message_id = _a.sent();
|
|
182
|
-
return [4 /*yield*/, this.isDuplicate(message_id)];
|
|
183
|
-
case 2:
|
|
184
182
|
// check if the message already exists
|
|
185
|
-
if (
|
|
183
|
+
if (this.isDuplicate(message_id)) {
|
|
186
184
|
logger.warn("Event already enqueued, try again after ".concat(millisecondsToSecond(this.flushIntervalMs), " seconds."));
|
|
187
185
|
return [2 /*return*/];
|
|
188
186
|
}
|
|
@@ -211,10 +209,11 @@ var EventQueue = /** @class */ (function () {
|
|
|
211
209
|
});
|
|
212
210
|
});
|
|
213
211
|
};
|
|
214
|
-
EventQueue.prototype.flush = function (
|
|
215
|
-
return __awaiter(this,
|
|
216
|
-
var items, sentAt, data, batches;
|
|
212
|
+
EventQueue.prototype.flush = function (callback_1) {
|
|
213
|
+
return __awaiter(this, arguments, void 0, function (callback, drainAll) {
|
|
214
|
+
var items, _i, items_1, item, sentAt, data, batches;
|
|
217
215
|
var _this = this;
|
|
216
|
+
if (drainAll === void 0) { drainAll = false; }
|
|
218
217
|
return __generator(this, function (_a) {
|
|
219
218
|
switch (_a.label) {
|
|
220
219
|
case 0:
|
|
@@ -228,13 +227,19 @@ var EventQueue = /** @class */ (function () {
|
|
|
228
227
|
return [2 /*return*/, Promise.resolve()];
|
|
229
228
|
}
|
|
230
229
|
if (!this.pendingFlush) return [3 /*break*/, 2];
|
|
230
|
+
if (!!drainAll) return [3 /*break*/, 2];
|
|
231
231
|
return [4 /*yield*/, this.pendingFlush];
|
|
232
232
|
case 1:
|
|
233
233
|
_a.sent();
|
|
234
234
|
_a.label = 2;
|
|
235
235
|
case 2:
|
|
236
|
-
items = this.queue.splice(0, this.flushAt);
|
|
237
|
-
|
|
236
|
+
items = this.queue.splice(0, drainAll ? this.queue.length : this.flushAt);
|
|
237
|
+
// Only remove hashes for flushed items so duplicate detection remains
|
|
238
|
+
// active for events still in the queue.
|
|
239
|
+
for (_i = 0, items_1 = items; _i < items_1.length; _i++) {
|
|
240
|
+
item = items_1[_i];
|
|
241
|
+
this.payloadHashes.delete(item.message.message_id);
|
|
242
|
+
}
|
|
238
243
|
sentAt = new Date().toISOString();
|
|
239
244
|
data = items.map(function (item) { return (__assign(__assign({}, item.message), { sent_at: sentAt })); });
|
|
240
245
|
batches = this.splitIntoBatches(items, data);
|
|
@@ -396,15 +401,11 @@ var EventQueue = /** @class */ (function () {
|
|
|
396
401
|
return false;
|
|
397
402
|
};
|
|
398
403
|
EventQueue.prototype.isDuplicate = function (eventId) {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
this.payloadHashes.add(eventId);
|
|
405
|
-
return [2 /*return*/, false];
|
|
406
|
-
});
|
|
407
|
-
});
|
|
404
|
+
// check if exists a message with identical payload within 1 minute
|
|
405
|
+
if (this.payloadHashes.has(eventId))
|
|
406
|
+
return true;
|
|
407
|
+
this.payloadHashes.add(eventId);
|
|
408
|
+
return false;
|
|
408
409
|
};
|
|
409
410
|
return EventQueue;
|
|
410
411
|
}());
|
|
@@ -38,15 +38,6 @@ export interface IFormoAnalyticsSession {
|
|
|
38
38
|
*/
|
|
39
39
|
markWalletIdentified(address: string, rdns: string): void;
|
|
40
40
|
}
|
|
41
|
-
/**
|
|
42
|
-
* Implementation of session management using cookies
|
|
43
|
-
*
|
|
44
|
-
* Tracks:
|
|
45
|
-
* - Detected wallets (by RDNS) - to prevent duplicate detection events
|
|
46
|
-
* - Identified wallet-address pairs - to prevent duplicate identification events
|
|
47
|
-
*
|
|
48
|
-
* Session data expires at end of day (86400 seconds).
|
|
49
|
-
*/
|
|
50
41
|
export declare class FormoAnalyticsSession implements IFormoAnalyticsSession {
|
|
51
42
|
/**
|
|
52
43
|
* Generate a unique key for wallet identification tracking
|
|
@@ -22,6 +22,7 @@ export var SESSION_WALLET_IDENTIFIED_KEY = "wallet-identified";
|
|
|
22
22
|
*
|
|
23
23
|
* Session data expires at end of day (86400 seconds).
|
|
24
24
|
*/
|
|
25
|
+
var MAX_SESSION_ENTRIES = 20;
|
|
25
26
|
var FormoAnalyticsSession = /** @class */ (function () {
|
|
26
27
|
function FormoAnalyticsSession() {
|
|
27
28
|
}
|
|
@@ -59,6 +60,9 @@ var FormoAnalyticsSession = /** @class */ (function () {
|
|
|
59
60
|
var rdnses = ((_a = cookie().get(SESSION_WALLET_DETECTED_KEY)) === null || _a === void 0 ? void 0 : _a.split(",")) || [];
|
|
60
61
|
if (!rdnses.includes(rdns)) {
|
|
61
62
|
rdnses.push(rdns);
|
|
63
|
+
if (rdnses.length > MAX_SESSION_ENTRIES) {
|
|
64
|
+
rdnses.splice(0, rdnses.length - MAX_SESSION_ENTRIES);
|
|
65
|
+
}
|
|
62
66
|
cookie().set(SESSION_WALLET_DETECTED_KEY, rdnses.join(","), {
|
|
63
67
|
// Expires by the end of the day
|
|
64
68
|
expires: new Date(Date.now() + 86400 * 1000).toUTCString(),
|
|
@@ -99,6 +103,9 @@ var FormoAnalyticsSession = /** @class */ (function () {
|
|
|
99
103
|
var alreadyExists = identifiedWallets.includes(identifiedKey);
|
|
100
104
|
if (!alreadyExists) {
|
|
101
105
|
identifiedWallets.push(identifiedKey);
|
|
106
|
+
if (identifiedWallets.length > MAX_SESSION_ENTRIES) {
|
|
107
|
+
identifiedWallets.splice(0, identifiedWallets.length - MAX_SESSION_ENTRIES);
|
|
108
|
+
}
|
|
102
109
|
var newValue = identifiedWallets.join(",");
|
|
103
110
|
cookie().set(SESSION_WALLET_IDENTIFIED_KEY, newValue, {
|
|
104
111
|
// Expires by the end of the day
|
|
@@ -26,11 +26,10 @@ export declare class SolanaAdapter {
|
|
|
26
26
|
*/
|
|
27
27
|
private pendingTransactions;
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Per-adapter original methods stored in a WeakMap to prevent routing
|
|
30
|
+
* to the wrong wallet after switching adapters.
|
|
30
31
|
*/
|
|
31
|
-
private
|
|
32
|
-
private originalAdapterSignMessage?;
|
|
33
|
-
private originalAdapterSignTransaction?;
|
|
32
|
+
private adapterOriginals;
|
|
34
33
|
/**
|
|
35
34
|
* Bound wrapper references — used to detect when external code (e.g. StandardWalletAdapter._reset())
|
|
36
35
|
* overwrites our wraps so we can re-apply them.
|