trufflesuite / drizzle-legacy

Reactive Ethereum datastore for dapp UIs.
http://truffleframework.com/docs/drizzle/getting-started
MIT License
502 stars 129 forks source link

Broadcast Events Externally #147

Closed OnlyOneJMJQ closed 5 years ago

OnlyOneJMJQ commented 5 years ago

Drizzle makes some subscriptions automatically, but currently their emitted events are "trapped" internally. This causes code duplication when someone wants to act on these events and they're not causing changes in the store, e.g. block subscription events.

We should provide the option to broadcast web3 events (data from onNewBlockHeaders for example) users would expect to get from making these subscriptions themselves as well as contract events and other chain happenings (account switching, for example).

I've opened this issue for visibility and to encourage anyone to comment with events they'd like to see!

cliffhall commented 5 years ago

Please and thank you. Right now, I just want to get an update when one of my contracts emits an event. That could be in the form of some state change, but I'd prefer a callback, since my app has its own store and uses DrizzleContext.Consumer to gain access to the drizzleState. Please take that possibility into account when you craft the solution.

samajammin commented 5 years ago

Yes, please! My use case:

I'm currently subscribing to a contract event in my drizzleOptions.js:

  events: {
    SimpleDemocracy: [
      'ElectionCreated'
    ]
  },

It appears we can pass event options into the events object. It would be great to also allow some sort of callback here to work with received event data. E.g.:

  events: {
    SimpleDemocracy: [
      {
        eventName: 'ElectionCreated',
        eventCallback: (event) => { trackEvent(event) }
      }
    ]
  },

I'm curious @DiscRiskandBisque ... you mentioned:

This causes code duplication when someone wants to act on these events and they're not causing changes in the store

If my event does cause changes to the store, how would you recommend reacting to this? Is there somewhere else I can add a listener to a state change in order to trigger my callback? Thanks.

samajammin commented 5 years ago

In case this is useful for others, here's the basic workaround I've come up with.

In my parent component's constructor:

context.drizzle.contracts.SimpleDemocracy.events
  .ElectionCreated()
  .on('data', event => {
    trackEvent(event);
  });

One issue I haven't solved is that this listener now fires multiple times per contract event. Digging into actions with Redux DevTools reveals duplicate EVENT_FIRED actions for a single transaction event:

image 2019-01-25 at 11 58 01 am

Not sure if that's a separate Drizzle/Web3 issue? Or merely a side-effect of using a local testnest as described here.

cds-amal commented 5 years ago

I'm working on exposing contract events by allowing drizzle clients to add custom Redux middleware. This method requires constructing a local store to pass as attribute to DrizzleProvider. There's some boiler plate that can be abstracted away by Drizzle.

I have a Demo repo here

[Edit update to reflect wip]