@formo/analytics 1.35.2 → 1.36.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 +79 -363
- package/dist/cjs/src/FormoAnalytics.js +368 -2234
- package/dist/cjs/src/event/EventManager.d.ts +3 -1
- package/dist/cjs/src/event/EventManager.js +5 -1
- package/dist/cjs/src/event/type.d.ts +1 -0
- package/dist/cjs/src/evm/EvmEventTracker.d.ts +175 -0
- package/dist/cjs/src/evm/EvmEventTracker.js +1030 -0
- package/dist/cjs/src/evm/EvmProviderRegistry.d.ts +132 -0
- package/dist/cjs/src/evm/EvmProviderRegistry.js +348 -0
- package/dist/cjs/src/evm/EvmRequestTracker.d.ts +120 -0
- package/dist/cjs/src/evm/EvmRequestTracker.js +756 -0
- package/dist/cjs/src/queue/EventQueue.d.ts +28 -0
- package/dist/cjs/src/queue/EventQueue.js +97 -19
- package/dist/cjs/src/queue/type.d.ts +1 -0
- package/dist/cjs/src/tracking/TrackingPolicy.d.ts +146 -0
- package/dist/cjs/src/tracking/TrackingPolicy.js +200 -0
- package/dist/cjs/src/validators/address.d.ts +1 -1
- package/dist/cjs/src/version.d.ts +1 -1
- package/dist/cjs/src/version.js +1 -1
- package/dist/cjs/src/wallet/WalletStateStore.d.ts +223 -0
- package/dist/cjs/src/wallet/WalletStateStore.js +515 -0
- package/dist/esm/src/FormoAnalytics.d.ts +79 -363
- package/dist/esm/src/FormoAnalytics.js +369 -2235
- package/dist/esm/src/event/EventManager.d.ts +3 -1
- package/dist/esm/src/event/EventManager.js +5 -1
- package/dist/esm/src/event/type.d.ts +1 -0
- package/dist/esm/src/evm/EvmEventTracker.d.ts +175 -0
- package/dist/esm/src/evm/EvmEventTracker.js +1027 -0
- package/dist/esm/src/evm/EvmProviderRegistry.d.ts +132 -0
- package/dist/esm/src/evm/EvmProviderRegistry.js +345 -0
- package/dist/esm/src/evm/EvmRequestTracker.d.ts +120 -0
- package/dist/esm/src/evm/EvmRequestTracker.js +753 -0
- package/dist/esm/src/queue/EventQueue.d.ts +28 -0
- package/dist/esm/src/queue/EventQueue.js +97 -19
- package/dist/esm/src/queue/type.d.ts +1 -0
- package/dist/esm/src/tracking/TrackingPolicy.d.ts +146 -0
- package/dist/esm/src/tracking/TrackingPolicy.js +197 -0
- package/dist/esm/src/version.d.ts +1 -1
- package/dist/esm/src/version.js +1 -1
- package/dist/esm/src/wallet/WalletStateStore.d.ts +223 -0
- package/dist/esm/src/wallet/WalletStateStore.js +512 -0
- package/dist/index.umd.min.js +1 -1
- package/package.json +5 -4
|
@@ -0,0 +1,753 @@
|
|
|
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
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
23
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
49
|
+
var t = {};
|
|
50
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
51
|
+
t[p] = s[p];
|
|
52
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
53
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
54
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
55
|
+
t[p[i]] = s[p[i]];
|
|
56
|
+
}
|
|
57
|
+
return t;
|
|
58
|
+
};
|
|
59
|
+
import { logger } from "../logger";
|
|
60
|
+
import { parseChainId } from "../utils/chain";
|
|
61
|
+
import { validateAndChecksumAddress } from "../utils/address";
|
|
62
|
+
import { SignatureStatus, TransactionStatus, WRAPPED_REQUEST_SYMBOL, WRAPPED_REQUEST_REF_SYMBOL, } from "../types";
|
|
63
|
+
/**
|
|
64
|
+
* Decode a hex-encoded `personal_sign` message.
|
|
65
|
+
*
|
|
66
|
+
* Deliberately not `Buffer.from(hex, "hex")`. `Buffer` is a Node global with
|
|
67
|
+
* no polyfill in this bundle, so in a browser that line threw and the
|
|
68
|
+
* signature event was dropped with it - silently, which is the worst way for
|
|
69
|
+
* analytics to fail. `TextDecoder` is available everywhere this SDK runs, and
|
|
70
|
+
* `TextEncoder` is already used elsewhere in the queue.
|
|
71
|
+
*
|
|
72
|
+
* Malformed input decodes to as much as can be read rather than throwing: a
|
|
73
|
+
* message we cannot fully read is still worth reporting the signature for.
|
|
74
|
+
*/
|
|
75
|
+
function hexToUtf8(hex) {
|
|
76
|
+
var clean = typeof hex === "string" && hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
77
|
+
if (typeof clean !== "string" || clean.length === 0)
|
|
78
|
+
return "";
|
|
79
|
+
var byteCount = Math.floor(clean.length / 2);
|
|
80
|
+
var bytes = new Uint8Array(byteCount);
|
|
81
|
+
for (var i = 0; i < byteCount; i++) {
|
|
82
|
+
var byte = Number.parseInt(clean.substring(i * 2, i * 2 + 2), 16);
|
|
83
|
+
if (Number.isNaN(byte))
|
|
84
|
+
return new TextDecoder().decode(bytes.subarray(0, i));
|
|
85
|
+
bytes[i] = byte;
|
|
86
|
+
}
|
|
87
|
+
return new TextDecoder().decode(bytes);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Autocapture for signatures and transactions, by wrapping a provider's
|
|
91
|
+
* `request`.
|
|
92
|
+
*
|
|
93
|
+
* The wrapper is deliberately thin: it observes the call the dapp was already
|
|
94
|
+
* making and never issues one of its own. That rule is why the chain a
|
|
95
|
+
* request ran on is read from `eth_chainId` calls the app makes, rather than
|
|
96
|
+
* probed - an SDK-issued lookup on a serialising transport can wedge the
|
|
97
|
+
* user's wallet, which is never an acceptable price for a label.
|
|
98
|
+
*/
|
|
99
|
+
var EvmRequestTracker = /** @class */ (function () {
|
|
100
|
+
function EvmRequestTracker(wallet, registry, deps) {
|
|
101
|
+
this.wallet = wallet;
|
|
102
|
+
this.registry = registry;
|
|
103
|
+
this.deps = deps;
|
|
104
|
+
/**
|
|
105
|
+
* Timers for receipt and batch-status polling.
|
|
106
|
+
*
|
|
107
|
+
* A poll re-arms for up to thirty seconds, so a torn-down instance would
|
|
108
|
+
* otherwise keep asking a wallet about transactions nobody is listening
|
|
109
|
+
* for, and hold the process open for the whole window. That is the same
|
|
110
|
+
* shape as the batch timer that hung the test suite in #338.
|
|
111
|
+
*/
|
|
112
|
+
this.polls = new Set();
|
|
113
|
+
this.disposed = false;
|
|
114
|
+
}
|
|
115
|
+
/** Stop every poll in flight. Terminal, like the event queue's close(). */
|
|
116
|
+
EvmRequestTracker.prototype.cleanup = function () {
|
|
117
|
+
this.disposed = true;
|
|
118
|
+
this.polls.forEach(function (timer) { return clearTimeout(timer); });
|
|
119
|
+
this.polls.clear();
|
|
120
|
+
};
|
|
121
|
+
/** Re-arm a poll, unless this tracker has been torn down. */
|
|
122
|
+
EvmRequestTracker.prototype.schedulePoll = function (fn, delayMs) {
|
|
123
|
+
var _this = this;
|
|
124
|
+
if (this.disposed)
|
|
125
|
+
return;
|
|
126
|
+
var timer = setTimeout(function () {
|
|
127
|
+
_this.polls.delete(timer);
|
|
128
|
+
fn();
|
|
129
|
+
}, delayMs);
|
|
130
|
+
this.polls.add(timer);
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Wrap a provider's `request`. Returns whether the wrapper is installed:
|
|
134
|
+
* a caller that marks the provider as tracked on a false return would
|
|
135
|
+
* never retry it, and every signature and transaction from that wallet
|
|
136
|
+
* would be missed for the rest of the session.
|
|
137
|
+
*/
|
|
138
|
+
EvmRequestTracker.prototype.registerRequestListeners = function (provider) {
|
|
139
|
+
var _this = this;
|
|
140
|
+
logger.info("registerRequestListeners");
|
|
141
|
+
if (!provider) {
|
|
142
|
+
logger.error("Provider not found for request (signature, transaction) tracking");
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
// Check if the provider is already wrapped with our SDK's wrapper
|
|
146
|
+
var currentRequest = provider.request;
|
|
147
|
+
if (this.registry.isWrapped(provider, currentRequest)) {
|
|
148
|
+
logger.info("Provider already wrapped with our SDK; skipping request wrapping.");
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
var request = provider.request.bind(provider);
|
|
152
|
+
var wrappedRequest = function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
|
|
153
|
+
var generation_1, responsePromise, capturedChainId_1, response_1, error_1, rpcError, txPromise, txChainId_1, transactionHash_1, error_2, rpcError;
|
|
154
|
+
var _this = this;
|
|
155
|
+
var method = _b.method, params = _b.params;
|
|
156
|
+
return __generator(this, function (_c) {
|
|
157
|
+
switch (_c.label) {
|
|
158
|
+
case 0:
|
|
159
|
+
// Learn the chain from a call the APP was making anyway.
|
|
160
|
+
//
|
|
161
|
+
// A standards-compliant provider need not expose a synchronous `chainId`
|
|
162
|
+
// property, and if it connected before the SDK initialised, its
|
|
163
|
+
// `connect` event is never replayed. Such a provider stayed unknown -
|
|
164
|
+
// reported as chain 0, and with `excludeChains` configured its events
|
|
165
|
+
// were dropped even on an allowed chain. This adds no request of its
|
|
166
|
+
// own; it only reads the answer to one the dapp already sent.
|
|
167
|
+
if (method === "eth_chainId") {
|
|
168
|
+
generation_1 = this.registry.chainGeneration(provider);
|
|
169
|
+
return [2 /*return*/, request({ method: method, params: params }).then(function (result) {
|
|
170
|
+
// A `chainChanged` for THIS provider may have landed while this was
|
|
171
|
+
// in flight. It is newer by definition, so it must not be
|
|
172
|
+
// overwritten by this answer.
|
|
173
|
+
if (generation_1 === (_this.registry.chainGeneration(provider)) &&
|
|
174
|
+
typeof result === "string") {
|
|
175
|
+
_this.registry.rememberChain(provider, parseChainId(result));
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
178
|
+
})];
|
|
179
|
+
}
|
|
180
|
+
if (!(Array.isArray(params) &&
|
|
181
|
+
["eth_signTypedData_v4", "personal_sign"].includes(method))) return [3 /*break*/, 4];
|
|
182
|
+
if (!this.deps.isAutocaptureEnabled("signature")) {
|
|
183
|
+
logger.debug("Signature event skipped (autocapture.signature: false)", { method: method });
|
|
184
|
+
return [2 /*return*/, request({ method: method, params: params })];
|
|
185
|
+
}
|
|
186
|
+
responsePromise = request({ method: method, params: params });
|
|
187
|
+
// Attach a no-op handler now so a rejection arriving before the await
|
|
188
|
+
// below is never reported as unhandled. The real handling is there.
|
|
189
|
+
responsePromise.catch(function () { return undefined; });
|
|
190
|
+
capturedChainId_1 = this.registry.resolveChainId(provider);
|
|
191
|
+
// Fire-and-forget tracking
|
|
192
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
193
|
+
var e_1;
|
|
194
|
+
return __generator(this, function (_a) {
|
|
195
|
+
switch (_a.label) {
|
|
196
|
+
case 0:
|
|
197
|
+
_a.trys.push([0, 2, , 3]);
|
|
198
|
+
return [4 /*yield*/, this.deps.signature(__assign({ status: SignatureStatus.REQUESTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1, provider)))];
|
|
199
|
+
case 1:
|
|
200
|
+
_a.sent();
|
|
201
|
+
return [3 /*break*/, 3];
|
|
202
|
+
case 2:
|
|
203
|
+
e_1 = _a.sent();
|
|
204
|
+
logger.error("Formo: Failed to track signature request", e_1);
|
|
205
|
+
return [3 /*break*/, 3];
|
|
206
|
+
case 3: return [2 /*return*/];
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}); })();
|
|
210
|
+
_c.label = 1;
|
|
211
|
+
case 1:
|
|
212
|
+
_c.trys.push([1, 3, , 4]);
|
|
213
|
+
return [4 /*yield*/, responsePromise];
|
|
214
|
+
case 2:
|
|
215
|
+
response_1 = _c.sent();
|
|
216
|
+
// Track signature confirmation only for truthy responses
|
|
217
|
+
if (response_1) {
|
|
218
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
219
|
+
var e_2;
|
|
220
|
+
return __generator(this, function (_a) {
|
|
221
|
+
switch (_a.label) {
|
|
222
|
+
case 0:
|
|
223
|
+
_a.trys.push([0, 2, , 3]);
|
|
224
|
+
return [4 /*yield*/, this.deps.signature(__assign({ status: SignatureStatus.CONFIRMED }, this.buildSignatureEventPayload(method, params, response_1, capturedChainId_1, provider)))];
|
|
225
|
+
case 1:
|
|
226
|
+
_a.sent();
|
|
227
|
+
return [3 /*break*/, 3];
|
|
228
|
+
case 2:
|
|
229
|
+
e_2 = _a.sent();
|
|
230
|
+
logger.error("Formo: Failed to track signature confirmation", e_2);
|
|
231
|
+
return [3 /*break*/, 3];
|
|
232
|
+
case 3: return [2 /*return*/];
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}); })();
|
|
236
|
+
}
|
|
237
|
+
return [2 /*return*/, response_1];
|
|
238
|
+
case 3:
|
|
239
|
+
error_1 = _c.sent();
|
|
240
|
+
rpcError = error_1;
|
|
241
|
+
if ((rpcError === null || rpcError === void 0 ? void 0 : rpcError.code) === 4001) {
|
|
242
|
+
// Use the already cast rpcError to avoid duplication
|
|
243
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
244
|
+
var e_3;
|
|
245
|
+
return __generator(this, function (_a) {
|
|
246
|
+
switch (_a.label) {
|
|
247
|
+
case 0:
|
|
248
|
+
_a.trys.push([0, 2, , 3]);
|
|
249
|
+
return [4 /*yield*/, this.deps.signature(__assign({ status: SignatureStatus.REJECTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1, provider)))];
|
|
250
|
+
case 1:
|
|
251
|
+
_a.sent();
|
|
252
|
+
return [3 /*break*/, 3];
|
|
253
|
+
case 2:
|
|
254
|
+
e_3 = _a.sent();
|
|
255
|
+
logger.error("Formo: Failed to track signature rejection", e_3);
|
|
256
|
+
return [3 /*break*/, 3];
|
|
257
|
+
case 3: return [2 /*return*/];
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}); })();
|
|
261
|
+
}
|
|
262
|
+
throw error_1;
|
|
263
|
+
case 4:
|
|
264
|
+
// Handle EIP-5792 batched calls.
|
|
265
|
+
//
|
|
266
|
+
// Smart accounts send through `wallet_sendCalls` rather than
|
|
267
|
+
// `eth_sendTransaction`, and until now the SDK understood only the
|
|
268
|
+
// latter: those transactions were not captured at all, silently. That
|
|
269
|
+
// is the same failure shape as the missing-connect bug that started
|
|
270
|
+
// this work - nothing errors, the data is simply absent.
|
|
271
|
+
if (method === "wallet_sendCalls" && Array.isArray(params) && params[0]) {
|
|
272
|
+
return [2 /*return*/, this.trackBatchedCalls(provider, request, params)];
|
|
273
|
+
}
|
|
274
|
+
if (!(Array.isArray(params) &&
|
|
275
|
+
method === "eth_sendTransaction" &&
|
|
276
|
+
params[0])) return [3 /*break*/, 8];
|
|
277
|
+
if (!this.deps.isAutocaptureEnabled("transaction")) {
|
|
278
|
+
logger.debug("Transaction event skipped (autocapture.transaction: false)", { method: method });
|
|
279
|
+
return [2 /*return*/, request({ method: method, params: params })];
|
|
280
|
+
}
|
|
281
|
+
txPromise = request({ method: method, params: params });
|
|
282
|
+
txPromise.catch(function () { return undefined; });
|
|
283
|
+
txChainId_1 = this.registry.resolveChainId(provider);
|
|
284
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
285
|
+
var payload, e_4;
|
|
286
|
+
return __generator(this, function (_a) {
|
|
287
|
+
switch (_a.label) {
|
|
288
|
+
case 0:
|
|
289
|
+
_a.trys.push([0, 3, , 4]);
|
|
290
|
+
return [4 /*yield*/, this.buildTransactionEventPayload(params, provider, txChainId_1)];
|
|
291
|
+
case 1:
|
|
292
|
+
payload = _a.sent();
|
|
293
|
+
return [4 /*yield*/, this.deps.transaction(__assign({ status: TransactionStatus.STARTED }, payload))];
|
|
294
|
+
case 2:
|
|
295
|
+
_a.sent();
|
|
296
|
+
return [3 /*break*/, 4];
|
|
297
|
+
case 3:
|
|
298
|
+
e_4 = _a.sent();
|
|
299
|
+
logger.error("Formo: Failed to track transaction start", e_4);
|
|
300
|
+
return [3 /*break*/, 4];
|
|
301
|
+
case 4: return [2 /*return*/];
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
}); })();
|
|
305
|
+
_c.label = 5;
|
|
306
|
+
case 5:
|
|
307
|
+
_c.trys.push([5, 7, , 8]);
|
|
308
|
+
return [4 /*yield*/, txPromise];
|
|
309
|
+
case 6:
|
|
310
|
+
transactionHash_1 = _c.sent();
|
|
311
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
312
|
+
var payload, e_5;
|
|
313
|
+
return __generator(this, function (_a) {
|
|
314
|
+
switch (_a.label) {
|
|
315
|
+
case 0:
|
|
316
|
+
_a.trys.push([0, 3, , 4]);
|
|
317
|
+
return [4 /*yield*/, this.buildTransactionEventPayload(params, provider, txChainId_1)];
|
|
318
|
+
case 1:
|
|
319
|
+
payload = _a.sent();
|
|
320
|
+
return [4 /*yield*/, this.deps.transaction(__assign(__assign({ status: TransactionStatus.BROADCASTED }, payload), { transactionHash: transactionHash_1 }))];
|
|
321
|
+
case 2:
|
|
322
|
+
_a.sent();
|
|
323
|
+
// Start async polling for transaction receipt
|
|
324
|
+
this.pollTransactionReceipt(provider, transactionHash_1, payload);
|
|
325
|
+
return [3 /*break*/, 4];
|
|
326
|
+
case 3:
|
|
327
|
+
e_5 = _a.sent();
|
|
328
|
+
logger.error("Formo: Failed to track transaction broadcast", e_5);
|
|
329
|
+
return [3 /*break*/, 4];
|
|
330
|
+
case 4: return [2 /*return*/];
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
}); })();
|
|
334
|
+
return [2 /*return*/, transactionHash_1];
|
|
335
|
+
case 7:
|
|
336
|
+
error_2 = _c.sent();
|
|
337
|
+
rpcError = error_2;
|
|
338
|
+
if ((rpcError === null || rpcError === void 0 ? void 0 : rpcError.code) === 4001) {
|
|
339
|
+
// Use the already cast rpcError to avoid duplication
|
|
340
|
+
(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
341
|
+
var payload, e_6;
|
|
342
|
+
return __generator(this, function (_a) {
|
|
343
|
+
switch (_a.label) {
|
|
344
|
+
case 0:
|
|
345
|
+
_a.trys.push([0, 3, , 4]);
|
|
346
|
+
return [4 /*yield*/, this.buildTransactionEventPayload(params, provider, txChainId_1)];
|
|
347
|
+
case 1:
|
|
348
|
+
payload = _a.sent();
|
|
349
|
+
return [4 /*yield*/, this.deps.transaction(__assign({ status: TransactionStatus.REJECTED }, payload))];
|
|
350
|
+
case 2:
|
|
351
|
+
_a.sent();
|
|
352
|
+
return [3 /*break*/, 4];
|
|
353
|
+
case 3:
|
|
354
|
+
e_6 = _a.sent();
|
|
355
|
+
logger.error("Formo: Failed to track transaction rejection", e_6);
|
|
356
|
+
return [3 /*break*/, 4];
|
|
357
|
+
case 4: return [2 /*return*/];
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}); })();
|
|
361
|
+
}
|
|
362
|
+
throw error_2;
|
|
363
|
+
case 8: return [2 /*return*/, request({ method: method, params: params })];
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
}); };
|
|
367
|
+
// Mark the wrapper so we can detect if request is replaced externally and keep a reference on provider
|
|
368
|
+
wrappedRequest[WRAPPED_REQUEST_SYMBOL] = true;
|
|
369
|
+
// Both writes go inside the try. A frozen or non-extensible provider
|
|
370
|
+
// throws on the symbol assignment just as readily as on `request`, and
|
|
371
|
+
// that one used to sit outside the guard, so an unwrappable provider
|
|
372
|
+
// aborted registration instead of being skipped.
|
|
373
|
+
try {
|
|
374
|
+
provider[WRAPPED_REQUEST_REF_SYMBOL] =
|
|
375
|
+
wrappedRequest;
|
|
376
|
+
provider.request = wrappedRequest;
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
catch (e) {
|
|
380
|
+
logger.warn("Failed to wrap provider.request; skipping", e);
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
EvmRequestTracker.prototype.buildSignatureEventPayload = function (method, params,
|
|
385
|
+
// Intentionally not read. Kept for positional call-site arity.
|
|
386
|
+
_response, chainId, provider) {
|
|
387
|
+
var _a;
|
|
388
|
+
var rawAddress = method === "personal_sign"
|
|
389
|
+
? params[1]
|
|
390
|
+
: params[0];
|
|
391
|
+
var validAddress = validateAndChecksumAddress(rawAddress);
|
|
392
|
+
if (!validAddress) {
|
|
393
|
+
throw new Error("Invalid address in signature payload: ".concat(rawAddress));
|
|
394
|
+
}
|
|
395
|
+
var effectiveChainId = (_a = chainId !== null && chainId !== void 0 ? chainId : this.wallet.evmChainId) !== null && _a !== void 0 ? _a : undefined;
|
|
396
|
+
// Only the active provider may write central wallet state - see the same
|
|
397
|
+
// guard in buildTransactionEventPayload.
|
|
398
|
+
if (!provider || provider === this.wallet.provider || !this.wallet.provider) {
|
|
399
|
+
this.wallet.backfill(validAddress, effectiveChainId, provider);
|
|
400
|
+
}
|
|
401
|
+
var basePayload = {
|
|
402
|
+
chainId: effectiveChainId,
|
|
403
|
+
address: validAddress,
|
|
404
|
+
};
|
|
405
|
+
if (method === "personal_sign") {
|
|
406
|
+
return __assign(__assign({}, basePayload), { message: hexToUtf8(params[0]) });
|
|
407
|
+
}
|
|
408
|
+
// eth_signTypedData*: params[1] is the full EIP-712 struct.
|
|
409
|
+
return __assign(__assign({}, basePayload), { message: params[1] });
|
|
410
|
+
};
|
|
411
|
+
EvmRequestTracker.prototype.buildTransactionEventPayload = function (params, provider,
|
|
412
|
+
/**
|
|
413
|
+
* Chain resolved once for this request's whole lifecycle. Passing it keeps
|
|
414
|
+
* every status of one transaction on the same chain even if the user
|
|
415
|
+
* switches network while the wallet prompt is open.
|
|
416
|
+
*/
|
|
417
|
+
capturedChainId) {
|
|
418
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
419
|
+
var _a, data, from, to, value, validAddress, chainId;
|
|
420
|
+
return __generator(this, function (_b) {
|
|
421
|
+
_a = params[0], data = _a.data, from = _a.from, to = _a.to, value = _a.value;
|
|
422
|
+
validAddress = validateAndChecksumAddress(from);
|
|
423
|
+
if (!validAddress) {
|
|
424
|
+
throw new Error("Invalid address in transaction payload: ".concat(from));
|
|
425
|
+
}
|
|
426
|
+
chainId = capturedChainId !== null && capturedChainId !== void 0 ? capturedChainId : this.registry.resolveChainId(provider);
|
|
427
|
+
// Only the ACTIVE provider may write central wallet state. A request from
|
|
428
|
+
// a second, non-active wallet would otherwise overwrite the active
|
|
429
|
+
// provider's address and chain, and every later request through the active
|
|
430
|
+
// provider would then trust the other wallet's chain - persistent
|
|
431
|
+
// mis-attribution, and a way around `excludeChains`.
|
|
432
|
+
if (!provider || provider === this.wallet.provider || !this.wallet.provider) {
|
|
433
|
+
this.wallet.backfill(validAddress, chainId, provider);
|
|
434
|
+
}
|
|
435
|
+
return [2 /*return*/, {
|
|
436
|
+
chainId: chainId,
|
|
437
|
+
data: data,
|
|
438
|
+
address: validAddress,
|
|
439
|
+
to: to,
|
|
440
|
+
value: value,
|
|
441
|
+
}];
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
};
|
|
445
|
+
/**
|
|
446
|
+
* Polls for transaction receipt and emits tx.status = CONFIRMED or REVERTED.
|
|
447
|
+
*/
|
|
448
|
+
EvmRequestTracker.prototype.pollTransactionReceipt = function (provider_1, transactionHash_2, payload_1) {
|
|
449
|
+
return __awaiter(this, arguments, void 0, function (provider, transactionHash, payload, maxAttempts, intervalMs) {
|
|
450
|
+
var attempts, poll;
|
|
451
|
+
var _this = this;
|
|
452
|
+
if (maxAttempts === void 0) { maxAttempts = 10; }
|
|
453
|
+
if (intervalMs === void 0) { intervalMs = 3000; }
|
|
454
|
+
return __generator(this, function (_a) {
|
|
455
|
+
attempts = 0;
|
|
456
|
+
if (!provider)
|
|
457
|
+
return [2 /*return*/];
|
|
458
|
+
poll = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
459
|
+
var receipt, e_7;
|
|
460
|
+
return __generator(this, function (_a) {
|
|
461
|
+
switch (_a.label) {
|
|
462
|
+
case 0:
|
|
463
|
+
if (this.disposed)
|
|
464
|
+
return [2 /*return*/];
|
|
465
|
+
_a.label = 1;
|
|
466
|
+
case 1:
|
|
467
|
+
_a.trys.push([1, 3, , 4]);
|
|
468
|
+
return [4 /*yield*/, provider.request({
|
|
469
|
+
method: "eth_getTransactionReceipt",
|
|
470
|
+
params: [transactionHash],
|
|
471
|
+
})];
|
|
472
|
+
case 2:
|
|
473
|
+
receipt = (_a.sent());
|
|
474
|
+
if (receipt) {
|
|
475
|
+
// status: 1 = success, 0 = reverted
|
|
476
|
+
if (receipt.status === "0x1" || receipt.status === 1) {
|
|
477
|
+
this.deps
|
|
478
|
+
.transaction(__assign(__assign({ status: TransactionStatus.CONFIRMED }, payload), { transactionHash: transactionHash }))
|
|
479
|
+
.catch(function (e) {
|
|
480
|
+
return logger.error("Formo: Failed to track transaction confirmation", e);
|
|
481
|
+
});
|
|
482
|
+
return [2 /*return*/];
|
|
483
|
+
}
|
|
484
|
+
else if (receipt.status === "0x0" || receipt.status === 0) {
|
|
485
|
+
this.deps
|
|
486
|
+
.transaction(__assign(__assign({ status: TransactionStatus.REVERTED }, payload), { transactionHash: transactionHash }))
|
|
487
|
+
.catch(function (e) {
|
|
488
|
+
return logger.error("Formo: Failed to track transaction revert", e);
|
|
489
|
+
});
|
|
490
|
+
return [2 /*return*/];
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return [3 /*break*/, 4];
|
|
494
|
+
case 3:
|
|
495
|
+
e_7 = _a.sent();
|
|
496
|
+
logger.error("Error polling transaction receipt", e_7);
|
|
497
|
+
return [3 /*break*/, 4];
|
|
498
|
+
case 4:
|
|
499
|
+
attempts++;
|
|
500
|
+
if (attempts < maxAttempts)
|
|
501
|
+
this.schedulePoll(poll, intervalMs);
|
|
502
|
+
return [2 /*return*/];
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
}); };
|
|
506
|
+
poll();
|
|
507
|
+
return [2 /*return*/];
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
};
|
|
511
|
+
/**
|
|
512
|
+
* One `transaction` event per call in an EIP-5792 batch.
|
|
513
|
+
*
|
|
514
|
+
* A batch is not a transaction. It maps to several on-chain transactions,
|
|
515
|
+
* so reporting it as one event would understate volume and make revenue and
|
|
516
|
+
* per-contract attribution wrong for every app that adopts smart accounts.
|
|
517
|
+
* Each call is reported on its own, carrying the batch id so the calls can
|
|
518
|
+
* be reassembled downstream.
|
|
519
|
+
*
|
|
520
|
+
* Status is per BATCH, because that is what `wallet_getCallsStatus` reports.
|
|
521
|
+
* When it resolves, every call in the batch moves together, except where
|
|
522
|
+
* per-call receipts say otherwise on a non-atomic batch.
|
|
523
|
+
*/
|
|
524
|
+
EvmRequestTracker.prototype.trackBatchedCalls = function (provider, request, params) {
|
|
525
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
526
|
+
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;
|
|
527
|
+
var _c;
|
|
528
|
+
return __generator(this, function (_d) {
|
|
529
|
+
switch (_d.label) {
|
|
530
|
+
case 0:
|
|
531
|
+
if (!this.deps.isAutocaptureEnabled("transaction")) {
|
|
532
|
+
logger.debug("Transaction event skipped (autocapture.transaction: false)", {
|
|
533
|
+
method: "wallet_sendCalls",
|
|
534
|
+
});
|
|
535
|
+
return [2 /*return*/, request({ method: "wallet_sendCalls", params: params })];
|
|
536
|
+
}
|
|
537
|
+
sendPromise = request({ method: "wallet_sendCalls", params: params });
|
|
538
|
+
sendPromise.catch(function () { return undefined; });
|
|
539
|
+
batch = params[0];
|
|
540
|
+
calls = Array.isArray(batch === null || batch === void 0 ? void 0 : batch.calls) ? batch.calls : [];
|
|
541
|
+
declared = typeof (batch === null || batch === void 0 ? void 0 : batch.chainId) === "string" ? parseChainId(batch.chainId) : undefined;
|
|
542
|
+
chainId = declared || this.registry.resolveChainId(provider);
|
|
543
|
+
address = validateAndChecksumAddress((_c = batch === null || batch === void 0 ? void 0 : batch.from) !== null && _c !== void 0 ? _c : "");
|
|
544
|
+
if (!address) {
|
|
545
|
+
// Nothing can be attributed without a sender, and inventing one would
|
|
546
|
+
// be worse than reporting nothing. The user's call still goes through.
|
|
547
|
+
logger.warn("Formo: wallet_sendCalls has no valid `from`; not tracking", {
|
|
548
|
+
from: batch === null || batch === void 0 ? void 0 : batch.from,
|
|
549
|
+
});
|
|
550
|
+
return [2 /*return*/, sendPromise];
|
|
551
|
+
}
|
|
552
|
+
if (calls.length === 0) {
|
|
553
|
+
logger.debug("Formo: wallet_sendCalls carried no calls");
|
|
554
|
+
return [2 /*return*/, sendPromise];
|
|
555
|
+
}
|
|
556
|
+
// Only the ACTIVE provider may write central wallet state, for the same
|
|
557
|
+
// reason as the single-transaction path: a second wallet would otherwise
|
|
558
|
+
// overwrite the active provider's address and chain.
|
|
559
|
+
if (!provider || provider === this.wallet.provider || !this.wallet.provider) {
|
|
560
|
+
this.wallet.backfill(address, chainId, provider);
|
|
561
|
+
}
|
|
562
|
+
payloads = calls.map(function (call, index) { return ({
|
|
563
|
+
chainId: chainId,
|
|
564
|
+
address: address,
|
|
565
|
+
to: call === null || call === void 0 ? void 0 : call.to,
|
|
566
|
+
value: call === null || call === void 0 ? void 0 : call.value,
|
|
567
|
+
data: call === null || call === void 0 ? void 0 : call.data,
|
|
568
|
+
properties: {
|
|
569
|
+
batch_size: calls.length,
|
|
570
|
+
batch_index: index,
|
|
571
|
+
},
|
|
572
|
+
}); });
|
|
573
|
+
// STARTED carries no batch id: the wallet has not issued one yet, exactly
|
|
574
|
+
// as `eth_sendTransaction` has no hash at this point. Position within the
|
|
575
|
+
// batch is known, and is what groups these until the id arrives.
|
|
576
|
+
for (_i = 0, payloads_1 = payloads; _i < payloads_1.length; _i++) {
|
|
577
|
+
p = payloads_1[_i];
|
|
578
|
+
properties = p.properties, rest = __rest(p, ["properties"]);
|
|
579
|
+
this.deps
|
|
580
|
+
.transaction(__assign({ status: TransactionStatus.STARTED }, rest), properties)
|
|
581
|
+
.catch(function (e) { return logger.error("Formo: Failed to track batch call start", e); });
|
|
582
|
+
}
|
|
583
|
+
_d.label = 1;
|
|
584
|
+
case 1:
|
|
585
|
+
_d.trys.push([1, 3, , 4]);
|
|
586
|
+
return [4 /*yield*/, sendPromise];
|
|
587
|
+
case 2:
|
|
588
|
+
result = _d.sent();
|
|
589
|
+
batchId = this.readBatchId(result);
|
|
590
|
+
for (_a = 0, payloads_2 = payloads; _a < payloads_2.length; _a++) {
|
|
591
|
+
p = payloads_2[_a];
|
|
592
|
+
properties = p.properties, rest = __rest(p, ["properties"]);
|
|
593
|
+
this.deps
|
|
594
|
+
.transaction(__assign({ status: TransactionStatus.BROADCASTED }, rest), __assign(__assign({}, properties), (batchId ? { batch_id: batchId } : {})))
|
|
595
|
+
.catch(function (e) {
|
|
596
|
+
return logger.error("Formo: Failed to track batch call broadcast", e);
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
if (batchId)
|
|
600
|
+
this.pollBatchStatus(provider, batchId, payloads);
|
|
601
|
+
return [2 /*return*/, result];
|
|
602
|
+
case 3:
|
|
603
|
+
error_3 = _d.sent();
|
|
604
|
+
rpcError = error_3;
|
|
605
|
+
if ((rpcError === null || rpcError === void 0 ? void 0 : rpcError.code) === 4001) {
|
|
606
|
+
// One rejection dismisses the whole prompt, so every call in it is
|
|
607
|
+
// rejected. Reporting only the first would undercount.
|
|
608
|
+
for (_b = 0, payloads_3 = payloads; _b < payloads_3.length; _b++) {
|
|
609
|
+
p = payloads_3[_b];
|
|
610
|
+
properties = p.properties, rest = __rest(p, ["properties"]);
|
|
611
|
+
this.deps
|
|
612
|
+
.transaction(__assign({ status: TransactionStatus.REJECTED }, rest), properties)
|
|
613
|
+
.catch(function (e) {
|
|
614
|
+
return logger.error("Formo: Failed to track batch call rejection", e);
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
throw error_3;
|
|
619
|
+
case 4: return [2 /*return*/];
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
});
|
|
623
|
+
};
|
|
624
|
+
/**
|
|
625
|
+
* How one call in a settled batch ended.
|
|
626
|
+
*
|
|
627
|
+
* A per-call receipt is authoritative where it exists: that is what makes a
|
|
628
|
+
* partially reverted non-atomic batch report honestly rather than tarring
|
|
629
|
+
* every call with the batch's worst outcome. A receipt whose own status is
|
|
630
|
+
* unreadable falls back to the batch verdict rather than being assumed good.
|
|
631
|
+
*
|
|
632
|
+
* The codes are EIP-5792's: 200 confirmed, 400 failed BEFORE landing on
|
|
633
|
+
* chain, 500 reverted, 600 partially reverted. 400 is a rejection, not a
|
|
634
|
+
* revert - nothing was mined, so calling it reverted would misreport gas
|
|
635
|
+
* spent and on-chain activity that never happened.
|
|
636
|
+
*
|
|
637
|
+
* Returns undefined when the call cannot be decided, which happens on 600
|
|
638
|
+
* for a call the wallet gave no receipt for.
|
|
639
|
+
*/
|
|
640
|
+
EvmRequestTracker.prototype.batchCallOutcome = function (code, receipt) {
|
|
641
|
+
var receiptStatus = receipt === null || receipt === void 0 ? void 0 : receipt.status;
|
|
642
|
+
if (receiptStatus !== undefined) {
|
|
643
|
+
return receiptStatus === "0x0" || receiptStatus === 0
|
|
644
|
+
? TransactionStatus.REVERTED
|
|
645
|
+
: TransactionStatus.CONFIRMED;
|
|
646
|
+
}
|
|
647
|
+
if (code >= 600)
|
|
648
|
+
return undefined;
|
|
649
|
+
if (code >= 500)
|
|
650
|
+
return TransactionStatus.REVERTED;
|
|
651
|
+
if (code >= 400)
|
|
652
|
+
return TransactionStatus.REJECTED;
|
|
653
|
+
return TransactionStatus.CONFIRMED;
|
|
654
|
+
};
|
|
655
|
+
/**
|
|
656
|
+
* The batch identifier from a `wallet_sendCalls` result.
|
|
657
|
+
*
|
|
658
|
+
* EIP-5792 settled on `{ id }`, but wallets shipped against the earlier
|
|
659
|
+
* draft return a bare string. Both are accepted so a wallet on either
|
|
660
|
+
* version is still grouped.
|
|
661
|
+
*/
|
|
662
|
+
EvmRequestTracker.prototype.readBatchId = function (result) {
|
|
663
|
+
if (typeof result === "string" && result.length > 0)
|
|
664
|
+
return result;
|
|
665
|
+
if (result && typeof result === "object") {
|
|
666
|
+
var id = result.id;
|
|
667
|
+
if (typeof id === "string" && id.length > 0)
|
|
668
|
+
return id;
|
|
669
|
+
}
|
|
670
|
+
return undefined;
|
|
671
|
+
};
|
|
672
|
+
/**
|
|
673
|
+
* Resolve a batch through `wallet_getCallsStatus`.
|
|
674
|
+
*
|
|
675
|
+
* The status codes are EIP-5792's: 100 pending, 200 confirmed, 400 failed
|
|
676
|
+
* before landing, 500 reverted, 600 partially reverted. Anything below 200
|
|
677
|
+
* means keep waiting.
|
|
678
|
+
*
|
|
679
|
+
* A per-call receipt wins over the batch verdict where one exists, which is
|
|
680
|
+
* what makes a partially reverted non-atomic batch report honestly instead
|
|
681
|
+
* of marking every call with the batch's worst outcome.
|
|
682
|
+
*/
|
|
683
|
+
EvmRequestTracker.prototype.pollBatchStatus = function (provider_1, batchId_1, payloads_4) {
|
|
684
|
+
return __awaiter(this, arguments, void 0, function (provider, batchId, payloads, maxAttempts, intervalMs) {
|
|
685
|
+
var attempts, poll;
|
|
686
|
+
var _this = this;
|
|
687
|
+
if (maxAttempts === void 0) { maxAttempts = 10; }
|
|
688
|
+
if (intervalMs === void 0) { intervalMs = 3000; }
|
|
689
|
+
return __generator(this, function (_a) {
|
|
690
|
+
if (!provider)
|
|
691
|
+
return [2 /*return*/];
|
|
692
|
+
attempts = 0;
|
|
693
|
+
poll = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
694
|
+
var res, code_1, receipts_1, e_8;
|
|
695
|
+
var _this = this;
|
|
696
|
+
return __generator(this, function (_a) {
|
|
697
|
+
switch (_a.label) {
|
|
698
|
+
case 0:
|
|
699
|
+
if (this.disposed)
|
|
700
|
+
return [2 /*return*/];
|
|
701
|
+
_a.label = 1;
|
|
702
|
+
case 1:
|
|
703
|
+
_a.trys.push([1, 3, , 4]);
|
|
704
|
+
return [4 /*yield*/, provider.request({
|
|
705
|
+
method: "wallet_getCallsStatus",
|
|
706
|
+
params: [batchId],
|
|
707
|
+
})];
|
|
708
|
+
case 2:
|
|
709
|
+
res = (_a.sent());
|
|
710
|
+
code_1 = typeof (res === null || res === void 0 ? void 0 : res.status) === "number" ? res.status : undefined;
|
|
711
|
+
if (code_1 !== undefined && code_1 >= 200) {
|
|
712
|
+
receipts_1 = Array.isArray(res === null || res === void 0 ? void 0 : res.receipts) ? res.receipts : [];
|
|
713
|
+
payloads.forEach(function (p, index) {
|
|
714
|
+
var receipt = receipts_1[index];
|
|
715
|
+
var outcome = _this.batchCallOutcome(code_1, receipt);
|
|
716
|
+
// 600 means SOME calls reverted, so a call with no receipt of its
|
|
717
|
+
// own has not been decided. Reporting it either way would invent
|
|
718
|
+
// a result; leaving it unsettled is the honest answer.
|
|
719
|
+
if (outcome === undefined)
|
|
720
|
+
return;
|
|
721
|
+
var properties = p.properties, rest = __rest(p, ["properties"]);
|
|
722
|
+
_this.deps
|
|
723
|
+
.transaction(__assign(__assign({ status: outcome }, rest), ((receipt === null || receipt === void 0 ? void 0 : receipt.transactionHash)
|
|
724
|
+
? { transactionHash: receipt.transactionHash }
|
|
725
|
+
: {})), __assign(__assign({}, properties), { batch_id: batchId }))
|
|
726
|
+
.catch(function (e) {
|
|
727
|
+
return logger.error("Formo: Failed to track batch call outcome", e);
|
|
728
|
+
});
|
|
729
|
+
});
|
|
730
|
+
return [2 /*return*/];
|
|
731
|
+
}
|
|
732
|
+
return [3 /*break*/, 4];
|
|
733
|
+
case 3:
|
|
734
|
+
e_8 = _a.sent();
|
|
735
|
+
logger.error("Error polling batch call status", e_8);
|
|
736
|
+
return [3 /*break*/, 4];
|
|
737
|
+
case 4:
|
|
738
|
+
attempts++;
|
|
739
|
+
if (attempts < maxAttempts)
|
|
740
|
+
this.schedulePoll(poll, intervalMs);
|
|
741
|
+
return [2 /*return*/];
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
}); };
|
|
745
|
+
poll();
|
|
746
|
+
return [2 /*return*/];
|
|
747
|
+
});
|
|
748
|
+
});
|
|
749
|
+
};
|
|
750
|
+
return EvmRequestTracker;
|
|
751
|
+
}());
|
|
752
|
+
export { EvmRequestTracker };
|
|
753
|
+
//# sourceMappingURL=EvmRequestTracker.js.map
|