xclud / web3dart

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

Event Filtering broken without Websockets #121

Open MariusVanDerWijden opened 10 months ago

MariusVanDerWijden commented 10 months 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 10 months 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