xclud / web3dart

Ethereum library, written in Dart.
https://pub.dev/packages/web3dart
MIT License
183 stars 96 forks source link

Event Filtering broken without Websockets #121

Open MariusVanDerWijden opened 1 year ago

MariusVanDerWijden commented 1 year ago

We've been working on an app that tries to query some events and the event filtering seems to be a bit broken. We're using "https://rpc.public.zkevm-test.net" as our RPC provider.

If we initialize the Web3Client without a socket connector, the event filtering fails with

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: RPCError: got code -32000 with msg "filter not found".
#0      JsonRPC.call (package:web3dart/json_rpc.dart:64:7)
<asynchronous suspension>
#1      _FilterEngine._refreshFilters (package:web3dart/src/core/filters.dart:359:13)
<asynchronous suspension>

If we initialize the Web3client with a bogus websocket connection like:

String ws = "ws://asdf.com";
client = Web3Client(rpc, Client(), socketConnector:  () {
      return IOWebSocketChannel.connect(ws).cast<String>();
    });

The filtering correctly returns the events

flutter: Found Open event for channel with ID [178, 59, 204, 204, 67, 15, 125, 110, 24, 162, 242, 162, 229, 159, 11, 31, 0, 146, 230, 20, 72, 103, 21, 232, 32, 21, 170, 218, 39, 14, 28, 107]

but the websocket connection errors (as expected)

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: WebSocketException: Connection to 'http://asdf.com:0#' was not upgraded to websocket
#0      _WebSocketImpl.connect (dart:_http/websocket_impl.dart:1011:41)
#1      WebSocket.connect (dart:_http/websocket.dart:320:22)

I think the issue is that get_Logs is only called when a socketConnector is available (even though it can be used on a regular http connection).

It works flawlessly if I modify the code to do this:

Stream<FilterEvent> events(FilterOptions options) {
    if (socketConnector != null) {
      // The real-time rpc nodes don't support listening to old data, so handle
      // that here.
      return Stream.fromFuture(getLogs(options))
          .expand((e) => e)
          .followedBy(_filters.addFilter(_EventFilter(options)));
    }
    return Stream.fromFuture(getLogs(options))
          .expand((e) => e); 
    //return _filters.addFilter(_EventFilter(options));
  }
MariusVanDerWijden commented 1 year ago

I've decided now to locally update our generated bindings to use getLogs instead of events, but it might be good either way to fix this