From 80031669e1514ea35464dcabb939c971cecd2098 Mon Sep 17 00:00:00 2001 From: andri lim Date: Wed, 23 Oct 2024 17:05:48 +0700 Subject: [PATCH 1/2] Fix subscription handler (#175) * 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. --- web3.nim | 16 +++------------- web3/contract_dsl.nim | 17 +++++++++++------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/web3.nim b/web3.nim index 377b13d..b1cb022 100644 --- a/web3.nim +++ b/web3.nim @@ -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() diff --git a/web3/contract_dsl.nim b/web3/contract_dsl.nim index 4a1db4f..b39115b 100644 --- a/web3/contract_dsl.nim +++ b/web3/contract_dsl.nim @@ -2,6 +2,7 @@ import std/[macros, strutils], json_serialization, ./[encoding, eth_api_types], + ./conversions, stint, stew/byteutils @@ -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 @@ -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()) @@ -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 @@ -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 From 40854fb51fd444b7537da767800fbca2189eb2b7 Mon Sep 17 00:00:00 2001 From: andri lim Date: Wed, 23 Oct 2024 17:24:33 +0700 Subject: [PATCH 2/2] No need to use derefType anymore when using useDefault***In (#174) --- web3/conversions.nim | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/web3/conversions.nim b/web3/conversions.nim index 7fa61fe..dd3b873 100644 --- a/web3/conversions.nim +++ b/web3/conversions.nim @@ -28,9 +28,6 @@ export export eth_types_json_serialization except Topic -template derefType(T: type): untyped = - typeof(T()[]) - #------------------------------------------------------------------------------ # eth_api_types #------------------------------------------------------------------------------ @@ -47,10 +44,10 @@ TransactionArgs.useDefaultSerializationIn JrpcConv FeeHistoryResult.useDefaultSerializationIn JrpcConv AuthorizationObject.useDefaultSerializationIn JrpcConv -derefType(BlockHeader).useDefaultSerializationIn JrpcConv -derefType(BlockObject).useDefaultSerializationIn JrpcConv -derefType(TransactionObject).useDefaultSerializationIn JrpcConv -derefType(ReceiptObject).useDefaultSerializationIn JrpcConv +BlockHeader.useDefaultSerializationIn JrpcConv +BlockObject.useDefaultSerializationIn JrpcConv +TransactionObject.useDefaultSerializationIn JrpcConv +ReceiptObject.useDefaultSerializationIn JrpcConv #------------------------------------------------------------------------------ # engine_api_types