-
-
Notifications
You must be signed in to change notification settings - Fork 327
Add websocket subprovider #189
Comments
Relevant notes here: MetaMask/metamask-extension#2350 (comment) id like to differentiate between:
|
@danfinlay & @kumavis I'm working on websockets support for ganache right now, which included updating to the latest provider engine. I'd be all kinds of happy to package up the subscription subprovider I'm writing as a PR. I have it mostly written already, but I need to do some cleanup/refactoring. Do you have any strong preferences for the way it should be done? At the moment it holds a reference to the At present it works by exposing an |
I’d defer to @kumavis, but the end subproviders should just pass through requests, allowing server-side filter management, unless a middleware like filter subprovider were before it. |
Isn't this already tackled by #207? |
I'm working on this. |
Looking closer at this, it seems there's more to do than just replace FetchProvider with a WebsocketProvider. The provider stack seems to be built around a polling mechanism (using |
@ryan-rowland You are correct, sorry for not including this in the original post (will update it): Since Enter: json-rpc-engine. Basically the same as provider-engine, but without the ethereum-opinionated portions like block-polling. It would be more correct to write the websocket subprovider for that, and then move MetaMask over to it from I'm hoping @kumavis can come in and shed additional light on this, since he's the one who's been re-writing |
@ryan-rowland you added WebsocketSubprovider (thanks!) in #227 but did not actually setup forwarding subscription responses (server-sent json rpc 'notifications') on the provider-engine. I did the final steps, and I'm releasing in |
Fixed in |
Thanks for following up @kumavis ! Glad to see this issue moving forward. |
@lazaridiscom This adds the logic to talk to the websocket gateways, so it's a step forward. The issue I ran into at this point was getting disconnected from the gateway because the provider was still using polling logic rather than subscription. It seems like @kumavis may have updated the logic to use subscriptions, in which case I'd say this is a big step toward web3 1.0 support. I'll let @kumavis speak to it in more detail as he's been following up on it. |
matthewlilley/metamask-extension@6827fdf This is the simplest solution I came up with for providing Web3 1.0+ subscription support to MetaMask, and it's inpage provider. It works. Needs review. @danfinlay @kumavis |
@matthewlilley I left comments on your commit. Open a PR next time please. 😄 @lazaridiscom Sorry I won't be a position to test any time this week. |
@ryan-rowland Thank you Ryan. Pull request MetaMask/metamask-extension@65d907f |
@matthewlilley You tricked me again! That's a commit, not a PR. |
Fix randomly failing filter and subscription tests #189
So... does Metamask now support connecting to custom WS-RPC? If I select Custom RPC and enter New RPC URL that starts with ws://, I get error "URIs require the appropriate HTTP/HTTPS prefix." |
@jtakalai no, seems to not yet seem the case. |
Worth noting that MetaMask has converted to a different module we wrote, json-rpc-engine, which can accomplish the same goals in combination with eth-json-rpc-middleware. It is less coupled to the ethereum RPC, and allows a more modular composition of features. |
Yes, a subprovider was added to provider-engine, but it was never added to MetaMask for a few reasons. Moving off provider-engine was more important to allowing performance than websockets (allowed better block-tracker pausing and cache busting by decoupling them from the main engine). That work could potentially be ported to There might be other implications, I would ask @kumavis to chime in. |
This would allow push updates, and compatibility with Web3 1.0.
Updated March 22, 2018 to help potential new contributors make sense of this issue:
Provider engine is a system for composing middleware objects (which we call
subproviders
) into a potentially complex system for managing the response to a given request object.ProviderEngine itself is also an Ethereum Provider, as in web3.currentProvider, so once composed with middleware, it exposes the standard
sendAsync()
method for Ethereum developers to make requests of the JSON RPC API.When calling
providerEngine.sendAsync(yourOpts, callbackFunction)
, those options you pass in get passed from one middleware object to the next. You can see how here.As you can see, each provider is passed the same options object, potentially mutating it, and with a pair of callback functions to either end the response immediately, or to pass the options on to the next provider.
To operate as a
subprovider
, an object only needs to expose afunction handleRequest (options, next, end)
, as you can see here in the fetch subprovider.In that function, the
subprovider
can mutate theoptions
freely, and then either call thenext()
orend()
functions.next()
is only used by true "middleware" subproviders, to pass the options to the next subprovider. That function will not be needed for this feature.The
end()
function represents the result that will be returned to theProviderEngine
consumer, and should follow the JavaScript API specification, including its JSON-RPC style error format.The Fetch Subprovider is how MetaMask currently talks to an Ethereum node. It uses the
fetch
API, which is pure HTTP, to make requests of whatever RPC it is pointed at.This issue is to create a similar subprovider, but one that uses Websockets instead of HTTP, and uses the Geth Websocket API instead of the usual HTTP-based JSON RPC API. The request/response format should otherwise be basically identical.
Further Goals
There are other goals that are often associated with this one, which can make it seem more complicated, but are actually separate deliverables.
Websocket Block Tracker
Right now the way MetaMask keeps track of the current block is also via HTTP, via the eth-block-tracker module. We could definitely also improve performance by moving that over to websockets, or making a websocket version of it.
Websocket Based Subscriptions
While #207 adds a subprovider for providing the
providerEngine.subscribe()
API, it does this with polling under the hood. This API would be much more performant if its functionality were moved into the websocket subprovider.The text was updated successfully, but these errors were encountered: