@pimlico/alto 0.0.0-main.20250916T162729 → 0.0.0-main.20251001T162733
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 +12 -0
- package/esm/cli/config/bundler.js +2 -0
- package/esm/cli/config/bundler.js.map +1 -1
- package/esm/cli/config/options.js +11 -0
- package/esm/cli/config/options.js.map +1 -1
- package/esm/cli/setupServer.js +1 -1
- package/esm/cli/setupServer.js.map +1 -1
- package/esm/cli/shutDown.js +15 -55
- package/esm/cli/shutDown.js.map +1 -1
- package/esm/executor/bundleManager.d.ts +1 -1
- package/esm/executor/bundleManager.js +47 -34
- package/esm/executor/bundleManager.js.map +1 -1
- package/esm/executor/executorManager.js +3 -4
- package/esm/executor/executorManager.js.map +1 -1
- package/esm/executor/senderManager/createRedisSenderManager.js +1 -2
- package/esm/executor/senderManager/createRedisSenderManager.js.map +1 -1
- package/esm/handlers/arbitrumGasPriceManager.js +2 -2
- package/esm/handlers/gasPriceManager.js +3 -3
- package/esm/handlers/mantleGasPriceManager.js +4 -4
- package/esm/handlers/optimismManager.js +1 -1
- package/esm/mempool/mempool.d.ts +3 -11
- package/esm/mempool/mempool.js +93 -96
- package/esm/mempool/mempool.js.map +1 -1
- package/esm/mempool/monitoring.d.ts +1 -1
- package/esm/mempool/monitoring.js +30 -21
- package/esm/mempool/monitoring.js.map +1 -1
- package/esm/receiptCache/createMemoryReceiptCache.js +8 -5
- package/esm/receiptCache/createMemoryReceiptCache.js.map +1 -1
- package/esm/receiptCache/createRedisReceiptCache.js +13 -11
- package/esm/receiptCache/createRedisReceiptCache.js.map +1 -1
- package/esm/receiptCache/index.d.ts +4 -1
- package/esm/receiptCache/index.js.map +1 -1
- package/esm/rpc/methods/eth_sendUserOperation.js +6 -7
- package/esm/rpc/methods/eth_sendUserOperation.js.map +1 -1
- package/esm/rpc/methods/pimlico_sendUserOperationNow.js +8 -11
- package/esm/rpc/methods/pimlico_sendUserOperationNow.js.map +1 -1
- package/esm/store/createMempoolStore.d.ts +1 -1
- package/esm/store/createMempoolStore.js +51 -143
- package/esm/store/createMempoolStore.js.map +1 -1
- package/esm/store/index.d.ts +4 -75
- package/esm/store/index.js +4 -1
- package/esm/store/index.js.map +1 -1
- package/esm/store/outstanding/index.d.ts +13 -0
- package/esm/store/outstanding/index.js +16 -0
- package/esm/store/outstanding/index.js.map +1 -0
- package/esm/store/{createMemoryOutstandingStore.d.ts → outstanding/memory.d.ts} +11 -10
- package/esm/store/outstanding/memory.js +249 -0
- package/esm/store/outstanding/memory.js.map +1 -0
- package/esm/store/outstanding/redis.d.ts +11 -0
- package/esm/store/outstanding/redis.js +201 -0
- package/esm/store/outstanding/redis.js.map +1 -0
- package/esm/store/outstanding/types.d.ts +18 -0
- package/esm/store/outstanding/types.js +2 -0
- package/esm/store/outstanding/types.js.map +1 -0
- package/esm/store/processing/index.d.ts +11 -0
- package/esm/store/processing/index.js +17 -0
- package/esm/store/processing/index.js.map +1 -0
- package/esm/store/processing/memory.d.ts +14 -0
- package/esm/store/processing/memory.js +46 -0
- package/esm/store/processing/memory.js.map +1 -0
- package/esm/store/processing/redis.d.ts +21 -0
- package/esm/store/processing/redis.js +69 -0
- package/esm/store/processing/redis.js.map +1 -0
- package/esm/store/processing/types.d.ts +9 -0
- package/esm/store/processing/types.js +2 -0
- package/esm/store/processing/types.js.map +1 -0
- package/esm/store/types.d.ts +49 -0
- package/esm/store/types.js +2 -0
- package/esm/store/types.js.map +1 -0
- package/esm/utils/helpers.d.ts +0 -1
- package/esm/utils/helpers.js +1 -8
- package/esm/utils/helpers.js.map +1 -1
- package/esm/utils/minMaxQueue/createRedisMinMaxQueue.d.ts +23 -2
- package/esm/utils/minMaxQueue/createRedisMinMaxQueue.js +83 -60
- package/esm/utils/minMaxQueue/createRedisMinMaxQueue.js.map +1 -1
- package/esm/utils/minMaxQueue/index.d.ts +2 -2
- package/esm/utils/minMaxQueue/index.js +2 -2
- package/esm/utils/minMaxQueue/index.js.map +1 -1
- package/esm/utils/preVerificationGasCalulator.d.ts +0 -2
- package/esm/utils/preVerificationGasCalulator.js +2 -2
- package/esm/utils/preVerificationGasCalulator.js.map +1 -1
- package/esm/utils/userop.d.ts +4 -50
- package/esm/utils/userop.js +61 -196
- package/esm/utils/userop.js.map +1 -1
- package/package.json +1 -1
- package/esm/cli/config/redisKeys.d.ts +0 -9
- package/esm/cli/config/redisKeys.js +0 -16
- package/esm/cli/config/redisKeys.js.map +0 -1
- package/esm/store/createMemoryOutstandingStore.js +0 -240
- package/esm/store/createMemoryOutstandingStore.js.map +0 -1
- package/esm/store/createRedisOutstandingStore.d.ts +0 -28
- package/esm/store/createRedisOutstandingStore.js +0 -341
- package/esm/store/createRedisOutstandingStore.js.map +0 -1
- package/esm/store/createRedisStore.d.ts +0 -10
- package/esm/store/createRedisStore.js +0 -128
- package/esm/store/createRedisStore.js.map +0 -1
- package/esm/store/createStore.d.ts +0 -6
- package/esm/store/createStore.js +0 -66
- package/esm/store/createStore.js.map +0 -1
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { getNonceKeyAndSequence, isDeployment, isVersion07 } from "../../utils/userop.js";
|
|
2
|
+
const senderNonceSlot = (userOp) => {
|
|
3
|
+
const sender = userOp.sender;
|
|
4
|
+
const [nonceKey] = getNonceKeyAndSequence(userOp.nonce);
|
|
5
|
+
return `${sender}-${nonceKey}`;
|
|
6
|
+
};
|
|
7
|
+
export class MemoryOutstanding {
|
|
8
|
+
config;
|
|
9
|
+
pendingOps = new Map();
|
|
10
|
+
priorityQueue = [];
|
|
11
|
+
hashLookup = new Map();
|
|
12
|
+
logger;
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.config = config;
|
|
15
|
+
// Setup args for getting userOpHash
|
|
16
|
+
this.logger = config.getLogger({ module: "memory-outstanding-queue" }, {
|
|
17
|
+
level: config.logLevel
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
dump() {
|
|
21
|
+
return [...Array.from(this.pendingOps.values()).flat()];
|
|
22
|
+
}
|
|
23
|
+
// Adds userOp to queue and maintains sorting by gas price.
|
|
24
|
+
addToPriorityQueue(userOpInfo) {
|
|
25
|
+
this.priorityQueue.push(userOpInfo);
|
|
26
|
+
this.priorityQueue.sort((a, b) => {
|
|
27
|
+
const userOpA = a.userOp;
|
|
28
|
+
const userOpB = b.userOp;
|
|
29
|
+
return Number(userOpA.maxFeePerGas - userOpB.maxFeePerGas);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
validateQueuedLimit(userOp) {
|
|
33
|
+
const outstandingOps = this.dump();
|
|
34
|
+
const parallelUserOpsCount = outstandingOps.filter((userOpInfo) => {
|
|
35
|
+
const { userOp: mempoolUserOp } = userOpInfo;
|
|
36
|
+
return mempoolUserOp.sender === userOp.sender;
|
|
37
|
+
}).length;
|
|
38
|
+
if (parallelUserOpsCount > this.config.mempoolMaxParallelOps) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
validateParallelLimit(userOp) {
|
|
44
|
+
const outstandingOps = this.dump();
|
|
45
|
+
const [nonceKey] = getNonceKeyAndSequence(userOp.nonce);
|
|
46
|
+
const queuedUserOpsCount = outstandingOps.filter((userOpInfo) => {
|
|
47
|
+
const { userOp: mempoolUserOp } = userOpInfo;
|
|
48
|
+
const [opNonceKey] = getNonceKeyAndSequence(mempoolUserOp.nonce);
|
|
49
|
+
return (mempoolUserOp.sender === userOp.sender &&
|
|
50
|
+
opNonceKey === nonceKey);
|
|
51
|
+
}).length;
|
|
52
|
+
if (queuedUserOpsCount > this.config.mempoolMaxQueuedOps) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
async popConflicting(userOp) {
|
|
58
|
+
const outstandingOps = this.dump();
|
|
59
|
+
let conflictingReason;
|
|
60
|
+
for (const userOpInfo of outstandingOps) {
|
|
61
|
+
const { userOp: mempoolUserOp } = userOpInfo;
|
|
62
|
+
const isSameSender = mempoolUserOp.sender === userOp.sender;
|
|
63
|
+
if (isSameSender && mempoolUserOp.nonce === userOp.nonce) {
|
|
64
|
+
const removed = await this.remove([userOpInfo.userOpHash]);
|
|
65
|
+
if (removed.length > 0) {
|
|
66
|
+
conflictingReason = {
|
|
67
|
+
reason: "conflicting_nonce",
|
|
68
|
+
userOpInfo: removed[0]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
const isConflictingDeployment = isSameSender &&
|
|
74
|
+
isDeployment(userOp) &&
|
|
75
|
+
isDeployment(mempoolUserOp);
|
|
76
|
+
if (isConflictingDeployment) {
|
|
77
|
+
const removed = await this.remove([userOpInfo.userOpHash]);
|
|
78
|
+
if (removed.length > 0) {
|
|
79
|
+
conflictingReason = {
|
|
80
|
+
reason: "conflicting_deployment",
|
|
81
|
+
userOpInfo: removed[0]
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return conflictingReason;
|
|
88
|
+
}
|
|
89
|
+
async contains(userOpHash) {
|
|
90
|
+
return this.hashLookup.has(userOpHash);
|
|
91
|
+
}
|
|
92
|
+
pop(count) {
|
|
93
|
+
const results = [];
|
|
94
|
+
for (let i = 0; i < count; i++) {
|
|
95
|
+
const userOpInfo = this.priorityQueue.shift();
|
|
96
|
+
if (!userOpInfo) {
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
const pendingOpsSlot = senderNonceSlot(userOpInfo.userOp);
|
|
100
|
+
const backlogOps = this.pendingOps.get(pendingOpsSlot);
|
|
101
|
+
// This should never throw.
|
|
102
|
+
if (!backlogOps?.shift()) {
|
|
103
|
+
throw new Error("FATAL: No pending userOps for sender");
|
|
104
|
+
}
|
|
105
|
+
// Move next pending userOp into priorityQueue if exist.
|
|
106
|
+
if (backlogOps.length > 0) {
|
|
107
|
+
this.addToPriorityQueue(backlogOps[0]);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Cleanup if no more ops for this slot
|
|
111
|
+
this.pendingOps.delete(pendingOpsSlot);
|
|
112
|
+
}
|
|
113
|
+
// Remove from hash lookup
|
|
114
|
+
this.hashLookup.delete(userOpInfo.userOpHash);
|
|
115
|
+
results.push(userOpInfo);
|
|
116
|
+
}
|
|
117
|
+
return Promise.resolve(results);
|
|
118
|
+
}
|
|
119
|
+
async add(userOpInfos) {
|
|
120
|
+
if (userOpInfos.length === 0)
|
|
121
|
+
return;
|
|
122
|
+
for (const userOpInfo of userOpInfos) {
|
|
123
|
+
const { userOp, userOpHash } = userOpInfo;
|
|
124
|
+
const [nonceKey] = getNonceKeyAndSequence(userOp.nonce);
|
|
125
|
+
const pendingOpsSlot = senderNonceSlot(userOp);
|
|
126
|
+
const backlogOps = (() => {
|
|
127
|
+
if (this.pendingOps.has(pendingOpsSlot)) {
|
|
128
|
+
return this.pendingOps.get(pendingOpsSlot);
|
|
129
|
+
}
|
|
130
|
+
this.pendingOps.set(pendingOpsSlot, []);
|
|
131
|
+
return this.pendingOps.get(pendingOpsSlot);
|
|
132
|
+
})();
|
|
133
|
+
if (!backlogOps) {
|
|
134
|
+
throw new Error("FATAL: No pending operations found for userOpHash");
|
|
135
|
+
}
|
|
136
|
+
// Note: the userOpInfo is always added to backlogOps, because we are pushing to a reference
|
|
137
|
+
backlogOps.push(userOpInfo);
|
|
138
|
+
// Add to hash lookup for O(1) contains checks
|
|
139
|
+
this.hashLookup.set(userOpHash, userOpInfo);
|
|
140
|
+
// Sort backlogOps by nonce sequence
|
|
141
|
+
backlogOps.sort((a, b) => {
|
|
142
|
+
const [, aNonceSeq] = getNonceKeyAndSequence(a.userOp.nonce);
|
|
143
|
+
const [, bNonceSeq] = getNonceKeyAndSequence(b.userOp.nonce);
|
|
144
|
+
return Number(aNonceSeq - bNonceSeq);
|
|
145
|
+
});
|
|
146
|
+
const lowestUserOpHash = backlogOps[0].userOpHash;
|
|
147
|
+
// If lowest, remove any existing userOp with same sender and nonceKey and add current userOp to priorityQueue.
|
|
148
|
+
if (lowestUserOpHash === userOpHash) {
|
|
149
|
+
this.priorityQueue = this.priorityQueue.filter((userOpInfo) => {
|
|
150
|
+
const pendingUserOp = userOpInfo.userOp;
|
|
151
|
+
const isSameSender = pendingUserOp.sender === userOp.sender;
|
|
152
|
+
const isSameNonceKey = getNonceKeyAndSequence(pendingUserOp.nonce)[0] ===
|
|
153
|
+
nonceKey;
|
|
154
|
+
return !(isSameSender && isSameNonceKey);
|
|
155
|
+
});
|
|
156
|
+
this.addToPriorityQueue(userOpInfo);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async getQueuedUserOps(userOp) {
|
|
161
|
+
const [nonceKey, nonceSequence] = getNonceKeyAndSequence(userOp.nonce);
|
|
162
|
+
const outstandingOps = this.dump();
|
|
163
|
+
const outstanding = outstandingOps.filter((userOpInfo) => {
|
|
164
|
+
const { userOp: mempoolUserOp } = userOpInfo;
|
|
165
|
+
const [mempoolNonceKey, mempoolNonceSequence] = getNonceKeyAndSequence(mempoolUserOp.nonce);
|
|
166
|
+
let isPaymasterSame = false;
|
|
167
|
+
if (isVersion07(userOp) && isVersion07(mempoolUserOp)) {
|
|
168
|
+
isPaymasterSame =
|
|
169
|
+
mempoolUserOp.paymaster === userOp.paymaster &&
|
|
170
|
+
!(mempoolUserOp.sender === userOp.sender &&
|
|
171
|
+
mempoolNonceKey === nonceKey &&
|
|
172
|
+
mempoolNonceSequence === nonceSequence) &&
|
|
173
|
+
userOp.paymaster !== null;
|
|
174
|
+
}
|
|
175
|
+
// Filter operations with the same sender and nonce key
|
|
176
|
+
// but with a lower nonce sequence
|
|
177
|
+
return ((mempoolUserOp.sender === userOp.sender &&
|
|
178
|
+
mempoolNonceKey === nonceKey &&
|
|
179
|
+
mempoolNonceSequence < nonceSequence) ||
|
|
180
|
+
isPaymasterSame);
|
|
181
|
+
});
|
|
182
|
+
return outstanding
|
|
183
|
+
.sort((a, b) => {
|
|
184
|
+
const aUserOp = a.userOp;
|
|
185
|
+
const bUserOp = b.userOp;
|
|
186
|
+
const [, aNonceValue] = getNonceKeyAndSequence(aUserOp.nonce);
|
|
187
|
+
const [, bNonceValue] = getNonceKeyAndSequence(bUserOp.nonce);
|
|
188
|
+
return Number(aNonceValue - bNonceValue);
|
|
189
|
+
})
|
|
190
|
+
.map((userOpInfo) => userOpInfo.userOp);
|
|
191
|
+
}
|
|
192
|
+
async remove(userOpHashes) {
|
|
193
|
+
if (userOpHashes.length === 0) {
|
|
194
|
+
return [];
|
|
195
|
+
}
|
|
196
|
+
const removedOps = [];
|
|
197
|
+
for (const userOpHash of userOpHashes) {
|
|
198
|
+
// Look up userOp in hash lookup first
|
|
199
|
+
const userOpInfo = this.hashLookup.get(userOpHash);
|
|
200
|
+
if (!userOpInfo) {
|
|
201
|
+
this.logger.info(`tried to remove non-existent user op from mempool: ${userOpHash}`);
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const pendingOpsSlot = senderNonceSlot(userOpInfo.userOp);
|
|
205
|
+
// Find and remove from pending ops
|
|
206
|
+
const backlogOps = this.pendingOps.get(pendingOpsSlot);
|
|
207
|
+
if (!backlogOps) {
|
|
208
|
+
throw new Error(`FATAL: No pending operations found for userOpHash ${userOpHash}`);
|
|
209
|
+
}
|
|
210
|
+
const backlogIndex = backlogOps.findIndex((info) => info.userOpHash === userOpHash);
|
|
211
|
+
if (backlogIndex === -1) {
|
|
212
|
+
throw new Error(`FATAL: UserOp with hash ${userOpHash} not found in backlog`);
|
|
213
|
+
}
|
|
214
|
+
backlogOps.splice(backlogIndex, 1);
|
|
215
|
+
// Remove from priority queue if present
|
|
216
|
+
const priorityQueueIndex = this.priorityQueue.findIndex((info) => info.userOpHash === userOpHash);
|
|
217
|
+
if (priorityQueueIndex !== -1) {
|
|
218
|
+
this.priorityQueue.splice(priorityQueueIndex, 1);
|
|
219
|
+
}
|
|
220
|
+
// Remove from hash lookup
|
|
221
|
+
this.hashLookup.delete(userOpHash);
|
|
222
|
+
// If this was the first operation and there are more in the backlog,
|
|
223
|
+
// add the new first operation to the priority queue
|
|
224
|
+
if (backlogIndex === 0 && backlogOps.length > 0) {
|
|
225
|
+
this.addToPriorityQueue(backlogOps[0]);
|
|
226
|
+
}
|
|
227
|
+
// Clean up empty slot
|
|
228
|
+
if (backlogOps.length === 0) {
|
|
229
|
+
this.pendingOps.delete(pendingOpsSlot);
|
|
230
|
+
}
|
|
231
|
+
removedOps.push(userOpInfo);
|
|
232
|
+
}
|
|
233
|
+
return removedOps;
|
|
234
|
+
}
|
|
235
|
+
dumpLocal() {
|
|
236
|
+
return Promise.resolve(this.dump());
|
|
237
|
+
}
|
|
238
|
+
clear() {
|
|
239
|
+
this.priorityQueue = [];
|
|
240
|
+
this.pendingOps.clear();
|
|
241
|
+
this.hashLookup.clear();
|
|
242
|
+
return Promise.resolve();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
export const createMemoryOutstandingQueue = ({ config, logger }) => {
|
|
246
|
+
logger.info("Using memory for outstanding mempool");
|
|
247
|
+
return new MemoryOutstanding(config);
|
|
248
|
+
};
|
|
249
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../store/outstanding/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Address } from "../../types/index.js";
|
|
2
|
+
import type { Logger } from "pino";
|
|
3
|
+
import type { AltoConfig } from "../../createConfig.js";
|
|
4
|
+
import type { OutstandingStore } from "./types.js";
|
|
5
|
+
export declare const createRedisOutstandingQueue: ({ config, entryPoint, redisEndpoint, logger }: {
|
|
6
|
+
config: AltoConfig;
|
|
7
|
+
entryPoint: Address;
|
|
8
|
+
redisEndpoint: string;
|
|
9
|
+
logger: Logger;
|
|
10
|
+
}) => OutstandingStore;
|
|
11
|
+
//# sourceMappingURL=redis.d.ts.map
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { userOpInfoSchema } from "../../types/index.js";
|
|
2
|
+
import { getNonceKeyAndSequence, isDeployment } from "../../utils/index.js";
|
|
3
|
+
import { Redis } from "ioredis";
|
|
4
|
+
import { toHex } from "viem/utils";
|
|
5
|
+
const serialize = (userOpInfo) => {
|
|
6
|
+
return JSON.stringify(userOpInfo, (_, value) => typeof value === "bigint" ? toHex(value) : value);
|
|
7
|
+
};
|
|
8
|
+
const deserialize = (data) => {
|
|
9
|
+
const parsed = JSON.parse(data);
|
|
10
|
+
return userOpInfoSchema.parse(parsed);
|
|
11
|
+
};
|
|
12
|
+
class RedisOutstandingQueue {
|
|
13
|
+
redis;
|
|
14
|
+
senderNonceKeyPrefix; // sender + nonceKey -> userOpHash
|
|
15
|
+
readyQueue; // Queue of userOpHashes (sorted by composite of userOp.nonceSeq + userOp.maxFeePerGas)
|
|
16
|
+
userOpHashMap; // userOpHash -> boolean
|
|
17
|
+
deploymentHashMap; // sender -> deployment userOpHash
|
|
18
|
+
senderNonceQueueTtl; // TTL for sender nonce queues in seconds
|
|
19
|
+
constructor({ config, entryPoint, redisEndpoint, logger }) {
|
|
20
|
+
this.redis = new Redis(redisEndpoint, {});
|
|
21
|
+
// Initialize Redis key names
|
|
22
|
+
const redisPrefix = `${config.redisKeyPrefix}:${config.chainId}:${entryPoint}:outstanding`;
|
|
23
|
+
this.readyQueue = `${redisPrefix}:ready-queue`;
|
|
24
|
+
this.senderNonceKeyPrefix = `${redisPrefix}:sender`;
|
|
25
|
+
this.userOpHashMap = `${redisPrefix}:userop-hash`;
|
|
26
|
+
this.deploymentHashMap = `${redisPrefix}:deployment-senders`;
|
|
27
|
+
// Calculate TTL for sender nonce queues (10 blocks worth of time)
|
|
28
|
+
this.senderNonceQueueTtl = config.blockTime * 10;
|
|
29
|
+
logger.info({
|
|
30
|
+
readyQueueKey: this.readyQueue
|
|
31
|
+
}, "Using redis for outstanding mempool.");
|
|
32
|
+
}
|
|
33
|
+
// Returns queue index for this sender + nonceKey.
|
|
34
|
+
getSenderNonceQueue(userOp) {
|
|
35
|
+
const [nonceKey] = getNonceKeyAndSequence(userOp.nonce);
|
|
36
|
+
return `${this.senderNonceKeyPrefix}:${userOp.sender}:${nonceKey}`;
|
|
37
|
+
}
|
|
38
|
+
// OutstandingStore methods
|
|
39
|
+
async contains(userOpHash) {
|
|
40
|
+
const exists = await this.redis.hexists(this.userOpHashMap, userOpHash);
|
|
41
|
+
return exists === 1;
|
|
42
|
+
}
|
|
43
|
+
async popConflicting(userOp) {
|
|
44
|
+
const { sender, nonce } = userOp;
|
|
45
|
+
const [nonceSeq] = getNonceKeyAndSequence(nonce);
|
|
46
|
+
// Check for conflicting nonce.
|
|
47
|
+
const senderNonceQueue = this.getSenderNonceQueue(userOp);
|
|
48
|
+
const conflictingHashes = await this.redis.zrangebyscore(senderNonceQueue, Number(nonceSeq), Number(nonceSeq));
|
|
49
|
+
if (conflictingHashes.length > 0) {
|
|
50
|
+
const conflictingHash = conflictingHashes[0];
|
|
51
|
+
const removedUserOps = await this.remove([conflictingHash]);
|
|
52
|
+
if (removedUserOps.length > 0) {
|
|
53
|
+
return {
|
|
54
|
+
reason: "conflicting_nonce",
|
|
55
|
+
userOpInfo: removedUserOps[0]
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Check for conflicting deployment.
|
|
60
|
+
if (isDeployment(userOp)) {
|
|
61
|
+
const existingDeploymentHash = (await this.redis.hget(this.deploymentHashMap, sender));
|
|
62
|
+
if (existingDeploymentHash) {
|
|
63
|
+
const removedUserOps = await this.remove([
|
|
64
|
+
existingDeploymentHash
|
|
65
|
+
]);
|
|
66
|
+
if (removedUserOps.length > 0) {
|
|
67
|
+
return {
|
|
68
|
+
reason: "conflicting_deployment",
|
|
69
|
+
userOpInfo: removedUserOps[0]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
async add(userOpInfos) {
|
|
77
|
+
if (userOpInfos.length === 0)
|
|
78
|
+
return;
|
|
79
|
+
// Use pipeline for atomic operations
|
|
80
|
+
const pipeline = this.redis.pipeline();
|
|
81
|
+
for (const userOpInfo of userOpInfos) {
|
|
82
|
+
const { userOp } = userOpInfo;
|
|
83
|
+
const [, nonceSequence] = getNonceKeyAndSequence(userOp.nonce);
|
|
84
|
+
const userOpHash = userOpInfo.userOpHash;
|
|
85
|
+
// Create composite score: nonceSequence in upper 32 bits, maxFeePerGas in lower 32 bits.
|
|
86
|
+
const score = (nonceSequence << 32n) | (userOp.maxFeePerGas & 0xffffffffn);
|
|
87
|
+
// Serialize userOpInfo for storage.
|
|
88
|
+
const serializedUserOp = serialize(userOpInfo);
|
|
89
|
+
// Add to main ready queue.
|
|
90
|
+
pipeline.zadd(this.readyQueue, Number(score), userOpHash);
|
|
91
|
+
// Add to sender+nonceKey index for fast lookup.
|
|
92
|
+
const senderNonceQueue = this.getSenderNonceQueue(userOp);
|
|
93
|
+
pipeline.zadd(senderNonceQueue, Number(nonceSequence), userOpHash);
|
|
94
|
+
pipeline.expire(senderNonceQueue, this.senderNonceQueueTtl);
|
|
95
|
+
// Add to userOpHash map.
|
|
96
|
+
pipeline.hset(this.userOpHashMap, userOpHash, serializedUserOp);
|
|
97
|
+
// Add sender to deployment hash if this is a deployment.
|
|
98
|
+
if (isDeployment(userOp)) {
|
|
99
|
+
pipeline.hset(this.deploymentHashMap, userOp.sender, userOpHash);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
await pipeline.exec();
|
|
103
|
+
}
|
|
104
|
+
// Removes userOps given their hashes and returns the userOpInfo objects.
|
|
105
|
+
async remove(userOpHashes) {
|
|
106
|
+
if (userOpHashes.length === 0)
|
|
107
|
+
return [];
|
|
108
|
+
// Get all serialized data in parallel.
|
|
109
|
+
const pipeline = this.redis.pipeline();
|
|
110
|
+
for (const hash of userOpHashes) {
|
|
111
|
+
pipeline.hget(this.userOpHashMap, hash);
|
|
112
|
+
}
|
|
113
|
+
const serializedResults = await pipeline.exec();
|
|
114
|
+
const removedUserOps = [];
|
|
115
|
+
const removalPipeline = this.redis.pipeline();
|
|
116
|
+
// Process each userOp that exists.
|
|
117
|
+
for (let i = 0; i < userOpHashes.length; i++) {
|
|
118
|
+
const serialized = serializedResults?.[i]?.[1];
|
|
119
|
+
if (!serialized)
|
|
120
|
+
continue;
|
|
121
|
+
const userOpHash = userOpHashes[i];
|
|
122
|
+
const userOpInfo = deserialize(serialized);
|
|
123
|
+
const { userOp } = userOpInfo;
|
|
124
|
+
const [, nonceSequence] = getNonceKeyAndSequence(userOp.nonce);
|
|
125
|
+
const senderNonceQueue = this.getSenderNonceQueue(userOp);
|
|
126
|
+
const isDeploymentOp = isDeployment(userOp);
|
|
127
|
+
// Remove from ready queue.
|
|
128
|
+
removalPipeline.zrem(this.readyQueue, userOpHash);
|
|
129
|
+
// Remove from sender nonceKey queue.
|
|
130
|
+
removalPipeline.zremrangebyscore(senderNonceQueue, Number(nonceSequence), Number(nonceSequence));
|
|
131
|
+
// Remove from hash lookup.
|
|
132
|
+
removalPipeline.hdel(this.userOpHashMap, userOpHash);
|
|
133
|
+
// Remove sender from deployment hash if this was a deployment.
|
|
134
|
+
if (isDeploymentOp) {
|
|
135
|
+
removalPipeline.hdel(this.deploymentHashMap, userOp.sender);
|
|
136
|
+
}
|
|
137
|
+
removedUserOps.push(userOpInfo);
|
|
138
|
+
}
|
|
139
|
+
// Execute all removals.
|
|
140
|
+
await removalPipeline.exec();
|
|
141
|
+
return removedUserOps;
|
|
142
|
+
}
|
|
143
|
+
async pop(count) {
|
|
144
|
+
// Pop from ready queue
|
|
145
|
+
const results = await this.redis.zpopmax(this.readyQueue, count);
|
|
146
|
+
if (!results || results.length === 0) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
// Extract hashes from results (zpopmax returns [member, score, member, score, ...])
|
|
150
|
+
const userOpHashes = [];
|
|
151
|
+
for (let i = 0; i < results.length; i += 2) {
|
|
152
|
+
userOpHashes.push(results[i]);
|
|
153
|
+
}
|
|
154
|
+
// Remove all userOps in batch
|
|
155
|
+
return await this.remove(userOpHashes);
|
|
156
|
+
}
|
|
157
|
+
async getQueuedUserOps(userOp) {
|
|
158
|
+
const [, nonceSequence] = getNonceKeyAndSequence(userOp.nonce);
|
|
159
|
+
const senderNonceQueue = this.getSenderNonceQueue(userOp);
|
|
160
|
+
// Get all userOpHashes with nonce sequence lower than the input
|
|
161
|
+
// ZRANGEBYSCORE returns elements with scores between min and max
|
|
162
|
+
// We want scores from 0 to (nonceSequence - 1)
|
|
163
|
+
const userOpHashes = await this.redis.zrangebyscore(senderNonceQueue, 0, Number(nonceSequence) - 1);
|
|
164
|
+
if (userOpHashes.length === 0)
|
|
165
|
+
return [];
|
|
166
|
+
// Fetch serialized data for each hash
|
|
167
|
+
const pipeline = this.redis.pipeline();
|
|
168
|
+
for (const hash of userOpHashes) {
|
|
169
|
+
pipeline.hget(this.userOpHashMap, hash);
|
|
170
|
+
}
|
|
171
|
+
const results = await pipeline.exec();
|
|
172
|
+
// Deserialize and extract userOps
|
|
173
|
+
return (results || [])
|
|
174
|
+
.map((result) => result?.[1])
|
|
175
|
+
.filter((serialized) => serialized !== null)
|
|
176
|
+
.map((serialized) => deserialize(serialized).userOp);
|
|
177
|
+
}
|
|
178
|
+
// These methods aren't implemented
|
|
179
|
+
dumpLocal() {
|
|
180
|
+
return Promise.resolve([]); // We can't dump from redis as the latency is too high
|
|
181
|
+
}
|
|
182
|
+
clear() {
|
|
183
|
+
throw new Error("Not implemented: clear");
|
|
184
|
+
}
|
|
185
|
+
// Skip limit checks when using Redis
|
|
186
|
+
validateQueuedLimit() {
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
validateParallelLimit() {
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
export const createRedisOutstandingQueue = ({ config, entryPoint, redisEndpoint, logger }) => {
|
|
194
|
+
return new RedisOutstandingQueue({
|
|
195
|
+
config,
|
|
196
|
+
entryPoint,
|
|
197
|
+
redisEndpoint,
|
|
198
|
+
logger
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
//# sourceMappingURL=redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../store/outstanding/redis.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { HexData32, UserOpInfo, UserOperation } from "../../types/index.js";
|
|
2
|
+
export type ConflictingOutstandingType = {
|
|
3
|
+
reason: "conflicting_nonce" | "conflicting_deployment";
|
|
4
|
+
userOpInfo: UserOpInfo;
|
|
5
|
+
} | undefined;
|
|
6
|
+
export interface OutstandingStore {
|
|
7
|
+
contains(userOpHash: HexData32): Promise<boolean>;
|
|
8
|
+
pop(count: number): Promise<UserOpInfo[]>;
|
|
9
|
+
popConflicting(userOp: UserOperation): Promise<ConflictingOutstandingType>;
|
|
10
|
+
add(userOpInfos: UserOpInfo[]): Promise<void>;
|
|
11
|
+
remove(userOpHash: HexData32[]): Promise<UserOpInfo[]>;
|
|
12
|
+
getQueuedUserOps(userOp: UserOperation): Promise<UserOperation[]>;
|
|
13
|
+
dumpLocal(): Promise<UserOpInfo[]>;
|
|
14
|
+
clear(): Promise<void>;
|
|
15
|
+
validateQueuedLimit(userOp: UserOperation): boolean;
|
|
16
|
+
validateParallelLimit(userOp: UserOperation): boolean;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../store/outstanding/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
import type { AltoConfig } from "../../createConfig.js";
|
|
3
|
+
import { type ProcessingStore } from "../index.js";
|
|
4
|
+
export declare function createProcessingStore({ config, entryPoint }: {
|
|
5
|
+
config: AltoConfig;
|
|
6
|
+
entryPoint: Address;
|
|
7
|
+
}): ProcessingStore;
|
|
8
|
+
export * from "./types.js";
|
|
9
|
+
export * from "./memory.js";
|
|
10
|
+
export * from "./redis.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { InMemoryProcessingStore, RedisProcessingStore } from "../index.js";
|
|
2
|
+
// Holds all userOps that have been removed from outstanding pool and are being processed.
|
|
3
|
+
// UserOps are are removed from this store when they have successfully landed onchain or when they are cancelled.
|
|
4
|
+
export function createProcessingStore({ config, entryPoint }) {
|
|
5
|
+
if (config.enableHorizontalScaling && config.redisEndpoint) {
|
|
6
|
+
return new RedisProcessingStore({
|
|
7
|
+
config,
|
|
8
|
+
entryPoint,
|
|
9
|
+
redisEndpoint: config.redisEndpoint
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
return new InMemoryProcessingStore();
|
|
13
|
+
}
|
|
14
|
+
export * from "./types.js";
|
|
15
|
+
export * from "./memory.js";
|
|
16
|
+
export * from "./redis.js";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../store/processing/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,uBAAuB,EAEvB,oBAAoB,EACvB,MAAM,aAAa,CAAA;AAEpB,0FAA0F;AAC1F,iHAAiH;AACjH,MAAM,UAAU,qBAAqB,CAAC,EAClC,MAAM,EACN,UAAU,EAIb;IACG,IAAI,MAAM,CAAC,uBAAuB,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QACzD,OAAO,IAAI,oBAAoB,CAAC;YAC5B,MAAM;YACN,UAAU;YACV,aAAa,EAAE,MAAM,CAAC,aAAa;SACtC,CAAC,CAAA;IACN,CAAC;IACD,OAAO,IAAI,uBAAuB,EAAE,CAAA;AACxC,CAAC;AAED,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { UserOpInfo, UserOperation } from "../../types/index.js";
|
|
2
|
+
import type { Hex } from "viem";
|
|
3
|
+
import type { ProcessingStore } from "./types.js";
|
|
4
|
+
export declare class InMemoryProcessingStore implements ProcessingStore {
|
|
5
|
+
private processingUserOpsSet;
|
|
6
|
+
private processingSenderNonceSet;
|
|
7
|
+
private processingDeploymentSet;
|
|
8
|
+
private encodeSenderNonceId;
|
|
9
|
+
addProcessing(userOpInfo: UserOpInfo): Promise<void>;
|
|
10
|
+
removeProcessing(userOpInfo: UserOpInfo): Promise<void>;
|
|
11
|
+
isProcessing(userOpHash: Hex): Promise<boolean>;
|
|
12
|
+
wouldConflict(userOp: UserOperation): Promise<"nonce_conflict" | "deployment_conflict" | undefined>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { isDeployment } from "../../utils/index.js";
|
|
2
|
+
export class InMemoryProcessingStore {
|
|
3
|
+
// Use Sets for boolean membership tracking (matching Redis store)
|
|
4
|
+
processingUserOpsSet = new Set();
|
|
5
|
+
processingSenderNonceSet = new Set();
|
|
6
|
+
processingDeploymentSet = new Set();
|
|
7
|
+
encodeSenderNonceId(sender, nonce) {
|
|
8
|
+
return `${sender}:${nonce}`;
|
|
9
|
+
}
|
|
10
|
+
async addProcessing(userOpInfo) {
|
|
11
|
+
const { userOpHash, userOp } = userOpInfo;
|
|
12
|
+
const isDeploymentOp = isDeployment(userOp);
|
|
13
|
+
const senderNonceId = this.encodeSenderNonceId(userOp.sender, userOp.nonce);
|
|
14
|
+
// Add to processing sets
|
|
15
|
+
this.processingUserOpsSet.add(userOpHash);
|
|
16
|
+
this.processingSenderNonceSet.add(senderNonceId);
|
|
17
|
+
if (isDeploymentOp) {
|
|
18
|
+
this.processingDeploymentSet.add(userOp.sender);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async removeProcessing(userOpInfo) {
|
|
22
|
+
const { userOpHash, userOp } = userOpInfo;
|
|
23
|
+
const senderNonceId = this.encodeSenderNonceId(userOp.sender, userOp.nonce);
|
|
24
|
+
// Remove from all sets
|
|
25
|
+
this.processingUserOpsSet.delete(userOpHash);
|
|
26
|
+
this.processingSenderNonceSet.delete(senderNonceId);
|
|
27
|
+
this.processingDeploymentSet.delete(userOp.sender);
|
|
28
|
+
}
|
|
29
|
+
async isProcessing(userOpHash) {
|
|
30
|
+
return this.processingUserOpsSet.has(userOpHash);
|
|
31
|
+
}
|
|
32
|
+
async wouldConflict(userOp) {
|
|
33
|
+
const isDeploymentOp = isDeployment(userOp);
|
|
34
|
+
const senderNonceId = this.encodeSenderNonceId(userOp.sender, userOp.nonce);
|
|
35
|
+
// Check deployment conflict first
|
|
36
|
+
if (isDeploymentOp && this.processingDeploymentSet.has(userOp.sender)) {
|
|
37
|
+
return "deployment_conflict";
|
|
38
|
+
}
|
|
39
|
+
// Check nonce conflict
|
|
40
|
+
if (this.processingSenderNonceSet.has(senderNonceId)) {
|
|
41
|
+
return "nonce_conflict";
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../store/processing/memory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI1C,MAAM,OAAO,uBAAuB;IAChC,kEAAkE;IAC1D,oBAAoB,GAAG,IAAI,GAAG,EAAO,CAAA;IACrC,wBAAwB,GAAG,IAAI,GAAG,EAAU,CAAA;IAC5C,uBAAuB,GAAG,IAAI,GAAG,EAAW,CAAA;IAE5C,mBAAmB,CAAC,MAAe,EAAE,KAAa;QACtD,OAAO,GAAG,MAAM,IAAI,KAAK,EAAE,CAAA;IAC/B,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,UAAsB;QACtC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,UAAU,CAAA;QACzC,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAC1C,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,KAAK,CACf,CAAA;QAED,yBAAyB;QACzB,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QACzC,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;QAEhD,IAAI,cAAc,EAAE,CAAC;YACjB,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACnD,CAAC;IACL,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,UAAsB;QACzC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,UAAU,CAAA;QACzC,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAC1C,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,KAAK,CACf,CAAA;QAED,uBAAuB;QACvB,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QAC5C,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;QACnD,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACtD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,UAAe;QAC9B,OAAO,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACpD,CAAC;IAED,KAAK,CAAC,aAAa,CACf,MAAqB;QAErB,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAC1C,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,KAAK,CACf,CAAA;QAED,kCAAkC;QAClC,IAAI,cAAc,IAAI,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACpE,OAAO,qBAAqB,CAAA;QAChC,CAAC;QAED,uBAAuB;QACvB,IAAI,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YACnD,OAAO,gBAAgB,CAAA;QAC3B,CAAC;QAED,OAAO,SAAS,CAAA;IACpB,CAAC;CACJ"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ProcessingStore } from "../index.js";
|
|
2
|
+
import type { UserOpInfo, UserOperation } from "../../types/index.js";
|
|
3
|
+
import type { Address, Hex } from "viem";
|
|
4
|
+
import type { AltoConfig } from "../../createConfig.js";
|
|
5
|
+
export declare class RedisProcessingStore implements ProcessingStore {
|
|
6
|
+
private redis;
|
|
7
|
+
private processingUserOpsSet;
|
|
8
|
+
private processingSenderNonceSet;
|
|
9
|
+
private processingDeploymentSet;
|
|
10
|
+
private encodeSenderNonceId;
|
|
11
|
+
constructor({ config, entryPoint, redisEndpoint }: {
|
|
12
|
+
config: AltoConfig;
|
|
13
|
+
entryPoint: Address;
|
|
14
|
+
redisEndpoint: string;
|
|
15
|
+
});
|
|
16
|
+
addProcessing(userOpInfo: UserOpInfo): Promise<void>;
|
|
17
|
+
removeProcessing(userOpInfo: UserOpInfo): Promise<void>;
|
|
18
|
+
isProcessing(userOpHash: Hex): Promise<boolean>;
|
|
19
|
+
wouldConflict(userOp: UserOperation): Promise<"nonce_conflict" | "deployment_conflict" | undefined>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=redis.d.ts.map
|