f-o-a-m / purescript-web3

a purescript library for the web3 api
Apache License 2.0
127 stars 24 forks source link

Allow streaming of Events in reverse order #147

Closed kejace closed 7 months ago

kejace commented 3 years ago

Problem

A common set of UX problem for web3 apps that are long-lived, is that it is hard to make the user get a good entry point to the events generated by that app.

Questions that the developer currently have to decide are:

An example is the chanterelle-halogen-template app, which streams the events from an ERC721 app which was deployed years ago, but which is still actively in use.

When launched, it displays the earliest events, and it would effectively take way too much time for the user to arrive at the most recent events. This makes the app, as written, impossible to use.

The developer could come up with a heuristic for how to get around these problems, but I would argue that the most ideal pattern is for ps-web3 to handle this, transparently.

Solution

If this library supports streaming of events in reverse order, it would be much easier for the developer to make a view of the app from the most recent activity. If the user requests earlier events, by scrolling to the bottom of the page for example, the app can simply stream older events, similar to paging in CRUD apps.

In the current implementation of event', it simply returns pure unit in the case that fromBlock >= toBlock. The requested feature is that it instead processes the events in an order which is effectively reversed. Note that there are some possible corner cases if fromBlock == Latest or fromBlock == Pending, for example, as it might be still processing older events while a new block comes in. The behavior in this case should be documented and allow for a non-overlapping events in the case that the developer runs event' on a more recent block in the future.

Note that the types don't need to change, as we have

newtype Filter a = Filter
  { address   :: Maybe Address
  , topics    :: Maybe (Array (Maybe HexString))
  , fromBlock :: ChainCursor
  , toBlock   :: ChainCursor
  }

and

data ChainCursor =
    Latest
  | Pending
  | Earliest
  | BN BlockNumber

and the behavior would simply support event' with a filter where fromBlock > toBlock