@pimlico/alto 0.0.0-main.20250916T162729 → 0.0.0-main.20250930T125129

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.
Files changed (91) hide show
  1. package/esm/cli/config/bundler.d.ts +12 -0
  2. package/esm/cli/config/bundler.js +2 -0
  3. package/esm/cli/config/bundler.js.map +1 -1
  4. package/esm/cli/config/options.js +11 -0
  5. package/esm/cli/config/options.js.map +1 -1
  6. package/esm/cli/setupServer.js +1 -1
  7. package/esm/cli/setupServer.js.map +1 -1
  8. package/esm/cli/shutDown.js +15 -55
  9. package/esm/cli/shutDown.js.map +1 -1
  10. package/esm/executor/bundleManager.d.ts +1 -1
  11. package/esm/executor/bundleManager.js +47 -34
  12. package/esm/executor/bundleManager.js.map +1 -1
  13. package/esm/executor/executorManager.js +3 -4
  14. package/esm/executor/executorManager.js.map +1 -1
  15. package/esm/executor/senderManager/createRedisSenderManager.js +1 -2
  16. package/esm/executor/senderManager/createRedisSenderManager.js.map +1 -1
  17. package/esm/handlers/arbitrumGasPriceManager.js +2 -2
  18. package/esm/handlers/gasPriceManager.js +3 -3
  19. package/esm/handlers/mantleGasPriceManager.js +4 -4
  20. package/esm/handlers/optimismManager.js +1 -1
  21. package/esm/mempool/mempool.d.ts +3 -11
  22. package/esm/mempool/mempool.js +91 -93
  23. package/esm/mempool/mempool.js.map +1 -1
  24. package/esm/mempool/monitoring.d.ts +1 -1
  25. package/esm/mempool/monitoring.js +30 -21
  26. package/esm/mempool/monitoring.js.map +1 -1
  27. package/esm/receiptCache/createMemoryReceiptCache.js +8 -5
  28. package/esm/receiptCache/createMemoryReceiptCache.js.map +1 -1
  29. package/esm/receiptCache/createRedisReceiptCache.js +13 -11
  30. package/esm/receiptCache/createRedisReceiptCache.js.map +1 -1
  31. package/esm/receiptCache/index.d.ts +4 -1
  32. package/esm/receiptCache/index.js.map +1 -1
  33. package/esm/rpc/methods/pimlico_sendUserOperationNow.js +4 -1
  34. package/esm/rpc/methods/pimlico_sendUserOperationNow.js.map +1 -1
  35. package/esm/store/createMempoolStore.d.ts +1 -1
  36. package/esm/store/createMempoolStore.js +51 -143
  37. package/esm/store/createMempoolStore.js.map +1 -1
  38. package/esm/store/index.d.ts +4 -75
  39. package/esm/store/index.js +4 -1
  40. package/esm/store/index.js.map +1 -1
  41. package/esm/store/outstanding/index.d.ts +13 -0
  42. package/esm/store/outstanding/index.js +16 -0
  43. package/esm/store/outstanding/index.js.map +1 -0
  44. package/esm/store/{createMemoryOutstandingStore.d.ts → outstanding/memory.d.ts} +11 -10
  45. package/esm/store/outstanding/memory.js +249 -0
  46. package/esm/store/outstanding/memory.js.map +1 -0
  47. package/esm/store/outstanding/redis.d.ts +11 -0
  48. package/esm/store/outstanding/redis.js +201 -0
  49. package/esm/store/outstanding/redis.js.map +1 -0
  50. package/esm/store/outstanding/types.d.ts +18 -0
  51. package/esm/store/outstanding/types.js +2 -0
  52. package/esm/store/outstanding/types.js.map +1 -0
  53. package/esm/store/processing/index.d.ts +11 -0
  54. package/esm/store/processing/index.js +17 -0
  55. package/esm/store/processing/index.js.map +1 -0
  56. package/esm/store/processing/memory.d.ts +14 -0
  57. package/esm/store/processing/memory.js +46 -0
  58. package/esm/store/processing/memory.js.map +1 -0
  59. package/esm/store/processing/redis.d.ts +21 -0
  60. package/esm/store/processing/redis.js +69 -0
  61. package/esm/store/processing/redis.js.map +1 -0
  62. package/esm/store/processing/types.d.ts +9 -0
  63. package/esm/store/processing/types.js +2 -0
  64. package/esm/store/processing/types.js.map +1 -0
  65. package/esm/store/types.d.ts +49 -0
  66. package/esm/store/types.js +2 -0
  67. package/esm/store/types.js.map +1 -0
  68. package/esm/utils/minMaxQueue/createRedisMinMaxQueue.d.ts +23 -2
  69. package/esm/utils/minMaxQueue/createRedisMinMaxQueue.js +83 -60
  70. package/esm/utils/minMaxQueue/createRedisMinMaxQueue.js.map +1 -1
  71. package/esm/utils/minMaxQueue/index.d.ts +2 -2
  72. package/esm/utils/minMaxQueue/index.js +2 -2
  73. package/esm/utils/minMaxQueue/index.js.map +1 -1
  74. package/esm/utils/userop.d.ts +1 -0
  75. package/esm/utils/userop.js +6 -0
  76. package/esm/utils/userop.js.map +1 -1
  77. package/package.json +1 -1
  78. package/esm/cli/config/redisKeys.d.ts +0 -9
  79. package/esm/cli/config/redisKeys.js +0 -16
  80. package/esm/cli/config/redisKeys.js.map +0 -1
  81. package/esm/store/createMemoryOutstandingStore.js +0 -240
  82. package/esm/store/createMemoryOutstandingStore.js.map +0 -1
  83. package/esm/store/createRedisOutstandingStore.d.ts +0 -28
  84. package/esm/store/createRedisOutstandingStore.js +0 -341
  85. package/esm/store/createRedisOutstandingStore.js.map +0 -1
  86. package/esm/store/createRedisStore.d.ts +0 -10
  87. package/esm/store/createRedisStore.js +0 -128
  88. package/esm/store/createRedisStore.js.map +0 -1
  89. package/esm/store/createStore.d.ts +0 -6
  90. package/esm/store/createStore.js +0 -66
  91. package/esm/store/createStore.js.map +0 -1
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.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
@@ -0,0 +1,69 @@
1
+ import { isDeployment } from "../../utils/index.js";
2
+ import { Redis } from "ioredis";
3
+ export class RedisProcessingStore {
4
+ redis;
5
+ processingUserOpsSet; // set of userOpHashes being processed
6
+ processingSenderNonceSet; // set of "sender:nonce" being processed
7
+ processingDeploymentSet; // set of senders with deployments being processed
8
+ encodeSenderNonceId(sender, nonce) {
9
+ return `${sender}:${nonce}`;
10
+ }
11
+ constructor({ config, entryPoint, redisEndpoint }) {
12
+ this.redis = new Redis(redisEndpoint);
13
+ const redisPrefix = `${config.redisKeyPrefix}:${config.chainId}:${entryPoint}:processing`;
14
+ this.processingUserOpsSet = `${redisPrefix}:userOps`;
15
+ this.processingSenderNonceSet = `${redisPrefix}:senderNonce`;
16
+ this.processingDeploymentSet = `${redisPrefix}:deployment`;
17
+ }
18
+ async addProcessing(userOpInfo) {
19
+ const { userOpHash, userOp } = userOpInfo;
20
+ const isDeploymentOp = isDeployment(userOp);
21
+ const senderNonceId = this.encodeSenderNonceId(userOp.sender, userOp.nonce);
22
+ // Use MULTI for atomic operation in single round trip
23
+ const multi = this.redis.multi();
24
+ multi.sadd(this.processingUserOpsSet, userOpHash);
25
+ multi.sadd(this.processingSenderNonceSet, senderNonceId);
26
+ if (isDeploymentOp) {
27
+ multi.sadd(this.processingDeploymentSet, userOp.sender);
28
+ }
29
+ await multi.exec();
30
+ }
31
+ async removeProcessing(userOpInfo) {
32
+ const { userOpHash, userOp } = userOpInfo;
33
+ const isDeploymentOp = isDeployment(userOp);
34
+ const senderNonceId = this.encodeSenderNonceId(userOp.sender, userOp.nonce);
35
+ // Use MULTI for atomic removal in single round trip
36
+ const multi = this.redis.multi();
37
+ multi.srem(this.processingUserOpsSet, userOpHash);
38
+ multi.srem(this.processingSenderNonceSet, senderNonceId);
39
+ if (isDeploymentOp) {
40
+ multi.srem(this.processingDeploymentSet, userOp.sender);
41
+ }
42
+ await multi.exec();
43
+ }
44
+ async isProcessing(userOpHash) {
45
+ const isMember = await this.redis.sismember(this.processingUserOpsSet, userOpHash);
46
+ return isMember === 1;
47
+ }
48
+ async wouldConflict(userOp) {
49
+ const senderNonceId = this.encodeSenderNonceId(userOp.sender, userOp.nonce);
50
+ // Use MULTI for atomic read in single round trip
51
+ const multi = this.redis.multi();
52
+ multi.sismember(this.processingDeploymentSet, userOp.sender);
53
+ multi.sismember(this.processingSenderNonceSet, senderNonceId);
54
+ const results = await multi.exec();
55
+ if (!results)
56
+ return undefined;
57
+ const [deploymentResult, nonceResult] = results;
58
+ const hasDeployment = deploymentResult?.[1] === 1;
59
+ const hasNonce = nonceResult?.[1] === 1;
60
+ if (hasDeployment) {
61
+ return "deployment_conflict";
62
+ }
63
+ if (hasNonce) {
64
+ return "nonce_conflict";
65
+ }
66
+ return undefined;
67
+ }
68
+ }
69
+ //# sourceMappingURL=redis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../store/processing/redis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { UserOpInfo, UserOperation } from "../../types/index.js";
2
+ import type { Hex } from "viem";
3
+ export interface ProcessingStore {
4
+ addProcessing(userOp: UserOpInfo): Promise<void>;
5
+ removeProcessing(userOp: UserOpInfo): Promise<void>;
6
+ isProcessing(userOpHash: Hex): Promise<boolean>;
7
+ wouldConflict(userOp: UserOperation): Promise<"nonce_conflict" | "deployment_conflict" | undefined>;
8
+ }
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../store/processing/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,49 @@
1
+ import type { Address } from "abitype";
2
+ import type { HexData32, UserOpInfo, UserOperation } from "../types/schemas.js";
3
+ import type { ConflictingOutstandingType } from "./outstanding/index.js";
4
+ export type StoreType = "outstanding" | "processing";
5
+ export type ValidationResult = {
6
+ valid: true;
7
+ } | {
8
+ valid: false;
9
+ reason: string;
10
+ };
11
+ export type EntryPointUserOpInfoParam = {
12
+ entryPoint: Address;
13
+ userOpInfo: UserOpInfo;
14
+ };
15
+ export type EntryPointUserOpInfosParam = {
16
+ entryPoint: Address;
17
+ userOpInfos: UserOpInfo[];
18
+ };
19
+ export type EntryPointUserOpHashParam = {
20
+ entryPoint: Address;
21
+ userOpHash: HexData32;
22
+ };
23
+ export type MempoolStore = {
24
+ popOutstanding: (entryPoint: Address, count: number) => Promise<UserOpInfo[]>;
25
+ addOutstanding: (args: EntryPointUserOpInfosParam) => Promise<void>;
26
+ removeOutstanding: (args: EntryPointUserOpHashParam) => Promise<void>;
27
+ dumpOutstanding: (entryPoint: Address) => Promise<UserOpInfo[]>;
28
+ addProcessing: (args: EntryPointUserOpInfoParam) => Promise<void>;
29
+ removeProcessing: (args: EntryPointUserOpInfoParam) => Promise<void>;
30
+ checkDuplicatesAndConflicts: (args: {
31
+ entryPoint: Address;
32
+ userOp: UserOperation;
33
+ userOpHash: HexData32;
34
+ }) => Promise<ValidationResult>;
35
+ popConflictingOustanding: (args: {
36
+ entryPoint: Address;
37
+ userOp: UserOperation;
38
+ }) => Promise<ConflictingOutstandingType>;
39
+ validateSenderLimits: (args: {
40
+ entryPoint: Address;
41
+ userOp: UserOperation;
42
+ }) => Promise<ValidationResult>;
43
+ getQueuedOutstandingUserOps: (args: {
44
+ userOp: UserOperation;
45
+ entryPoint: Address;
46
+ }) => Promise<UserOperation[]>;
47
+ clearOutstanding: (entryPoint: Address) => Promise<void>;
48
+ };
49
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../store/types.ts"],"names":[],"mappings":""}
@@ -1,8 +1,29 @@
1
+ /**
2
+ * MinMaxQueue implementation in Redis using a single sorted set
3
+ *
4
+ * ## Data Structure
5
+ * - Uses a Redis sorted set where:
6
+ * - Score: timestamp when value was added (seconds since epoch)
7
+ * - Member: the actual bigint value (stored as string)
8
+ *
9
+ * ## Flow
10
+ * 1. **Adding values**: New values are added/updated with current timestamp as score
11
+ * 2. **Reading values**: Queries filter out expired entries based on timestamp
12
+ * 3. **Cleanup**: Background process runs every minute to remove expired entries
13
+ *
14
+ * ## Optimization Strategy
15
+ * - Lazy cleanup: expired entries filtered on read, bulk removed by background process (removing is expensive)
16
+ *
17
+ * ## TTL Management
18
+ * - Entries expire based on `queueValidity` (configured via `gasPriceExpiry`)
19
+ * - Background cleanup prevents unbounded growth
20
+ * - Read operations ignore expired entries without removing them
21
+ */
1
22
  import type { MinMaxQueue } from "./index.js";
2
23
  import type { AltoConfig } from "../../createConfig.js";
3
- export declare const createRedisMinMaxQueue: ({ config, keyPrefix, redisEndpoint }: {
24
+ export declare const createRedisMinMaxQueue: ({ config, queueName, redisEndpoint }: {
4
25
  config: AltoConfig;
5
- keyPrefix: string;
26
+ queueName: string;
6
27
  redisEndpoint: string;
7
28
  }) => MinMaxQueue;
8
29
  //# sourceMappingURL=createRedisMinMaxQueue.d.ts.map