Skip to content

Commit

Permalink
Fix subscription handler (#175)
Browse files Browse the repository at this point in the history
* Fix contract_dsl event response parser

* Fix pending subscription event handler

* Use useDefaultSerializationIn for EventData

Surprisingly the pending event bug not detected when using ganache. It only manifest after migrated to hardhat. Also not detected on linux and windows CI. Only on macos amd64 CI, and sometimes on macos arm64 CI. Probably related to async timing trigger pending event?. But it's a genuine bug, dated back far before migration from stdlib/json to json-serialization.
  • Loading branch information
jangko authored Oct 23, 2024
1 parent c76ddef commit 8003166
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 19 deletions.
16 changes: 3 additions & 13 deletions web3.nim
Original file line number Diff line number Diff line change
Expand Up @@ -87,28 +87,18 @@ func getValue(params: RequestParamsRx, field: string, FieldType: type):
except CatchableError as exc:
return err(exc.msg)

func toJsonString(params: RequestParamsRx):
Result[JsonString, string] {.gcsafe, raises: [].} =
try:
let res = JrpcSys.encode(params.toTx)
return ok(res.JsonString)
except CatchableError as exc:
return err(exc.msg)

proc handleSubscriptionNotification(w: Web3, params: RequestParamsRx):
Result[void, string] {.gcsafe, raises: [].} =
let subs = params.getValue("subscription", string).valueOr:
return err(error)
let s = w.subscriptions.getOrDefault(subs)
if not s.isNil and not s.removed:
let res = params.getValue("result", JsonString).valueOr:
return err(error)
if s.historicalEventsProcessed:
let res = params.getValue("result", JsonString).valueOr:
return err(error)
s.eventHandler(res)
else:
let par = params.toJsonString().valueOr:
return err(error)
s.pendingEvents.add(par)
s.pendingEvents.add(res)

ok()

Expand Down
17 changes: 11 additions & 6 deletions web3/contract_dsl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import
std/[macros, strutils],
json_serialization,
./[encoding, eth_api_types],
./conversions,
stint,
stew/byteutils

Expand Down Expand Up @@ -40,6 +41,12 @@ type
of constructor: constructorObject: ConstructorObject
of event: eventObject: EventObject

EventData* = object
data*: seq[byte]
topics*: seq[Bytes32]

EventData.useDefaultSerializationIn JrpcConv

proc joinStrings(s: varargs[string]): string = join(s)

proc unknownType() = discard # Used for informative errors
Expand Down Expand Up @@ -233,7 +240,7 @@ proc genEvent(cname: NimNode, eventObject: EventObject): NimNode =
if not eventObject.anonymous:
let callbackIdent = ident "callback"
let jsonIdent = ident "j"
let jsonData = ident "jsonData"
let eventData = ident "eventData"
var
params = nnkFormalParams.newTree(newEmptyNode())
paramsWithRawData = nnkFormalParams.newTree(newEmptyNode())
Expand All @@ -243,10 +250,9 @@ proc genEvent(cname: NimNode, eventObject: EventObject): NimNode =
call = nnkCall.newTree(callbackIdent)
callWithRawData = nnkCall.newTree(callbackIdent)
offset = ident "offset"
inputData = ident "inputData"

argParseBody.add quote do:
let `jsonData` = JrpcConv.decode(`jsonIdent`.string, JsonNode)
let `eventData` = JrpcConv.decode(`jsonIdent`.string, EventData)

var offsetInited = false

Expand All @@ -264,19 +270,18 @@ proc genEvent(cname: NimNode, eventObject: EventObject): NimNode =
if input.indexed:
argParseBody.add quote do:
var `argument`: `kind`
discard decode(hexToSeqByte(`jsonData`["topics"][`i`].getStr), 0, 0, `argument`)
discard decode(`eventData`.topics[`i`].data, 0, 0, `argument`)
i += 1
else:
if not offsetInited:
argParseBody.add quote do:
var `inputData` = hexToSeqByte(`jsonData`["data"].getStr)
var `offset` = 0

offsetInited = true

argParseBody.add quote do:
var `argument`: `kind`
`offset` += decode(`inputData`, 0, `offset`, `argument`)
`offset` += decode(`eventData`.data, 0, `offset`, `argument`)
call.add argument
callWithRawData.add argument
let
Expand Down

0 comments on commit 8003166

Please sign in to comment.