Skip to content

Commit 80b2ead

Browse files
authored
fix: block filters can be also recreated (#85)
* fix: block filters can be also recreated * refactor: rename filter to logFilter
1 parent d60cedb commit 80b2ead

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed

ethers/providers/jsonrpc/subscriptions.nim

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ type
140140
# We need to keep around the filters that are used to create log filters on the RPC node
141141
# as there might be a time when they need to be recreated as RPC node might prune/forget
142142
# about them
143-
filters: Table[JsonNode, EventFilter]
143+
logFilters: Table[JsonNode, EventFilter]
144144

145145
# Used when filters are recreated to translate from the id that user
146146
# originally got returned to new filter id
@@ -167,8 +167,15 @@ proc new*(_: type JsonRpcSubscriptions,
167167
raise e
168168
except CatchableError as e:
169169
if "filter not found" in e.msg:
170-
let filter = subscriptions.filters[originalId]
171-
let newId = await subscriptions.client.eth_newFilter(filter)
170+
var newId: JsonNode
171+
# Log filters are stored in logFilters, block filters are not persisted
172+
# there is they do not need any specific data for their recreation.
173+
# We use this to determine if the filter was log or block filter here.
174+
if subscriptions.logFilters.hasKey(originalId):
175+
let filter = subscriptions.logFilters[originalId]
176+
newId = await subscriptions.client.eth_newFilter(filter)
177+
else:
178+
newId = await subscriptions.client.eth_newBlockFilter()
172179
subscriptions.subscriptionMapping[originalId] = newId
173180
return await getChanges(originalId)
174181
else:
@@ -225,14 +232,14 @@ method subscribeLogs(subscriptions: PollingSubscriptions,
225232

226233
let id = await subscriptions.client.eth_newFilter(filter)
227234
subscriptions.callbacks[id] = callback
228-
subscriptions.filters[id] = filter
235+
subscriptions.logFilters[id] = filter
229236
subscriptions.subscriptionMapping[id] = id
230237
return id
231238

232239
method unsubscribe*(subscriptions: PollingSubscriptions,
233240
id: JsonNode)
234241
{.async.} =
235-
subscriptions.filters.del(id)
242+
subscriptions.logFilters.del(id)
236243
subscriptions.callbacks.del(id)
237244
let sub = subscriptions.subscriptionMapping[id]
238245
subscriptions.subscriptionMapping.del(id)

testmodule/providers/jsonrpc/rpc_mock.nim

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ proc start*(server: MockRpcHttpServer) =
2525
server.filters.add filterId
2626
return filterId
2727

28+
server.srv.router.rpc("eth_newBlockFilter") do() -> string:
29+
let filterId = "0x" & (array[16, byte].example).toHex
30+
server.filters.add filterId
31+
return filterId
32+
2833
server.srv.router.rpc("eth_getFilterChanges") do(id: string) -> seq[string]:
2934
if id notin server.filters:
3035
raise (ref ApplicationError)(code: -32000, msg: "filter not found")

testmodule/providers/jsonrpc/testJsonRpcSubscriptions.nim

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,25 +124,25 @@ suite "HTTP polling subscriptions - filter not found":
124124
await client.close()
125125
await mockServer.stop()
126126

127-
test "filter not found error recreates filter":
127+
test "filter not found error recreates log filter":
128128
let filter = EventFilter(address: Address.example, topics: @[array[32, byte].example])
129129
let emptyHandler = proc(log: Log) = discard
130130

131-
check subscriptions.filters.len == 0
131+
check subscriptions.logFilters.len == 0
132132
check subscriptions.subscriptionMapping.len == 0
133133

134134
let id = await subscriptions.subscribeLogs(filter, emptyHandler)
135135

136-
check subscriptions.filters[id] == filter
136+
check subscriptions.logFilters[id] == filter
137137
check subscriptions.subscriptionMapping[id] == id
138-
check subscriptions.filters.len == 1
138+
check subscriptions.logFilters.len == 1
139139
check subscriptions.subscriptionMapping.len == 1
140140

141141
mockServer.invalidateFilter(id)
142142

143143
check eventually subscriptions.subscriptionMapping[id] != id
144144

145-
test "recreated filter can be still unsubscribed using the original id":
145+
test "recreated log filter can be still unsubscribed using the original id":
146146
let filter = EventFilter(address: Address.example, topics: @[array[32, byte].example])
147147
let emptyHandler = proc(log: Log) = discard
148148
let id = await subscriptions.subscribeLogs(filter, emptyHandler)
@@ -151,5 +151,26 @@ suite "HTTP polling subscriptions - filter not found":
151151

152152
await subscriptions.unsubscribe(id)
153153

154-
check not subscriptions.filters.hasKey id
154+
check not subscriptions.logFilters.hasKey id
155+
check not subscriptions.subscriptionMapping.hasKey id
156+
157+
test "filter not found error recreates block filter":
158+
let emptyHandler = proc(blck: Block) = discard
159+
160+
check subscriptions.subscriptionMapping.len == 0
161+
let id = await subscriptions.subscribeBlocks(emptyHandler)
162+
check subscriptions.subscriptionMapping[id] == id
163+
164+
mockServer.invalidateFilter(id)
165+
166+
check eventually subscriptions.subscriptionMapping[id] != id
167+
168+
test "recreated block filter can be still unsubscribed using the original id":
169+
let emptyHandler = proc(blck: Block) = discard
170+
let id = await subscriptions.subscribeBlocks(emptyHandler)
171+
mockServer.invalidateFilter(id)
172+
check eventually subscriptions.subscriptionMapping[id] != id
173+
174+
await subscriptions.unsubscribe(id)
175+
155176
check not subscriptions.subscriptionMapping.hasKey id

0 commit comments

Comments
 (0)