@pimlico/alto 0.0.0-main.20250203T212650 → 0.0.0-main.20250205T150420
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/esm/cli/config/bundler.d.ts +0 -30
- package/esm/cli/config/bundler.js +1 -6
- package/esm/cli/config/bundler.js.map +1 -1
- package/esm/cli/config/options.js +1 -30
- package/esm/cli/config/options.js.map +1 -1
- package/esm/cli/setupServer.js +5 -5
- package/esm/cli/setupServer.js.map +1 -1
- package/esm/executor/executor.d.ts +34 -44
- package/esm/executor/executor.js +103 -463
- package/esm/executor/executor.js.map +1 -1
- package/esm/executor/executorManager.d.ts +20 -10
- package/esm/executor/executorManager.js +371 -310
- package/esm/executor/executorManager.js.map +1 -1
- package/esm/executor/filterOpsAndEStimateGas.d.ts +28 -0
- package/esm/executor/filterOpsAndEStimateGas.js +191 -0
- package/esm/executor/filterOpsAndEStimateGas.js.map +1 -0
- package/esm/executor/senderManager.d.ts +2 -0
- package/esm/executor/senderManager.js +32 -0
- package/esm/executor/senderManager.js.map +1 -1
- package/esm/executor/utils.d.ts +21 -20
- package/esm/executor/utils.js +46 -185
- package/esm/executor/utils.js.map +1 -1
- package/esm/handlers/eventManager.d.ts +4 -1
- package/esm/handlers/eventManager.js +10 -8
- package/esm/handlers/eventManager.js.map +1 -1
- package/esm/mempool/mempool.d.ts +15 -11
- package/esm/mempool/mempool.js +207 -176
- package/esm/mempool/mempool.js.map +1 -1
- package/esm/mempool/store.d.ts +7 -7
- package/esm/mempool/store.js +13 -12
- package/esm/mempool/store.js.map +1 -1
- package/esm/rpc/nonceQueuer.js +2 -2
- package/esm/rpc/nonceQueuer.js.map +1 -1
- package/esm/rpc/rpcHandler.js +27 -31
- package/esm/rpc/rpcHandler.js.map +1 -1
- package/esm/rpc/validation/SafeValidator.d.ts +1 -1
- package/esm/rpc/validation/SafeValidator.js +1 -11
- package/esm/rpc/validation/SafeValidator.js.map +1 -1
- package/esm/rpc/validation/UnsafeValidator.d.ts +1 -1
- package/esm/rpc/validation/UnsafeValidator.js +4 -6
- package/esm/rpc/validation/UnsafeValidator.js.map +1 -1
- package/esm/types/mempool.d.ts +40 -41
- package/esm/types/mempool.js.map +1 -1
- package/esm/types/schemas.d.ts +0 -4
- package/esm/types/schemas.js.map +1 -1
- package/esm/utils/userop.d.ts +8 -3
- package/esm/utils/userop.js +5 -3
- package/esm/utils/userop.js.map +1 -1
- package/lib/cli/config/bundler.d.ts +0 -30
- package/lib/cli/config/bundler.js +1 -6
- package/lib/cli/config/bundler.js.map +1 -1
- package/lib/cli/config/options.js +1 -30
- package/lib/cli/config/options.js.map +1 -1
- package/lib/cli/setupServer.js +5 -5
- package/lib/cli/setupServer.js.map +1 -1
- package/lib/executor/executor.d.ts +34 -44
- package/lib/executor/executor.js +100 -460
- package/lib/executor/executor.js.map +1 -1
- package/lib/executor/executorManager.d.ts +20 -10
- package/lib/executor/executorManager.js +370 -309
- package/lib/executor/executorManager.js.map +1 -1
- package/lib/executor/filterOpsAndEStimateGas.d.ts +28 -0
- package/lib/executor/filterOpsAndEStimateGas.js +218 -0
- package/lib/executor/filterOpsAndEStimateGas.js.map +1 -0
- package/lib/executor/senderManager.d.ts +2 -0
- package/lib/executor/senderManager.js +32 -0
- package/lib/executor/senderManager.js.map +1 -1
- package/lib/executor/utils.d.ts +21 -20
- package/lib/executor/utils.js +49 -186
- package/lib/executor/utils.js.map +1 -1
- package/lib/handlers/eventManager.d.ts +4 -1
- package/lib/handlers/eventManager.js +10 -8
- package/lib/handlers/eventManager.js.map +1 -1
- package/lib/mempool/mempool.d.ts +15 -11
- package/lib/mempool/mempool.js +206 -175
- package/lib/mempool/mempool.js.map +1 -1
- package/lib/mempool/store.d.ts +7 -7
- package/lib/mempool/store.js +13 -12
- package/lib/mempool/store.js.map +1 -1
- package/lib/rpc/nonceQueuer.js +1 -1
- package/lib/rpc/nonceQueuer.js.map +1 -1
- package/lib/rpc/rpcHandler.js +26 -30
- package/lib/rpc/rpcHandler.js.map +1 -1
- package/lib/rpc/validation/SafeValidator.d.ts +1 -1
- package/lib/rpc/validation/SafeValidator.js +1 -11
- package/lib/rpc/validation/SafeValidator.js.map +1 -1
- package/lib/rpc/validation/UnsafeValidator.d.ts +1 -1
- package/lib/rpc/validation/UnsafeValidator.js +3 -5
- package/lib/rpc/validation/UnsafeValidator.js.map +1 -1
- package/lib/types/mempool.d.ts +40 -41
- package/lib/types/mempool.js.map +1 -1
- package/lib/types/schemas.d.ts +0 -4
- package/lib/types/schemas.js.map +1 -1
- package/lib/utils/userop.d.ts +8 -3
- package/lib/utils/userop.js +7 -5
- package/lib/utils/userop.js.map +1 -1
- package/package.json +1 -1
- package/esm/executor/types.d.ts +0 -25
- package/esm/executor/types.js +0 -2
- package/esm/executor/types.js.map +0 -1
- package/lib/executor/types.d.ts +0 -25
- package/lib/executor/types.js +0 -3
- package/lib/executor/types.js.map +0 -1
|
@@ -4,16 +4,19 @@ exports.ExecutorManager = void 0;
|
|
|
4
4
|
const types_1 = require("../types/index.js");
|
|
5
5
|
const utils_1 = require("../utils/index.js");
|
|
6
6
|
const viem_1 = require("viem");
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
const abitype_1 = require("abitype");
|
|
8
|
+
const utils_2 = require("./utils.js");
|
|
9
|
+
function getTransactionsFromUserOperationEntries(submittedOps) {
|
|
10
|
+
const transactionInfos = submittedOps.map((userOpInfo) => userOpInfo.transactionInfo);
|
|
11
|
+
// Remove duplicates
|
|
12
|
+
return Array.from(new Set(transactionInfos));
|
|
11
13
|
}
|
|
12
14
|
const MIN_INTERVAL = 100; // 0.1 seconds (100ms)
|
|
13
15
|
const MAX_INTERVAL = 1000; // Capped at 1 second (1000ms)
|
|
14
16
|
const SCALE_FACTOR = 10; // Interval increases by 5ms per task per minute
|
|
15
17
|
const RPM_WINDOW = 60000; // 1 minute window in ms
|
|
16
18
|
class ExecutorManager {
|
|
19
|
+
senderManager;
|
|
17
20
|
config;
|
|
18
21
|
executor;
|
|
19
22
|
mempool;
|
|
@@ -27,7 +30,7 @@ class ExecutorManager {
|
|
|
27
30
|
eventManager;
|
|
28
31
|
opsCount = [];
|
|
29
32
|
bundlingMode;
|
|
30
|
-
constructor({ config, executor, mempool, monitor, reputationManager, metrics, gasPriceManager, eventManager }) {
|
|
33
|
+
constructor({ config, executor, mempool, monitor, reputationManager, metrics, gasPriceManager, eventManager, senderManager }) {
|
|
31
34
|
this.config = config;
|
|
32
35
|
this.reputationManager = reputationManager;
|
|
33
36
|
this.executor = executor;
|
|
@@ -39,6 +42,7 @@ class ExecutorManager {
|
|
|
39
42
|
this.metrics = metrics;
|
|
40
43
|
this.gasPriceManager = gasPriceManager;
|
|
41
44
|
this.eventManager = eventManager;
|
|
45
|
+
this.senderManager = senderManager;
|
|
42
46
|
this.bundlingMode = this.config.bundleMode;
|
|
43
47
|
if (this.bundlingMode === "auto") {
|
|
44
48
|
this.autoScalingBundling();
|
|
@@ -56,12 +60,18 @@ class ExecutorManager {
|
|
|
56
60
|
async autoScalingBundling() {
|
|
57
61
|
const now = Date.now();
|
|
58
62
|
this.opsCount = this.opsCount.filter((timestamp) => now - timestamp < RPM_WINDOW);
|
|
59
|
-
const
|
|
60
|
-
if (
|
|
61
|
-
const opsCount =
|
|
63
|
+
const bundles = await this.mempool.getBundles();
|
|
64
|
+
if (bundles.length > 0) {
|
|
65
|
+
const opsCount = bundles
|
|
66
|
+
.map(({ userOps }) => userOps.length)
|
|
67
|
+
.reduce((a, b) => a + b);
|
|
68
|
+
// Add timestamps for each task
|
|
62
69
|
const timestamp = Date.now();
|
|
63
|
-
this.opsCount.push(...Array(opsCount).fill(timestamp));
|
|
64
|
-
|
|
70
|
+
this.opsCount.push(...Array(opsCount).fill(timestamp));
|
|
71
|
+
// Send bundles to executor
|
|
72
|
+
await Promise.all(bundles.map(async (bundle) => {
|
|
73
|
+
await this.sendBundleToExecutor(bundle);
|
|
74
|
+
}));
|
|
65
75
|
}
|
|
66
76
|
const rpm = this.opsCount.length;
|
|
67
77
|
// Calculate next interval with linear scaling
|
|
@@ -72,145 +82,106 @@ class ExecutorManager {
|
|
|
72
82
|
setTimeout(this.autoScalingBundling.bind(this), nextInterval);
|
|
73
83
|
}
|
|
74
84
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
opsToBundle.push(ops);
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
if (opsToBundle.length === 0) {
|
|
87
|
-
return [];
|
|
88
|
-
}
|
|
89
|
-
return opsToBundle;
|
|
90
|
-
}
|
|
91
|
-
async bundleNow() {
|
|
92
|
-
const ops = await this.mempool.process(this.config.maxGasPerBundle, 1);
|
|
93
|
-
if (ops.length === 0) {
|
|
85
|
+
// Debug endpoint
|
|
86
|
+
async sendBundleNow() {
|
|
87
|
+
const bundles = await this.mempool.getBundles(1);
|
|
88
|
+
const bundle = bundles[0];
|
|
89
|
+
if (bundle.userOps.length === 0) {
|
|
94
90
|
throw new Error("no ops to bundle");
|
|
95
91
|
}
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
opEntryPointMap.set(op.entryPoint, []);
|
|
100
|
-
}
|
|
101
|
-
opEntryPointMap.get(op.entryPoint)?.push(op.userOperation);
|
|
102
|
-
}
|
|
103
|
-
const txHashes = [];
|
|
104
|
-
await Promise.all(this.config.entrypoints.map(async (entryPoint) => {
|
|
105
|
-
const ops = opEntryPointMap.get(entryPoint);
|
|
106
|
-
if (ops) {
|
|
107
|
-
const txHash = await this.sendToExecutor(entryPoint, ops);
|
|
108
|
-
if (!txHash) {
|
|
109
|
-
throw new Error("no tx hash");
|
|
110
|
-
}
|
|
111
|
-
txHashes.push(txHash);
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
this.logger.warn({ entryPoint }, "no user operations for entry point");
|
|
115
|
-
}
|
|
116
|
-
}));
|
|
117
|
-
return txHashes;
|
|
118
|
-
}
|
|
119
|
-
async sendToExecutor(entryPoint, mempoolOps) {
|
|
120
|
-
const ops = mempoolOps.map((op) => op);
|
|
121
|
-
const bundles = [];
|
|
122
|
-
if (ops.length > 0) {
|
|
123
|
-
bundles.push(await this.executor.bundle(entryPoint, ops));
|
|
124
|
-
}
|
|
125
|
-
for (const bundle of bundles) {
|
|
126
|
-
const isBundleSuccess = bundle.every((result) => result.status === "success");
|
|
127
|
-
const isBundleResubmit = bundle.every((result) => result.status === "resubmit");
|
|
128
|
-
const isBundleFailed = bundle.every((result) => result.status === "failure");
|
|
129
|
-
if (isBundleSuccess) {
|
|
130
|
-
this.metrics.bundlesSubmitted
|
|
131
|
-
.labels({ status: "success" })
|
|
132
|
-
.inc();
|
|
133
|
-
}
|
|
134
|
-
if (isBundleResubmit) {
|
|
135
|
-
this.metrics.bundlesSubmitted
|
|
136
|
-
.labels({ status: "resubmit" })
|
|
137
|
-
.inc();
|
|
138
|
-
}
|
|
139
|
-
if (isBundleFailed) {
|
|
140
|
-
this.metrics.bundlesSubmitted.labels({ status: "failed" }).inc();
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
const results = bundles.flat();
|
|
144
|
-
const filteredOutOps = mempoolOps.length - results.length;
|
|
145
|
-
if (filteredOutOps > 0) {
|
|
146
|
-
this.logger.debug({ filteredOutOps }, "user operations filtered out");
|
|
147
|
-
this.metrics.userOperationsSubmitted
|
|
148
|
-
.labels({ status: "filtered" })
|
|
149
|
-
.inc(filteredOutOps);
|
|
150
|
-
}
|
|
151
|
-
let txHash = undefined;
|
|
152
|
-
for (const result of results) {
|
|
153
|
-
if (result.status === "success") {
|
|
154
|
-
const res = result.value;
|
|
155
|
-
this.mempool.markSubmitted(res.userOperation.userOperationHash, res.transactionInfo);
|
|
156
|
-
this.monitor.setUserOperationStatus(res.userOperation.userOperationHash, {
|
|
157
|
-
status: "submitted",
|
|
158
|
-
transactionHash: res.transactionInfo.transactionHash
|
|
159
|
-
});
|
|
160
|
-
txHash = res.transactionInfo.transactionHash;
|
|
161
|
-
this.startWatchingBlocks(this.handleBlock.bind(this));
|
|
162
|
-
this.metrics.userOperationsSubmitted
|
|
163
|
-
.labels({ status: "success" })
|
|
164
|
-
.inc();
|
|
165
|
-
}
|
|
166
|
-
if (result.status === "failure") {
|
|
167
|
-
const { userOpHash, reason } = result.error;
|
|
168
|
-
this.mempool.removeProcessing(userOpHash);
|
|
169
|
-
this.eventManager.emitDropped(userOpHash, reason, (0, utils_1.getAAError)(reason));
|
|
170
|
-
this.monitor.setUserOperationStatus(userOpHash, {
|
|
171
|
-
status: "rejected",
|
|
172
|
-
transactionHash: null
|
|
173
|
-
});
|
|
174
|
-
this.logger.warn({
|
|
175
|
-
userOperation: JSON.stringify(result.error.userOperation, (_k, v) => typeof v === "bigint" ? v.toString() : v),
|
|
176
|
-
userOpHash,
|
|
177
|
-
reason
|
|
178
|
-
}, "user operation rejected");
|
|
179
|
-
this.metrics.userOperationsSubmitted
|
|
180
|
-
.labels({ status: "failed" })
|
|
181
|
-
.inc();
|
|
182
|
-
}
|
|
183
|
-
if (result.status === "resubmit") {
|
|
184
|
-
this.logger.info({
|
|
185
|
-
userOpHash: result.info.userOpHash,
|
|
186
|
-
reason: result.info.reason
|
|
187
|
-
}, "resubmitting user operation");
|
|
188
|
-
this.mempool.removeProcessing(result.info.userOpHash);
|
|
189
|
-
this.mempool.add(result.info.userOperation, result.info.entryPoint);
|
|
190
|
-
this.metrics.userOperationsResubmitted.inc();
|
|
191
|
-
}
|
|
92
|
+
const txHash = await this.sendBundleToExecutor(bundle);
|
|
93
|
+
if (!txHash) {
|
|
94
|
+
throw new Error("no tx hash");
|
|
192
95
|
}
|
|
193
96
|
return txHash;
|
|
194
97
|
}
|
|
195
|
-
async
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
98
|
+
async sendBundleToExecutor(userOpBundle) {
|
|
99
|
+
const { entryPoint, userOps, version } = userOpBundle;
|
|
100
|
+
if (userOps.length === 0) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
const wallet = await this.senderManager.getWallet();
|
|
104
|
+
const [gasPriceParams, nonce] = await Promise.all([
|
|
105
|
+
this.gasPriceManager.tryGetNetworkGasPrice(),
|
|
106
|
+
this.config.publicClient.getTransactionCount({
|
|
107
|
+
address: wallet.address,
|
|
108
|
+
blockTag: "latest"
|
|
109
|
+
})
|
|
110
|
+
]).catch((_) => {
|
|
111
|
+
return [];
|
|
112
|
+
});
|
|
113
|
+
if (!gasPriceParams || nonce === undefined) {
|
|
114
|
+
this.resubmitUserOperations(userOps, entryPoint, "Failed to get nonce and gas parameters for bundling");
|
|
115
|
+
// Free executor if failed to get initial params.
|
|
116
|
+
this.senderManager.markWalletProcessed(wallet);
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
const bundleResult = await this.executor.bundle({
|
|
120
|
+
executor: wallet,
|
|
121
|
+
userOpBundle,
|
|
122
|
+
nonce,
|
|
123
|
+
gasPriceParams,
|
|
124
|
+
isReplacementTx: false
|
|
125
|
+
});
|
|
126
|
+
// Free wallet if no bundle was sent.
|
|
127
|
+
if (bundleResult.status !== "bundle_success") {
|
|
128
|
+
this.senderManager.markWalletProcessed(wallet);
|
|
129
|
+
}
|
|
130
|
+
// All ops failed simulation, drop them and return.
|
|
131
|
+
if (bundleResult.status === "all_ops_failed_simulation") {
|
|
132
|
+
const { rejectedUserOps } = bundleResult;
|
|
133
|
+
this.dropUserOps(rejectedUserOps);
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
// Unhandled error during simulation, drop all ops.
|
|
137
|
+
if (bundleResult.status === "unhandled_simulation_failure") {
|
|
138
|
+
const { rejectedUserOps } = bundleResult;
|
|
139
|
+
this.dropUserOps(rejectedUserOps);
|
|
140
|
+
this.metrics.bundlesSubmitted.labels({ status: "failed" }).inc();
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
// Resubmit if executor has insufficient funds.
|
|
144
|
+
if (bundleResult.status === "bundle_submission_failure" &&
|
|
145
|
+
bundleResult.reason instanceof viem_1.InsufficientFundsError) {
|
|
146
|
+
const { reason, userOpsToBundle, rejectedUserOps } = bundleResult;
|
|
147
|
+
this.dropUserOps(rejectedUserOps);
|
|
148
|
+
this.resubmitUserOperations(userOpsToBundle, entryPoint, reason.name);
|
|
149
|
+
this.metrics.bundlesSubmitted.labels({ status: "resubmit" }).inc();
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
// Encountered unhandled error during bundle simulation.
|
|
153
|
+
if (bundleResult.status === "bundle_submission_failure") {
|
|
154
|
+
const { rejectedUserOps, userOpsToBundle, reason } = bundleResult;
|
|
155
|
+
this.dropUserOps(rejectedUserOps);
|
|
156
|
+
// NOTE: these ops passed validation, so we can try resubmitting them
|
|
157
|
+
this.resubmitUserOperations(userOpsToBundle, entryPoint, reason instanceof abitype_1.BaseError
|
|
158
|
+
? reason.name
|
|
159
|
+
: "Encountered unhandled error during bundle simulation");
|
|
160
|
+
this.metrics.bundlesSubmitted.labels({ status: "failed" }).inc();
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
if (bundleResult.status === "bundle_success") {
|
|
164
|
+
const { userOpsBundled, rejectedUserOps, transactionRequest, transactionHash } = bundleResult;
|
|
165
|
+
const transactionInfo = {
|
|
166
|
+
executor: wallet,
|
|
167
|
+
transactionHash,
|
|
168
|
+
transactionRequest,
|
|
169
|
+
bundle: {
|
|
170
|
+
entryPoint,
|
|
171
|
+
version,
|
|
172
|
+
userOps: userOpsBundled
|
|
173
|
+
},
|
|
174
|
+
previousTransactionHashes: [],
|
|
175
|
+
lastReplaced: Date.now(),
|
|
176
|
+
firstSubmitted: Date.now(),
|
|
177
|
+
timesPotentiallyIncluded: 0
|
|
178
|
+
};
|
|
179
|
+
this.markUserOperationsAsSubmitted(userOpsBundled, transactionInfo);
|
|
180
|
+
this.dropUserOps(rejectedUserOps);
|
|
181
|
+
this.metrics.bundlesSubmitted.labels({ status: "success" }).inc();
|
|
182
|
+
return transactionHash;
|
|
183
|
+
}
|
|
184
|
+
return undefined;
|
|
214
185
|
}
|
|
215
186
|
startWatchingBlocks(handleBlock) {
|
|
216
187
|
if (this.unWatch) {
|
|
@@ -218,18 +189,6 @@ class ExecutorManager {
|
|
|
218
189
|
}
|
|
219
190
|
this.unWatch = this.config.publicClient.watchBlocks({
|
|
220
191
|
onBlock: handleBlock,
|
|
221
|
-
// onBlock: async (block) => {
|
|
222
|
-
// // Use an arrow function to ensure correct binding of `this`
|
|
223
|
-
// this.checkAndReplaceTransactions(block)
|
|
224
|
-
// .then(() => {
|
|
225
|
-
// this.logger.trace("block handled")
|
|
226
|
-
// // Handle the resolution of the promise here, if needed
|
|
227
|
-
// })
|
|
228
|
-
// .catch((error) => {
|
|
229
|
-
// // Handle any errors that occur during the execution of the promise
|
|
230
|
-
// this.logger.error({ error }, "error while handling block")
|
|
231
|
-
// })
|
|
232
|
-
// },
|
|
233
192
|
onError: (error) => {
|
|
234
193
|
this.logger.error({ error }, "error while watching blocks");
|
|
235
194
|
},
|
|
@@ -247,94 +206,71 @@ class ExecutorManager {
|
|
|
247
206
|
}
|
|
248
207
|
}
|
|
249
208
|
// update the current status of the bundling transaction/s
|
|
250
|
-
async refreshTransactionStatus(
|
|
251
|
-
const { transactionHash:
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
...previousTransactionHashes
|
|
255
|
-
];
|
|
209
|
+
async refreshTransactionStatus(transactionInfo) {
|
|
210
|
+
const { transactionHash: currentTxhash, bundle, previousTransactionHashes } = transactionInfo;
|
|
211
|
+
const { userOps, entryPoint } = bundle;
|
|
212
|
+
const txHashesToCheck = [currentTxhash, ...previousTransactionHashes];
|
|
256
213
|
const transactionDetails = await Promise.all(txHashesToCheck.map(async (transactionHash) => ({
|
|
257
214
|
transactionHash,
|
|
258
|
-
...(await (0, utils_1.getBundleStatus)(
|
|
215
|
+
...(await (0, utils_1.getBundleStatus)({
|
|
216
|
+
transactionHash,
|
|
217
|
+
bundle: transactionInfo.bundle,
|
|
218
|
+
publicClient: this.config.publicClient,
|
|
219
|
+
logger: this.logger
|
|
220
|
+
}))
|
|
259
221
|
})));
|
|
260
222
|
// first check if bundling txs returns status "mined", if not, check for reverted
|
|
261
223
|
const mined = transactionDetails.find(({ bundlingStatus }) => bundlingStatus.status === "included");
|
|
262
224
|
const reverted = transactionDetails.find(({ bundlingStatus }) => bundlingStatus.status === "reverted");
|
|
263
225
|
const finalizedTransaction = mined ?? reverted;
|
|
264
226
|
if (!finalizedTransaction) {
|
|
265
|
-
for (const { userOperationHash } of opInfos) {
|
|
266
|
-
this.logger.trace({
|
|
267
|
-
userOperationHash,
|
|
268
|
-
currentTransactionHash
|
|
269
|
-
}, "user op still pending");
|
|
270
|
-
}
|
|
271
227
|
return;
|
|
272
228
|
}
|
|
273
229
|
const { bundlingStatus, transactionHash, blockNumber } = finalizedTransaction;
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
.labels({ status: bundlingStatus.status })
|
|
277
|
-
.inc(opInfos.length);
|
|
278
|
-
const { userOperationDetails } = bundlingStatus;
|
|
279
|
-
opInfos.map((opInfo) => {
|
|
280
|
-
const { userOperation, userOperationHash, entryPoint, firstSubmitted } = opInfo;
|
|
281
|
-
const opDetails = userOperationDetails[userOperationHash];
|
|
282
|
-
this.metrics.userOperationInclusionDuration.observe((Date.now() - firstSubmitted) / 1000);
|
|
283
|
-
this.mempool.removeSubmitted(userOperationHash);
|
|
284
|
-
this.reputationManager.updateUserOperationIncludedStatus(userOperation, entryPoint, opDetails.accountDeployed);
|
|
285
|
-
if (opDetails.status === "succesful") {
|
|
286
|
-
this.eventManager.emitIncludedOnChain(userOperationHash, transactionHash, blockNumber);
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
this.eventManager.emitExecutionRevertedOnChain(userOperationHash, transactionHash, opDetails.revertReason || "0x", blockNumber);
|
|
290
|
-
}
|
|
291
|
-
this.monitor.setUserOperationStatus(userOperationHash, {
|
|
292
|
-
status: "included",
|
|
293
|
-
transactionHash
|
|
294
|
-
});
|
|
295
|
-
this.logger.info({
|
|
296
|
-
userOperationHash,
|
|
297
|
-
transactionHash
|
|
298
|
-
}, "user op included");
|
|
299
|
-
});
|
|
300
|
-
this.executor.markWalletProcessed(transactionInfo.executor);
|
|
301
|
-
}
|
|
302
|
-
else if (bundlingStatus.status === "reverted" &&
|
|
303
|
-
bundlingStatus.isAA95) {
|
|
230
|
+
// TODO: there has to be a better way of solving onchain AA95 errors.
|
|
231
|
+
if (bundlingStatus.status === "reverted" && bundlingStatus.isAA95) {
|
|
304
232
|
// resubmit with more gas when bundler encounters AA95
|
|
305
233
|
transactionInfo.transactionRequest.gas = (0, utils_1.scaleBigIntByPercent)(transactionInfo.transactionRequest.gas, this.config.aa95GasMultiplier);
|
|
306
234
|
transactionInfo.transactionRequest.nonce += 1;
|
|
307
235
|
await this.replaceTransaction(transactionInfo, "AA95");
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
// Free executor if tx landed onchain
|
|
239
|
+
if (bundlingStatus.status !== "not_found") {
|
|
240
|
+
this.senderManager.markWalletProcessed(transactionInfo.executor);
|
|
308
241
|
}
|
|
309
|
-
|
|
310
|
-
|
|
242
|
+
if (bundlingStatus.status === "included") {
|
|
243
|
+
const { userOperationDetails } = bundlingStatus;
|
|
244
|
+
this.markUserOpsIncluded(userOps, entryPoint, blockNumber, transactionHash, userOperationDetails);
|
|
245
|
+
}
|
|
246
|
+
if (bundlingStatus.status === "reverted") {
|
|
247
|
+
await Promise.all(userOps.map((userOpInfo) => {
|
|
248
|
+
const { userOpHash } = userOpInfo;
|
|
311
249
|
this.checkFrontrun({
|
|
312
|
-
|
|
250
|
+
userOpHash,
|
|
313
251
|
transactionHash,
|
|
314
252
|
blockNumber
|
|
315
253
|
});
|
|
316
254
|
}));
|
|
317
|
-
|
|
318
|
-
this.mempool.removeSubmitted(userOperationHash);
|
|
319
|
-
});
|
|
320
|
-
this.executor.markWalletProcessed(transactionInfo.executor);
|
|
255
|
+
this.removeSubmitted(userOps);
|
|
321
256
|
}
|
|
322
257
|
}
|
|
323
|
-
checkFrontrun({
|
|
258
|
+
checkFrontrun({ userOpHash, transactionHash, blockNumber }) {
|
|
324
259
|
const unwatch = this.config.publicClient.watchBlockNumber({
|
|
325
260
|
onBlockNumber: async (currentBlockNumber) => {
|
|
326
261
|
if (currentBlockNumber > blockNumber + 1n) {
|
|
327
|
-
const userOperationReceipt = await this.getUserOperationReceipt(
|
|
262
|
+
const userOperationReceipt = await this.getUserOperationReceipt(userOpHash);
|
|
328
263
|
if (userOperationReceipt) {
|
|
329
264
|
const transactionHash = userOperationReceipt.receipt.transactionHash;
|
|
330
265
|
const blockNumber = userOperationReceipt.receipt.blockNumber;
|
|
331
|
-
this.
|
|
266
|
+
this.mempool.removeSubmitted(userOpHash);
|
|
267
|
+
this.monitor.setUserOperationStatus(userOpHash, {
|
|
332
268
|
status: "included",
|
|
333
269
|
transactionHash
|
|
334
270
|
});
|
|
335
|
-
this.eventManager.emitFrontranOnChain(
|
|
271
|
+
this.eventManager.emitFrontranOnChain(userOpHash, transactionHash, blockNumber);
|
|
336
272
|
this.logger.info({
|
|
337
|
-
userOpHash
|
|
273
|
+
userOpHash,
|
|
338
274
|
transactionHash
|
|
339
275
|
}, "user op frontrun onchain");
|
|
340
276
|
this.metrics.userOperationsOnChain
|
|
@@ -342,13 +278,13 @@ class ExecutorManager {
|
|
|
342
278
|
.inc(1);
|
|
343
279
|
}
|
|
344
280
|
else {
|
|
345
|
-
this.monitor.setUserOperationStatus(
|
|
346
|
-
status: "
|
|
281
|
+
this.monitor.setUserOperationStatus(userOpHash, {
|
|
282
|
+
status: "failed",
|
|
347
283
|
transactionHash
|
|
348
284
|
});
|
|
349
|
-
this.eventManager.emitFailedOnChain(
|
|
285
|
+
this.eventManager.emitFailedOnChain(userOpHash, transactionHash, blockNumber);
|
|
350
286
|
this.logger.info({
|
|
351
|
-
userOpHash
|
|
287
|
+
userOpHash,
|
|
352
288
|
transactionHash
|
|
353
289
|
}, "user op failed onchain");
|
|
354
290
|
this.metrics.userOperationsOnChain
|
|
@@ -451,28 +387,6 @@ class ExecutorManager {
|
|
|
451
387
|
const userOperationReceipt = (0, utils_1.parseUserOperationReceipt)(userOperationHash, receipt);
|
|
452
388
|
return userOperationReceipt;
|
|
453
389
|
}
|
|
454
|
-
async refreshUserOperationStatuses() {
|
|
455
|
-
const ops = this.mempool.dumpSubmittedOps();
|
|
456
|
-
const opEntryPointMap = new Map();
|
|
457
|
-
for (const op of ops) {
|
|
458
|
-
if (!opEntryPointMap.has(op.userOperation.entryPoint)) {
|
|
459
|
-
opEntryPointMap.set(op.userOperation.entryPoint, []);
|
|
460
|
-
}
|
|
461
|
-
opEntryPointMap.get(op.userOperation.entryPoint)?.push(op);
|
|
462
|
-
}
|
|
463
|
-
await Promise.all(this.config.entrypoints.map(async (entryPoint) => {
|
|
464
|
-
const ops = opEntryPointMap.get(entryPoint);
|
|
465
|
-
if (ops) {
|
|
466
|
-
const txs = getTransactionsFromUserOperationEntries(ops);
|
|
467
|
-
await Promise.all(txs.map(async (txInfo) => {
|
|
468
|
-
await this.refreshTransactionStatus(entryPoint, txInfo);
|
|
469
|
-
}));
|
|
470
|
-
}
|
|
471
|
-
else {
|
|
472
|
-
this.logger.warn({ entryPoint }, "no user operations for entry point");
|
|
473
|
-
}
|
|
474
|
-
}));
|
|
475
|
-
}
|
|
476
390
|
async handleBlock(block) {
|
|
477
391
|
if (this.currentlyHandlingBlock) {
|
|
478
392
|
return;
|
|
@@ -486,102 +400,249 @@ class ExecutorManager {
|
|
|
486
400
|
return;
|
|
487
401
|
}
|
|
488
402
|
// refresh op statuses
|
|
489
|
-
|
|
403
|
+
const ops = this.mempool.dumpSubmittedOps();
|
|
404
|
+
const txs = getTransactionsFromUserOperationEntries(ops);
|
|
405
|
+
await Promise.all(txs.map((txInfo) => this.refreshTransactionStatus(txInfo)));
|
|
490
406
|
// for all still not included check if needs to be replaced (based on gas price)
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
gasPriceParameters = {
|
|
498
|
-
maxFeePerGas: 0n,
|
|
499
|
-
maxPriorityFeePerGas: 0n
|
|
500
|
-
};
|
|
501
|
-
}
|
|
502
|
-
this.logger.trace({ gasPriceParameters }, "fetched gas price parameters");
|
|
407
|
+
const gasPriceParameters = await this.gasPriceManager
|
|
408
|
+
.tryGetNetworkGasPrice()
|
|
409
|
+
.catch(() => ({
|
|
410
|
+
maxFeePerGas: 0n,
|
|
411
|
+
maxPriorityFeePerGas: 0n
|
|
412
|
+
}));
|
|
503
413
|
const transactionInfos = getTransactionsFromUserOperationEntries(this.mempool.dumpSubmittedOps());
|
|
504
414
|
await Promise.all(transactionInfos.map(async (txInfo) => {
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
415
|
+
const { transactionRequest } = txInfo;
|
|
416
|
+
const { maxFeePerGas, maxPriorityFeePerGas } = transactionRequest;
|
|
417
|
+
const isMaxFeeTooLow = maxFeePerGas < gasPriceParameters.maxFeePerGas;
|
|
418
|
+
const isPriorityFeeTooLow = maxPriorityFeePerGas <
|
|
419
|
+
gasPriceParameters.maxPriorityFeePerGas;
|
|
420
|
+
const isStuck = Date.now() - txInfo.lastReplaced >
|
|
421
|
+
this.config.resubmitStuckTimeout;
|
|
422
|
+
if (isMaxFeeTooLow || isPriorityFeeTooLow) {
|
|
423
|
+
await this.replaceTransaction(txInfo, "gas_price");
|
|
509
424
|
return;
|
|
510
425
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
// for any left check if enough time has passed, if so replace
|
|
514
|
-
const transactionInfos2 = getTransactionsFromUserOperationEntries(this.mempool.dumpSubmittedOps());
|
|
515
|
-
await Promise.all(transactionInfos2.map(async (txInfo) => {
|
|
516
|
-
if (Date.now() - txInfo.lastReplaced <
|
|
517
|
-
this.config.resubmitStuckTimeout) {
|
|
426
|
+
if (isStuck) {
|
|
427
|
+
await this.replaceTransaction(txInfo, "stuck");
|
|
518
428
|
return;
|
|
519
429
|
}
|
|
520
|
-
await this.replaceTransaction(txInfo, "stuck");
|
|
521
430
|
}));
|
|
522
431
|
this.currentlyHandlingBlock = false;
|
|
523
432
|
}
|
|
524
433
|
async replaceTransaction(txInfo, reason) {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}, "user operation rejected");
|
|
543
|
-
this.mempool.removeSubmitted(opInfo.userOperationHash);
|
|
434
|
+
// Setup vars
|
|
435
|
+
const { bundle, executor, transactionRequest, transactionHash: oldTxHash } = txInfo;
|
|
436
|
+
const { userOps } = bundle;
|
|
437
|
+
const gasPriceParameters = await this.gasPriceManager
|
|
438
|
+
.tryGetNetworkGasPrice()
|
|
439
|
+
.catch((_) => {
|
|
440
|
+
return undefined;
|
|
441
|
+
});
|
|
442
|
+
if (!gasPriceParameters) {
|
|
443
|
+
const rejectedUserOps = userOps.map((userOpInfo) => ({
|
|
444
|
+
...userOpInfo,
|
|
445
|
+
reason: "Failed to get network gas price during replacement"
|
|
446
|
+
}));
|
|
447
|
+
this.failedToReplaceTransaction({
|
|
448
|
+
rejectedUserOps,
|
|
449
|
+
oldTxHash,
|
|
450
|
+
reason: "Failed to get network gas price during replacement"
|
|
544
451
|
});
|
|
545
|
-
|
|
452
|
+
// Free executor if failed to get initial params.
|
|
453
|
+
this.senderManager.markWalletProcessed(txInfo.executor);
|
|
546
454
|
return;
|
|
547
455
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
456
|
+
const bundleResult = await this.executor.bundle({
|
|
457
|
+
executor: executor,
|
|
458
|
+
userOpBundle: bundle,
|
|
459
|
+
nonce: transactionRequest.nonce,
|
|
460
|
+
gasPriceParams: {
|
|
461
|
+
maxFeePerGas: (0, utils_1.scaleBigIntByPercent)(gasPriceParameters.maxFeePerGas, 115n),
|
|
462
|
+
maxPriorityFeePerGas: (0, utils_1.scaleBigIntByPercent)(gasPriceParameters.maxPriorityFeePerGas, 115n)
|
|
463
|
+
},
|
|
464
|
+
gasLimitSuggestion: transactionRequest.gas,
|
|
465
|
+
isReplacementTx: true
|
|
466
|
+
});
|
|
467
|
+
// Free wallet and return if potentially included too many times.
|
|
468
|
+
if (txInfo.timesPotentiallyIncluded >= 3) {
|
|
551
469
|
if (txInfo.timesPotentiallyIncluded >= 3) {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
470
|
+
this.removeSubmitted(bundle.userOps);
|
|
471
|
+
this.logger.warn({
|
|
472
|
+
oldTxHash,
|
|
473
|
+
userOps: (0, utils_2.getUserOpHashes)(bundleResult.rejectedUserOps)
|
|
474
|
+
}, "transaction potentially already included too many times, removing");
|
|
557
475
|
}
|
|
476
|
+
this.senderManager.markWalletProcessed(txInfo.executor);
|
|
558
477
|
return;
|
|
559
478
|
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
.
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
.
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
479
|
+
// Free wallet if no bundle was sent or potentially included.
|
|
480
|
+
if (bundleResult.status !== "bundle_success") {
|
|
481
|
+
this.senderManager.markWalletProcessed(txInfo.executor);
|
|
482
|
+
}
|
|
483
|
+
// Check if the transaction is potentially included.
|
|
484
|
+
const nonceTooLow = bundleResult.status === "bundle_submission_failure" &&
|
|
485
|
+
bundleResult.reason instanceof viem_1.NonceTooLowError;
|
|
486
|
+
const allOpsFailedSimulation = bundleResult.status === "all_ops_failed_simulation" &&
|
|
487
|
+
bundleResult.rejectedUserOps.every((op) => op.reason === "AA25 invalid account nonce" ||
|
|
488
|
+
op.reason === "AA10 sender already constructed");
|
|
489
|
+
const potentiallyIncluded = nonceTooLow || allOpsFailedSimulation;
|
|
490
|
+
// log metrics
|
|
491
|
+
const replaceStatus = (() => {
|
|
492
|
+
switch (true) {
|
|
493
|
+
case potentiallyIncluded:
|
|
494
|
+
return "potentially_already_included";
|
|
495
|
+
case bundleResult?.status === "bundle_success":
|
|
496
|
+
return "replaced";
|
|
497
|
+
default:
|
|
498
|
+
return "failed";
|
|
499
|
+
}
|
|
500
|
+
})();
|
|
501
|
+
this.metrics.replacedTransactions
|
|
502
|
+
.labels({ reason, status: replaceStatus })
|
|
503
|
+
.inc();
|
|
504
|
+
if (potentiallyIncluded) {
|
|
505
|
+
this.logger.info({
|
|
506
|
+
oldTxHash,
|
|
507
|
+
userOpHashes: (0, utils_2.getUserOpHashes)(bundleResult.rejectedUserOps)
|
|
508
|
+
}, "transaction potentially already included");
|
|
509
|
+
txInfo.timesPotentiallyIncluded += 1;
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (bundleResult.status === "unhandled_simulation_failure") {
|
|
513
|
+
const { rejectedUserOps, reason } = bundleResult;
|
|
514
|
+
this.failedToReplaceTransaction({
|
|
515
|
+
oldTxHash,
|
|
516
|
+
reason,
|
|
517
|
+
rejectedUserOps
|
|
518
|
+
});
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
if (bundleResult.status === "all_ops_failed_simulation") {
|
|
522
|
+
this.failedToReplaceTransaction({
|
|
523
|
+
oldTxHash,
|
|
524
|
+
reason: "all ops failed simulation",
|
|
525
|
+
rejectedUserOps: bundleResult.rejectedUserOps
|
|
526
|
+
});
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
if (bundleResult.status === "bundle_submission_failure") {
|
|
530
|
+
const { reason, rejectedUserOps } = bundleResult;
|
|
531
|
+
const submissionFailureReason = reason instanceof abitype_1.BaseError ? reason.name : "INTERNAL FAILURE";
|
|
532
|
+
this.failedToReplaceTransaction({
|
|
533
|
+
oldTxHash,
|
|
534
|
+
rejectedUserOps,
|
|
535
|
+
reason: submissionFailureReason
|
|
536
|
+
});
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const { rejectedUserOps, userOpsBundled, transactionRequest: newTransactionRequest, transactionHash: newTxHash } = bundleResult;
|
|
540
|
+
const userOpsReplaced = userOpsBundled;
|
|
541
|
+
const newTxInfo = {
|
|
542
|
+
...txInfo,
|
|
543
|
+
transactionRequest: newTransactionRequest,
|
|
544
|
+
transactionHash: newTxHash,
|
|
545
|
+
previousTransactionHashes: [
|
|
546
|
+
txInfo.transactionHash,
|
|
547
|
+
...txInfo.previousTransactionHashes
|
|
548
|
+
],
|
|
549
|
+
lastReplaced: Date.now(),
|
|
550
|
+
bundle: {
|
|
551
|
+
...txInfo.bundle,
|
|
552
|
+
userOps: userOpsReplaced
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
userOpsReplaced.map((userOp) => {
|
|
556
|
+
this.mempool.replaceSubmitted(userOp, newTxInfo);
|
|
577
557
|
});
|
|
558
|
+
// Drop all userOperations that were rejected during simulation.
|
|
559
|
+
this.dropUserOps(rejectedUserOps);
|
|
578
560
|
this.logger.info({
|
|
579
|
-
oldTxHash
|
|
580
|
-
newTxHash
|
|
561
|
+
oldTxHash,
|
|
562
|
+
newTxHash,
|
|
581
563
|
reason
|
|
582
564
|
}, "replaced transaction");
|
|
583
565
|
return;
|
|
584
566
|
}
|
|
567
|
+
markUserOperationsAsSubmitted(userOpInfos, transactionInfo) {
|
|
568
|
+
userOpInfos.map((userOpInfo) => {
|
|
569
|
+
const { userOpHash } = userOpInfo;
|
|
570
|
+
this.mempool.markSubmitted(userOpHash, transactionInfo);
|
|
571
|
+
this.startWatchingBlocks(this.handleBlock.bind(this));
|
|
572
|
+
this.metrics.userOperationsSubmitted
|
|
573
|
+
.labels({ status: "success" })
|
|
574
|
+
.inc();
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
resubmitUserOperations(userOps, entryPoint, reason) {
|
|
578
|
+
userOps.map((userOpInfo) => {
|
|
579
|
+
const { userOpHash, userOp } = userOpInfo;
|
|
580
|
+
this.logger.info({
|
|
581
|
+
userOpHash,
|
|
582
|
+
reason
|
|
583
|
+
}, "resubmitting user operation");
|
|
584
|
+
this.mempool.removeProcessing(userOpHash);
|
|
585
|
+
this.mempool.add(userOp, entryPoint);
|
|
586
|
+
this.metrics.userOperationsResubmitted.inc();
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
failedToReplaceTransaction({ oldTxHash, rejectedUserOps, reason }) {
|
|
590
|
+
this.logger.warn({ oldTxHash, reason }, "failed to replace transaction");
|
|
591
|
+
this.dropUserOps(rejectedUserOps);
|
|
592
|
+
}
|
|
593
|
+
removeSubmitted(userOps) {
|
|
594
|
+
userOps.map((userOpInfo) => {
|
|
595
|
+
const { userOpHash } = userOpInfo;
|
|
596
|
+
this.mempool.removeSubmitted(userOpHash);
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
markUserOpsIncluded(userOps, entryPoint, blockNumber, transactionHash, userOperationDetails) {
|
|
600
|
+
userOps.map((userOpInfo) => {
|
|
601
|
+
this.metrics.userOperationsOnChain
|
|
602
|
+
.labels({ status: "included" })
|
|
603
|
+
.inc();
|
|
604
|
+
const { userOpHash, userOp } = userOpInfo;
|
|
605
|
+
const opDetails = userOperationDetails[userOpHash];
|
|
606
|
+
const firstSubmitted = userOpInfo.addedToMempool;
|
|
607
|
+
this.metrics.userOperationInclusionDuration.observe((Date.now() - firstSubmitted) / 1000);
|
|
608
|
+
this.mempool.removeSubmitted(userOpHash);
|
|
609
|
+
this.reputationManager.updateUserOperationIncludedStatus(userOp, entryPoint, opDetails.accountDeployed);
|
|
610
|
+
if (opDetails.status === "succesful") {
|
|
611
|
+
this.eventManager.emitIncludedOnChain(userOpHash, transactionHash, blockNumber);
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
this.eventManager.emitExecutionRevertedOnChain(userOpHash, transactionHash, opDetails.revertReason || "0x", blockNumber);
|
|
615
|
+
}
|
|
616
|
+
this.monitor.setUserOperationStatus(userOpHash, {
|
|
617
|
+
status: "included",
|
|
618
|
+
transactionHash
|
|
619
|
+
});
|
|
620
|
+
this.logger.info({
|
|
621
|
+
opHash: userOpHash,
|
|
622
|
+
transactionHash
|
|
623
|
+
}, "user op included");
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
dropUserOps(rejectedUserOps) {
|
|
627
|
+
rejectedUserOps.map((rejectedUserOp) => {
|
|
628
|
+
const { userOp, reason, userOpHash } = rejectedUserOp;
|
|
629
|
+
this.mempool.removeProcessing(userOpHash);
|
|
630
|
+
this.mempool.removeSubmitted(userOpHash);
|
|
631
|
+
this.eventManager.emitDropped(userOpHash, reason, (0, utils_1.getAAError)(reason));
|
|
632
|
+
this.monitor.setUserOperationStatus(userOpHash, {
|
|
633
|
+
status: "rejected",
|
|
634
|
+
transactionHash: null
|
|
635
|
+
});
|
|
636
|
+
this.logger.warn({
|
|
637
|
+
userOperation: JSON.stringify(userOp, (_k, v) => typeof v === "bigint" ? v.toString() : v),
|
|
638
|
+
userOpHash,
|
|
639
|
+
reason
|
|
640
|
+
}, "user operation rejected");
|
|
641
|
+
this.metrics.userOperationsSubmitted
|
|
642
|
+
.labels({ status: "failed" })
|
|
643
|
+
.inc();
|
|
644
|
+
});
|
|
645
|
+
}
|
|
585
646
|
}
|
|
586
647
|
exports.ExecutorManager = ExecutorManager;
|
|
587
648
|
//# sourceMappingURL=executorManager.js.map
|