@formo/analytics 1.36.0 → 1.38.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 +64 -0
- package/dist/cjs/src/FormoAnalytics.js +155 -5
- package/dist/cjs/src/FormoAnalyticsProvider.js +1 -0
- package/dist/cjs/src/evm/EvmEventTracker.d.ts +38 -10
- package/dist/cjs/src/evm/EvmEventTracker.js +182 -0
- package/dist/cjs/src/evm/EvmProviderRegistry.js +26 -4
- package/dist/cjs/src/evm/EvmRequestTracker.d.ts +36 -40
- package/dist/cjs/src/evm/EvmRequestTracker.js +216 -115
- package/dist/cjs/src/evm/batch.d.ts +94 -0
- package/dist/cjs/src/evm/batch.js +130 -0
- package/dist/cjs/src/provider/detection.d.ts +30 -0
- package/dist/cjs/src/provider/detection.js +62 -0
- package/dist/cjs/src/provider/index.d.ts +1 -1
- package/dist/cjs/src/provider/index.js +3 -1
- package/dist/cjs/src/types/base.d.ts +23 -0
- package/dist/cjs/src/types/provider.d.ts +16 -0
- package/dist/cjs/src/types/provider.js +17 -1
- package/dist/cjs/src/version.d.ts +1 -1
- package/dist/cjs/src/version.js +1 -1
- package/dist/cjs/src/wagmi/WagmiEventHandler.d.ts +87 -0
- package/dist/cjs/src/wagmi/WagmiEventHandler.js +536 -13
- package/dist/esm/src/FormoAnalytics.d.ts +64 -0
- package/dist/esm/src/FormoAnalytics.js +155 -5
- package/dist/esm/src/FormoAnalyticsProvider.js +1 -0
- package/dist/esm/src/evm/EvmEventTracker.d.ts +38 -10
- package/dist/esm/src/evm/EvmEventTracker.js +183 -1
- package/dist/esm/src/evm/EvmProviderRegistry.js +27 -5
- package/dist/esm/src/evm/EvmRequestTracker.d.ts +36 -40
- package/dist/esm/src/evm/EvmRequestTracker.js +215 -114
- package/dist/esm/src/evm/batch.d.ts +94 -0
- package/dist/esm/src/evm/batch.js +123 -0
- package/dist/esm/src/provider/detection.d.ts +30 -0
- package/dist/esm/src/provider/detection.js +60 -0
- package/dist/esm/src/provider/index.d.ts +1 -1
- package/dist/esm/src/provider/index.js +1 -1
- package/dist/esm/src/types/base.d.ts +23 -0
- package/dist/esm/src/types/provider.d.ts +16 -0
- package/dist/esm/src/types/provider.js +16 -0
- package/dist/esm/src/version.d.ts +1 -1
- package/dist/esm/src/version.js +1 -1
- package/dist/esm/src/wagmi/WagmiEventHandler.d.ts +87 -0
- package/dist/esm/src/wagmi/WagmiEventHandler.js +536 -13
- package/dist/index.umd.min.js +1 -1
- package/package.json +4 -3
|
@@ -57,12 +57,23 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
57
57
|
}
|
|
58
58
|
return t;
|
|
59
59
|
};
|
|
60
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
61
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
62
|
+
if (ar || !(i in from)) {
|
|
63
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
64
|
+
ar[i] = from[i];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
68
|
+
};
|
|
60
69
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
61
70
|
exports.EvmRequestTracker = void 0;
|
|
62
71
|
var logger_1 = require("../logger");
|
|
72
|
+
var provider_1 = require("../provider");
|
|
63
73
|
var chain_1 = require("../utils/chain");
|
|
64
74
|
var address_1 = require("../utils/address");
|
|
65
75
|
var types_1 = require("../types");
|
|
76
|
+
var batch_1 = require("./batch");
|
|
66
77
|
/**
|
|
67
78
|
* Decode a hex-encoded `personal_sign` message.
|
|
68
79
|
*
|
|
@@ -99,6 +110,19 @@ function hexToUtf8(hex) {
|
|
|
99
110
|
* probed - an SDK-issued lookup on a serialising transport can wedge the
|
|
100
111
|
* user's wallet, which is never an acceptable price for a label.
|
|
101
112
|
*/
|
|
113
|
+
/**
|
|
114
|
+
* Providers with a dispatch already on the synchronous call stack.
|
|
115
|
+
*
|
|
116
|
+
* A page can end up with LAYERED Formo wrappers: another library wraps our
|
|
117
|
+
* wrapper, the SDK rebuilds, and the new instance wraps the outer function
|
|
118
|
+
* because the marker is not on it. Both layers route to the same newest
|
|
119
|
+
* live tracker, which would instrument one user request twice. Every
|
|
120
|
+
* dispatch issues its underlying request synchronously (deliberately -
|
|
121
|
+
* the wallet call always goes out first), so an inner shim reached during
|
|
122
|
+
* that window belongs to the SAME user request and passes straight
|
|
123
|
+
* through.
|
|
124
|
+
*/
|
|
125
|
+
var dispatchInFlight = new WeakSet();
|
|
102
126
|
var EvmRequestTracker = /** @class */ (function () {
|
|
103
127
|
function EvmRequestTracker(wallet, registry, deps) {
|
|
104
128
|
this.wallet = wallet;
|
|
@@ -114,12 +138,28 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
114
138
|
*/
|
|
115
139
|
this.polls = new Set();
|
|
116
140
|
this.disposed = false;
|
|
141
|
+
/** Providers whose owner list includes this instance; pruned on cleanup. */
|
|
142
|
+
this.wrappedProviders = new Set();
|
|
117
143
|
}
|
|
118
144
|
/** Stop every poll in flight. Terminal, like the event queue's close(). */
|
|
119
145
|
EvmRequestTracker.prototype.cleanup = function () {
|
|
146
|
+
var _this = this;
|
|
120
147
|
this.disposed = true;
|
|
121
148
|
this.polls.forEach(function (timer) { return clearTimeout(timer); });
|
|
122
149
|
this.polls.clear();
|
|
150
|
+
// Remove this instance from every provider's owner list. The lists
|
|
151
|
+
// live on LONG-LIVED provider objects; leaving disposed trackers in
|
|
152
|
+
// them retains each old instance's whole object graph across rebuilds,
|
|
153
|
+
// growing without bound under HMR.
|
|
154
|
+
this.wrappedProviders.forEach(function (provider) {
|
|
155
|
+
var owners = provider[types_1.WRAPPED_REQUEST_OWNER_SYMBOL];
|
|
156
|
+
if (Array.isArray(owners)) {
|
|
157
|
+
var idx = owners.indexOf(_this);
|
|
158
|
+
if (idx !== -1)
|
|
159
|
+
owners.splice(idx, 1);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
this.wrappedProviders.clear();
|
|
123
163
|
};
|
|
124
164
|
/** Re-arm a poll, unless this tracker has been torn down. */
|
|
125
165
|
EvmRequestTracker.prototype.schedulePoll = function (fn, delayMs) {
|
|
@@ -145,19 +185,118 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
145
185
|
logger_1.logger.error("Provider not found for request (signature, transaction) tracking");
|
|
146
186
|
return false;
|
|
147
187
|
}
|
|
148
|
-
//
|
|
188
|
+
// Already wrapped: take OWNERSHIP rather than skipping. The wrapper
|
|
189
|
+
// survives an SDK rebuild and closes over the instance that installed
|
|
190
|
+
// it, whose queue is closed after cleanup - "skip" made the rebuilt
|
|
191
|
+
// instance report success while every request-derived event died in
|
|
192
|
+
// the dead instance's queue. The wrapper reads the owner slot per call.
|
|
149
193
|
var currentRequest = provider.request;
|
|
150
194
|
if (this.registry.isWrapped(provider, currentRequest)) {
|
|
151
|
-
|
|
195
|
+
var owners = provider[types_1.WRAPPED_REQUEST_OWNER_SYMBOL];
|
|
196
|
+
if (!Array.isArray(owners)) {
|
|
197
|
+
// A wrapper without its owner list cannot be taken over, and
|
|
198
|
+
// claiming success would silence every request event.
|
|
199
|
+
logger_1.logger.warn("wrapped without owner list; cannot rebind");
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
var idx = owners.indexOf(this);
|
|
203
|
+
if (idx !== -1)
|
|
204
|
+
owners.splice(idx, 1);
|
|
205
|
+
owners.push(this);
|
|
206
|
+
this.wrappedProviders.add(provider);
|
|
207
|
+
logger_1.logger.info("Provider already wrapped; rebinding the wrapper to this instance.");
|
|
152
208
|
return true;
|
|
153
209
|
}
|
|
154
210
|
var request = provider.request.bind(provider);
|
|
155
211
|
var wrappedRequest = function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
|
|
212
|
+
var owners, liveOwner;
|
|
213
|
+
var method = _b.method, params = _b.params;
|
|
214
|
+
return __generator(this, function (_c) {
|
|
215
|
+
owners = provider[types_1.WRAPPED_REQUEST_OWNER_SYMBOL];
|
|
216
|
+
if (dispatchInFlight.has(provider)) {
|
|
217
|
+
// An outer Formo wrapper is already instrumenting this very
|
|
218
|
+
// request; this layer only forwards.
|
|
219
|
+
return [2 /*return*/, request({ method: method, params: params })];
|
|
220
|
+
}
|
|
221
|
+
liveOwner = Array.isArray(owners)
|
|
222
|
+
? __spreadArray([], owners, true).reverse().find(function (o) { return !o.disposed; })
|
|
223
|
+
: undefined;
|
|
224
|
+
dispatchInFlight.add(provider);
|
|
225
|
+
try {
|
|
226
|
+
return [2 /*return*/, (liveOwner !== null && liveOwner !== void 0 ? liveOwner : this).dispatchWrappedRequest({ method: method, params: params }, provider, request)];
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
// Cleared as soon as the dispatch call RETURNS its promise: the
|
|
230
|
+
// underlying request has been issued synchronously by then, so
|
|
231
|
+
// the window covers exactly the nested layers of this one call
|
|
232
|
+
// and never a concurrent request.
|
|
233
|
+
dispatchInFlight.delete(provider);
|
|
234
|
+
}
|
|
235
|
+
return [2 /*return*/];
|
|
236
|
+
});
|
|
237
|
+
}); };
|
|
238
|
+
try {
|
|
239
|
+
// MERGE with any existing list rather than overwriting: a wallet that
|
|
240
|
+
// replaced `request` forces a re-wrap, and discarding the prior list
|
|
241
|
+
// would drop other live instances from ownership - the newest-live
|
|
242
|
+
// fallback then has nobody to fall back to.
|
|
243
|
+
var slot = provider;
|
|
244
|
+
var prior = slot[types_1.WRAPPED_REQUEST_OWNER_SYMBOL];
|
|
245
|
+
var owners = Array.isArray(prior) ? prior : [];
|
|
246
|
+
var idx = owners.indexOf(this);
|
|
247
|
+
if (idx !== -1)
|
|
248
|
+
owners.splice(idx, 1);
|
|
249
|
+
owners.push(this);
|
|
250
|
+
if (!Array.isArray(prior)) {
|
|
251
|
+
slot[types_1.WRAPPED_REQUEST_OWNER_SYMBOL] = owners;
|
|
252
|
+
}
|
|
253
|
+
this.wrappedProviders.add(provider);
|
|
254
|
+
}
|
|
255
|
+
catch (_a) {
|
|
256
|
+
/* frozen provider: the request write below fails too and aborts */
|
|
257
|
+
}
|
|
258
|
+
return this.installWrappedRequest(provider, wrappedRequest);
|
|
259
|
+
};
|
|
260
|
+
/** Install the wrapper function onto the provider; separated so the
|
|
261
|
+
* routing shim above stays small. */
|
|
262
|
+
EvmRequestTracker.prototype.installWrappedRequest = function (provider, wrappedRequest) {
|
|
263
|
+
// Mark the wrapper so we can detect if request is replaced externally and keep a reference on provider
|
|
264
|
+
wrappedRequest[types_1.WRAPPED_REQUEST_SYMBOL] = true;
|
|
265
|
+
// Both writes go inside the try. A frozen or non-extensible provider
|
|
266
|
+
// throws on the symbol assignment just as readily as on `request`, and
|
|
267
|
+
// that one used to sit outside the guard, so an unwrappable provider
|
|
268
|
+
// aborted registration instead of being skipped.
|
|
269
|
+
try {
|
|
270
|
+
provider[types_1.WRAPPED_REQUEST_REF_SYMBOL] =
|
|
271
|
+
wrappedRequest;
|
|
272
|
+
provider.request = wrappedRequest;
|
|
273
|
+
// Read back: an accessor or Proxy can ACCEPT the assignment without
|
|
274
|
+
// installing it, and success here is a promise that capture works.
|
|
275
|
+
if (provider.request !== wrappedRequest) {
|
|
276
|
+
logger_1.logger.warn("request assignment swallowed; not wrapped");
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
catch (e) {
|
|
282
|
+
logger_1.logger.warn("Failed to wrap provider.request; skipping", e);
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* The wrapper body proper: everything a request observation does, run
|
|
288
|
+
* against THIS instance's registry, wallet state, and event queue. Kept
|
|
289
|
+
* as a method so a surviving wrapper installed by a previous SDK
|
|
290
|
+
* instance can hand calls to the current one.
|
|
291
|
+
*/
|
|
292
|
+
EvmRequestTracker.prototype.dispatchWrappedRequest = function (_a, provider_2, request_1) {
|
|
293
|
+
return __awaiter(this, arguments, void 0, function (_b, provider, request) {
|
|
156
294
|
var generation_1, responsePromise, capturedChainId_1, response_1, error_1, rpcError, txPromise, txChainId_1, transactionHash_1, error_2, rpcError;
|
|
157
295
|
var _this = this;
|
|
296
|
+
var _c, _d, _e, _f;
|
|
158
297
|
var method = _b.method, params = _b.params;
|
|
159
|
-
return __generator(this, function (
|
|
160
|
-
switch (
|
|
298
|
+
return __generator(this, function (_g) {
|
|
299
|
+
switch (_g.label) {
|
|
161
300
|
case 0:
|
|
162
301
|
// Learn the chain from a call the APP was making anyway.
|
|
163
302
|
//
|
|
@@ -186,6 +325,10 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
186
325
|
logger_1.logger.debug("Signature event skipped (autocapture.signature: false)", { method: method });
|
|
187
326
|
return [2 /*return*/, request({ method: method, params: params })];
|
|
188
327
|
}
|
|
328
|
+
if ((_d = (_c = this.deps).shouldSkipRequestCapture) === null || _d === void 0 ? void 0 : _d.call(_c, method, params)) {
|
|
329
|
+
// A pending wagmi mutation owns this capture.
|
|
330
|
+
return [2 /*return*/, request({ method: method, params: params })];
|
|
331
|
+
}
|
|
189
332
|
responsePromise = request({ method: method, params: params });
|
|
190
333
|
// Attach a no-op handler now so a rejection arriving before the await
|
|
191
334
|
// below is never reported as unhandled. The real handling is there.
|
|
@@ -198,7 +341,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
198
341
|
switch (_a.label) {
|
|
199
342
|
case 0:
|
|
200
343
|
_a.trys.push([0, 2, , 3]);
|
|
201
|
-
return [4 /*yield*/, this.deps.signature(__assign({ status: types_1.SignatureStatus.REQUESTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1, provider)))];
|
|
344
|
+
return [4 /*yield*/, this.deps.signature(__assign({ status: types_1.SignatureStatus.REQUESTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1, provider)), this.attributionFor(provider))];
|
|
202
345
|
case 1:
|
|
203
346
|
_a.sent();
|
|
204
347
|
return [3 /*break*/, 3];
|
|
@@ -210,12 +353,12 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
210
353
|
}
|
|
211
354
|
});
|
|
212
355
|
}); })();
|
|
213
|
-
|
|
356
|
+
_g.label = 1;
|
|
214
357
|
case 1:
|
|
215
|
-
|
|
358
|
+
_g.trys.push([1, 3, , 4]);
|
|
216
359
|
return [4 /*yield*/, responsePromise];
|
|
217
360
|
case 2:
|
|
218
|
-
response_1 =
|
|
361
|
+
response_1 = _g.sent();
|
|
219
362
|
// Track signature confirmation only for truthy responses
|
|
220
363
|
if (response_1) {
|
|
221
364
|
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
@@ -224,7 +367,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
224
367
|
switch (_a.label) {
|
|
225
368
|
case 0:
|
|
226
369
|
_a.trys.push([0, 2, , 3]);
|
|
227
|
-
return [4 /*yield*/, this.deps.signature(__assign({ status: types_1.SignatureStatus.CONFIRMED }, this.buildSignatureEventPayload(method, params, response_1, capturedChainId_1, provider)))];
|
|
370
|
+
return [4 /*yield*/, this.deps.signature(__assign({ status: types_1.SignatureStatus.CONFIRMED }, this.buildSignatureEventPayload(method, params, response_1, capturedChainId_1, provider)), this.attributionFor(provider))];
|
|
228
371
|
case 1:
|
|
229
372
|
_a.sent();
|
|
230
373
|
return [3 /*break*/, 3];
|
|
@@ -239,9 +382,9 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
239
382
|
}
|
|
240
383
|
return [2 /*return*/, response_1];
|
|
241
384
|
case 3:
|
|
242
|
-
error_1 =
|
|
385
|
+
error_1 = _g.sent();
|
|
243
386
|
rpcError = error_1;
|
|
244
|
-
if ((
|
|
387
|
+
if ((0, provider_1.isUserRejectionError)(rpcError)) {
|
|
245
388
|
// Use the already cast rpcError to avoid duplication
|
|
246
389
|
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
247
390
|
var e_3;
|
|
@@ -249,7 +392,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
249
392
|
switch (_a.label) {
|
|
250
393
|
case 0:
|
|
251
394
|
_a.trys.push([0, 2, , 3]);
|
|
252
|
-
return [4 /*yield*/, this.deps.signature(__assign({ status: types_1.SignatureStatus.REJECTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1, provider)))];
|
|
395
|
+
return [4 /*yield*/, this.deps.signature(__assign({ status: types_1.SignatureStatus.REJECTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1, provider)), this.attributionFor(provider))];
|
|
253
396
|
case 1:
|
|
254
397
|
_a.sent();
|
|
255
398
|
return [3 /*break*/, 3];
|
|
@@ -281,6 +424,10 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
281
424
|
logger_1.logger.debug("Transaction event skipped (autocapture.transaction: false)", { method: method });
|
|
282
425
|
return [2 /*return*/, request({ method: method, params: params })];
|
|
283
426
|
}
|
|
427
|
+
if ((_f = (_e = this.deps).shouldSkipRequestCapture) === null || _f === void 0 ? void 0 : _f.call(_e, method, params)) {
|
|
428
|
+
// A pending wagmi mutation owns this capture.
|
|
429
|
+
return [2 /*return*/, request({ method: method, params: params })];
|
|
430
|
+
}
|
|
284
431
|
txPromise = request({ method: method, params: params });
|
|
285
432
|
txPromise.catch(function () { return undefined; });
|
|
286
433
|
txChainId_1 = this.registry.resolveChainId(provider);
|
|
@@ -293,7 +440,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
293
440
|
return [4 /*yield*/, this.buildTransactionEventPayload(params, provider, txChainId_1)];
|
|
294
441
|
case 1:
|
|
295
442
|
payload = _a.sent();
|
|
296
|
-
return [4 /*yield*/, this.deps.transaction(__assign({ status: types_1.TransactionStatus.STARTED }, payload))];
|
|
443
|
+
return [4 /*yield*/, this.deps.transaction(__assign({ status: types_1.TransactionStatus.STARTED }, payload), this.attributionFor(provider))];
|
|
297
444
|
case 2:
|
|
298
445
|
_a.sent();
|
|
299
446
|
return [3 /*break*/, 4];
|
|
@@ -305,12 +452,12 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
305
452
|
}
|
|
306
453
|
});
|
|
307
454
|
}); })();
|
|
308
|
-
|
|
455
|
+
_g.label = 5;
|
|
309
456
|
case 5:
|
|
310
|
-
|
|
457
|
+
_g.trys.push([5, 7, , 8]);
|
|
311
458
|
return [4 /*yield*/, txPromise];
|
|
312
459
|
case 6:
|
|
313
|
-
transactionHash_1 =
|
|
460
|
+
transactionHash_1 = _g.sent();
|
|
314
461
|
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
315
462
|
var payload, e_5;
|
|
316
463
|
return __generator(this, function (_a) {
|
|
@@ -320,7 +467,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
320
467
|
return [4 /*yield*/, this.buildTransactionEventPayload(params, provider, txChainId_1)];
|
|
321
468
|
case 1:
|
|
322
469
|
payload = _a.sent();
|
|
323
|
-
return [4 /*yield*/, this.deps.transaction(__assign(__assign({ status: types_1.TransactionStatus.BROADCASTED }, payload), { transactionHash: transactionHash_1 }))];
|
|
470
|
+
return [4 /*yield*/, this.deps.transaction(__assign(__assign({ status: types_1.TransactionStatus.BROADCASTED }, payload), { transactionHash: transactionHash_1 }), this.attributionFor(provider))];
|
|
324
471
|
case 2:
|
|
325
472
|
_a.sent();
|
|
326
473
|
// Start async polling for transaction receipt
|
|
@@ -336,9 +483,9 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
336
483
|
}); })();
|
|
337
484
|
return [2 /*return*/, transactionHash_1];
|
|
338
485
|
case 7:
|
|
339
|
-
error_2 =
|
|
486
|
+
error_2 = _g.sent();
|
|
340
487
|
rpcError = error_2;
|
|
341
|
-
if ((
|
|
488
|
+
if ((0, provider_1.isUserRejectionError)(rpcError)) {
|
|
342
489
|
// Use the already cast rpcError to avoid duplication
|
|
343
490
|
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
344
491
|
var payload, e_6;
|
|
@@ -349,7 +496,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
349
496
|
return [4 /*yield*/, this.buildTransactionEventPayload(params, provider, txChainId_1)];
|
|
350
497
|
case 1:
|
|
351
498
|
payload = _a.sent();
|
|
352
|
-
return [4 /*yield*/, this.deps.transaction(__assign({ status: types_1.TransactionStatus.REJECTED }, payload))];
|
|
499
|
+
return [4 /*yield*/, this.deps.transaction(__assign({ status: types_1.TransactionStatus.REJECTED }, payload), this.attributionFor(provider))];
|
|
353
500
|
case 2:
|
|
354
501
|
_a.sent();
|
|
355
502
|
return [3 /*break*/, 4];
|
|
@@ -366,23 +513,19 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
366
513
|
case 8: return [2 /*return*/, request({ method: method, params: params })];
|
|
367
514
|
}
|
|
368
515
|
});
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
catch (e) {
|
|
383
|
-
logger_1.logger.warn("Failed to wrap provider.request; skipping", e);
|
|
384
|
-
return false;
|
|
385
|
-
}
|
|
516
|
+
});
|
|
517
|
+
};
|
|
518
|
+
/**
|
|
519
|
+
* Wallet attribution for request-derived events.
|
|
520
|
+
*
|
|
521
|
+
* Live per read through the registry, so a WalletConnect session names
|
|
522
|
+
* its actual signer ("MetaMask Wallet", "Ledger Live") - the live-test
|
|
523
|
+
* rows had provider_name EMPTY on every signature and transaction, which
|
|
524
|
+
* made per-wallet activity unanswerable in the warehouse.
|
|
525
|
+
*/
|
|
526
|
+
EvmRequestTracker.prototype.attributionFor = function (provider) {
|
|
527
|
+
var info = this.registry.infoFor(provider);
|
|
528
|
+
return { providerName: info.name, rdns: info.rdns };
|
|
386
529
|
};
|
|
387
530
|
EvmRequestTracker.prototype.buildSignatureEventPayload = function (method, params,
|
|
388
531
|
// Intentionally not read. Kept for positional call-site arity.
|
|
@@ -448,7 +591,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
448
591
|
/**
|
|
449
592
|
* Polls for transaction receipt and emits tx.status = CONFIRMED or REVERTED.
|
|
450
593
|
*/
|
|
451
|
-
EvmRequestTracker.prototype.pollTransactionReceipt = function (
|
|
594
|
+
EvmRequestTracker.prototype.pollTransactionReceipt = function (provider_2, transactionHash_2, payload_1) {
|
|
452
595
|
return __awaiter(this, arguments, void 0, function (provider, transactionHash, payload, maxAttempts, intervalMs) {
|
|
453
596
|
var attempts, poll;
|
|
454
597
|
var _this = this;
|
|
@@ -478,7 +621,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
478
621
|
// status: 1 = success, 0 = reverted
|
|
479
622
|
if (receipt.status === "0x1" || receipt.status === 1) {
|
|
480
623
|
this.deps
|
|
481
|
-
.transaction(__assign(__assign({ status: types_1.TransactionStatus.CONFIRMED }, payload), { transactionHash: transactionHash }))
|
|
624
|
+
.transaction(__assign(__assign({ status: types_1.TransactionStatus.CONFIRMED }, payload), { transactionHash: transactionHash }), this.attributionFor(provider))
|
|
482
625
|
.catch(function (e) {
|
|
483
626
|
return logger_1.logger.error("Formo: Failed to track transaction confirmation", e);
|
|
484
627
|
});
|
|
@@ -486,7 +629,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
486
629
|
}
|
|
487
630
|
else if (receipt.status === "0x0" || receipt.status === 0) {
|
|
488
631
|
this.deps
|
|
489
|
-
.transaction(__assign(__assign({ status: types_1.TransactionStatus.REVERTED }, payload), { transactionHash: transactionHash }))
|
|
632
|
+
.transaction(__assign(__assign({ status: types_1.TransactionStatus.REVERTED }, payload), { transactionHash: transactionHash }), this.attributionFor(provider))
|
|
490
633
|
.catch(function (e) {
|
|
491
634
|
return logger_1.logger.error("Formo: Failed to track transaction revert", e);
|
|
492
635
|
});
|
|
@@ -514,11 +657,14 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
514
657
|
/**
|
|
515
658
|
* One `transaction` event per call in an EIP-5792 batch.
|
|
516
659
|
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
* per-contract
|
|
520
|
-
*
|
|
521
|
-
*
|
|
660
|
+
* The CALL is the unit of attribution: each has its own target, calldata,
|
|
661
|
+
* and value, and folding a batch into one event would misattribute revenue
|
|
662
|
+
* and per-contract activity for every app that adopts smart accounts. How
|
|
663
|
+
* many on-chain transactions a batch becomes depends on execution - an
|
|
664
|
+
* atomic batch lands as ONE transaction, a non-atomic fallback as several -
|
|
665
|
+
* so on-chain volume is `count(distinct transaction_hash)`, wallet actions
|
|
666
|
+
* `count(distinct batch_id)`, never the event count. Each call is reported
|
|
667
|
+
* on its own, carrying the batch id so the calls reassemble downstream.
|
|
522
668
|
*
|
|
523
669
|
* Status is per BATCH, because that is what `wallet_getCallsStatus` reports.
|
|
524
670
|
* When it resolves, every call in the batch moves together, except where
|
|
@@ -526,10 +672,10 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
526
672
|
*/
|
|
527
673
|
EvmRequestTracker.prototype.trackBatchedCalls = function (provider, request, params) {
|
|
528
674
|
return __awaiter(this, void 0, void 0, function () {
|
|
529
|
-
var sendPromise, batch, calls, declared, chainId, address, payloads, _i, payloads_1, p, properties, rest, result, batchId, _a, payloads_2, p, properties, rest, error_3, rpcError, _b, payloads_3, p, properties, rest;
|
|
530
|
-
var _c;
|
|
531
|
-
return __generator(this, function (
|
|
532
|
-
switch (
|
|
675
|
+
var sendPromise, batch, calls, declared, chainId, address, attribution, payloads, _i, payloads_1, p, properties, rest, result, batchId, _a, payloads_2, p, properties, rest, error_3, rpcError, _b, payloads_3, p, properties, rest;
|
|
676
|
+
var _c, _d, _e;
|
|
677
|
+
return __generator(this, function (_f) {
|
|
678
|
+
switch (_f.label) {
|
|
533
679
|
case 0:
|
|
534
680
|
if (!this.deps.isAutocaptureEnabled("transaction")) {
|
|
535
681
|
logger_1.logger.debug("Transaction event skipped (autocapture.transaction: false)", {
|
|
@@ -537,13 +683,17 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
537
683
|
});
|
|
538
684
|
return [2 /*return*/, request({ method: "wallet_sendCalls", params: params })];
|
|
539
685
|
}
|
|
686
|
+
if ((_d = (_c = this.deps).shouldSkipRequestCapture) === null || _d === void 0 ? void 0 : _d.call(_c, "wallet_sendCalls", params)) {
|
|
687
|
+
// A pending wagmi sendCalls mutation owns this capture.
|
|
688
|
+
return [2 /*return*/, request({ method: "wallet_sendCalls", params: params })];
|
|
689
|
+
}
|
|
540
690
|
sendPromise = request({ method: "wallet_sendCalls", params: params });
|
|
541
691
|
sendPromise.catch(function () { return undefined; });
|
|
542
692
|
batch = params[0];
|
|
543
693
|
calls = Array.isArray(batch === null || batch === void 0 ? void 0 : batch.calls) ? batch.calls : [];
|
|
544
694
|
declared = typeof (batch === null || batch === void 0 ? void 0 : batch.chainId) === "string" ? (0, chain_1.parseChainId)(batch.chainId) : undefined;
|
|
545
695
|
chainId = declared || this.registry.resolveChainId(provider);
|
|
546
|
-
address = (0, address_1.validateAndChecksumAddress)((
|
|
696
|
+
address = (0, address_1.validateAndChecksumAddress)((_e = batch === null || batch === void 0 ? void 0 : batch.from) !== null && _e !== void 0 ? _e : "");
|
|
547
697
|
if (!address) {
|
|
548
698
|
// Nothing can be attributed without a sender, and inventing one would
|
|
549
699
|
// be worse than reporting nothing. The user's call still goes through.
|
|
@@ -562,16 +712,14 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
562
712
|
if (!provider || provider === this.wallet.provider || !this.wallet.provider) {
|
|
563
713
|
this.wallet.backfill(address, chainId, provider);
|
|
564
714
|
}
|
|
715
|
+
attribution = this.attributionFor(provider);
|
|
565
716
|
payloads = calls.map(function (call, index) { return ({
|
|
566
717
|
chainId: chainId,
|
|
567
718
|
address: address,
|
|
568
719
|
to: call === null || call === void 0 ? void 0 : call.to,
|
|
569
720
|
value: call === null || call === void 0 ? void 0 : call.value,
|
|
570
721
|
data: call === null || call === void 0 ? void 0 : call.data,
|
|
571
|
-
properties: {
|
|
572
|
-
batch_size: calls.length,
|
|
573
|
-
batch_index: index,
|
|
574
|
-
},
|
|
722
|
+
properties: __assign({ batch_size: calls.length, batch_index: index }, attribution),
|
|
575
723
|
}); });
|
|
576
724
|
// STARTED carries no batch id: the wallet has not issued one yet, exactly
|
|
577
725
|
// as `eth_sendTransaction` has no hash at this point. Position within the
|
|
@@ -583,13 +731,13 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
583
731
|
.transaction(__assign({ status: types_1.TransactionStatus.STARTED }, rest), properties)
|
|
584
732
|
.catch(function (e) { return logger_1.logger.error("Formo: Failed to track batch call start", e); });
|
|
585
733
|
}
|
|
586
|
-
|
|
734
|
+
_f.label = 1;
|
|
587
735
|
case 1:
|
|
588
|
-
|
|
736
|
+
_f.trys.push([1, 3, , 4]);
|
|
589
737
|
return [4 /*yield*/, sendPromise];
|
|
590
738
|
case 2:
|
|
591
|
-
result =
|
|
592
|
-
batchId =
|
|
739
|
+
result = _f.sent();
|
|
740
|
+
batchId = (0, batch_1.readBatchId)(result);
|
|
593
741
|
for (_a = 0, payloads_2 = payloads; _a < payloads_2.length; _a++) {
|
|
594
742
|
p = payloads_2[_a];
|
|
595
743
|
properties = p.properties, rest = __rest(p, ["properties"]);
|
|
@@ -603,9 +751,9 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
603
751
|
this.pollBatchStatus(provider, batchId, payloads);
|
|
604
752
|
return [2 /*return*/, result];
|
|
605
753
|
case 3:
|
|
606
|
-
error_3 =
|
|
754
|
+
error_3 = _f.sent();
|
|
607
755
|
rpcError = error_3;
|
|
608
|
-
if ((
|
|
756
|
+
if ((0, provider_1.isUserRejectionError)(rpcError)) {
|
|
609
757
|
// One rejection dismisses the whole prompt, so every call in it is
|
|
610
758
|
// rejected. Reporting only the first would undercount.
|
|
611
759
|
for (_b = 0, payloads_3 = payloads; _b < payloads_3.length; _b++) {
|
|
@@ -624,54 +772,6 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
624
772
|
});
|
|
625
773
|
});
|
|
626
774
|
};
|
|
627
|
-
/**
|
|
628
|
-
* How one call in a settled batch ended.
|
|
629
|
-
*
|
|
630
|
-
* A per-call receipt is authoritative where it exists: that is what makes a
|
|
631
|
-
* partially reverted non-atomic batch report honestly rather than tarring
|
|
632
|
-
* every call with the batch's worst outcome. A receipt whose own status is
|
|
633
|
-
* unreadable falls back to the batch verdict rather than being assumed good.
|
|
634
|
-
*
|
|
635
|
-
* The codes are EIP-5792's: 200 confirmed, 400 failed BEFORE landing on
|
|
636
|
-
* chain, 500 reverted, 600 partially reverted. 400 is a rejection, not a
|
|
637
|
-
* revert - nothing was mined, so calling it reverted would misreport gas
|
|
638
|
-
* spent and on-chain activity that never happened.
|
|
639
|
-
*
|
|
640
|
-
* Returns undefined when the call cannot be decided, which happens on 600
|
|
641
|
-
* for a call the wallet gave no receipt for.
|
|
642
|
-
*/
|
|
643
|
-
EvmRequestTracker.prototype.batchCallOutcome = function (code, receipt) {
|
|
644
|
-
var receiptStatus = receipt === null || receipt === void 0 ? void 0 : receipt.status;
|
|
645
|
-
if (receiptStatus !== undefined) {
|
|
646
|
-
return receiptStatus === "0x0" || receiptStatus === 0
|
|
647
|
-
? types_1.TransactionStatus.REVERTED
|
|
648
|
-
: types_1.TransactionStatus.CONFIRMED;
|
|
649
|
-
}
|
|
650
|
-
if (code >= 600)
|
|
651
|
-
return undefined;
|
|
652
|
-
if (code >= 500)
|
|
653
|
-
return types_1.TransactionStatus.REVERTED;
|
|
654
|
-
if (code >= 400)
|
|
655
|
-
return types_1.TransactionStatus.REJECTED;
|
|
656
|
-
return types_1.TransactionStatus.CONFIRMED;
|
|
657
|
-
};
|
|
658
|
-
/**
|
|
659
|
-
* The batch identifier from a `wallet_sendCalls` result.
|
|
660
|
-
*
|
|
661
|
-
* EIP-5792 settled on `{ id }`, but wallets shipped against the earlier
|
|
662
|
-
* draft return a bare string. Both are accepted so a wallet on either
|
|
663
|
-
* version is still grouped.
|
|
664
|
-
*/
|
|
665
|
-
EvmRequestTracker.prototype.readBatchId = function (result) {
|
|
666
|
-
if (typeof result === "string" && result.length > 0)
|
|
667
|
-
return result;
|
|
668
|
-
if (result && typeof result === "object") {
|
|
669
|
-
var id = result.id;
|
|
670
|
-
if (typeof id === "string" && id.length > 0)
|
|
671
|
-
return id;
|
|
672
|
-
}
|
|
673
|
-
return undefined;
|
|
674
|
-
};
|
|
675
775
|
/**
|
|
676
776
|
* Resolve a batch through `wallet_getCallsStatus`.
|
|
677
777
|
*
|
|
@@ -683,7 +783,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
683
783
|
* what makes a partially reverted non-atomic batch report honestly instead
|
|
684
784
|
* of marking every call with the batch's worst outcome.
|
|
685
785
|
*/
|
|
686
|
-
EvmRequestTracker.prototype.pollBatchStatus = function (
|
|
786
|
+
EvmRequestTracker.prototype.pollBatchStatus = function (provider_2, batchId_1, payloads_4) {
|
|
687
787
|
return __awaiter(this, arguments, void 0, function (provider, batchId, payloads, maxAttempts, intervalMs) {
|
|
688
788
|
var attempts, poll;
|
|
689
789
|
var _this = this;
|
|
@@ -694,7 +794,7 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
694
794
|
return [2 /*return*/];
|
|
695
795
|
attempts = 0;
|
|
696
796
|
poll = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
697
|
-
var
|
|
797
|
+
var res_1, code_1, e_8;
|
|
698
798
|
var _this = this;
|
|
699
799
|
return __generator(this, function (_a) {
|
|
700
800
|
switch (_a.label) {
|
|
@@ -709,13 +809,14 @@ var EvmRequestTracker = /** @class */ (function () {
|
|
|
709
809
|
params: [batchId],
|
|
710
810
|
})];
|
|
711
811
|
case 2:
|
|
712
|
-
|
|
713
|
-
code_1 =
|
|
812
|
+
res_1 = (_a.sent());
|
|
813
|
+
code_1 = (0, batch_1.readBatchStatusCode)(res_1);
|
|
714
814
|
if (code_1 !== undefined && code_1 >= 200) {
|
|
715
|
-
receipts_1 = Array.isArray(res === null || res === void 0 ? void 0 : res.receipts) ? res.receipts : [];
|
|
716
815
|
payloads.forEach(function (p, index) {
|
|
717
|
-
|
|
718
|
-
|
|
816
|
+
// Atomic-aware: one receipt covering the whole batch reaches
|
|
817
|
+
// every call, hash included, not just call 0.
|
|
818
|
+
var receipt = (0, batch_1.batchReceiptForCall)(res_1, index, payloads.length);
|
|
819
|
+
var outcome = (0, batch_1.batchCallOutcome)(code_1, receipt);
|
|
719
820
|
// 600 means SOME calls reverted, so a call with no receipt of its
|
|
720
821
|
// own has not been decided. Reporting it either way would invent
|
|
721
822
|
// a result; leaving it unsettled is the honest answer.
|