This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Discussion: Provider will fail if the backend network changes except for "any" #866
Labels
META
An Issue about Issues
This is the beginning for an issue I think will seem confusing to some at first, but is the culmination of a lot of thought, discussion and experimentation. :)
The related issues are: #495 #589 #861
tl;dr: This only affects backends that can change their network, such as MetaMask or using your own Geth instance; to get the legacy functionality, pass the string
"any"
as the network parameter, but please be aware that there are many edge cases your dapp should be handling that you may not be. Not using the"any"
network might help flush out parts of your dapp which were previously unsafe in cases you hadn't even thought of. :)Provider calls result in NETWORK_ERROR
Basically, when a Provider is created, it will self-detect its network (or can have its network explicitly specified in the constructor) and whenever executing an operation, it ensures the network matches. If it has changed the call will fail and throw a
NETWORK_ERROR
.This extends to events. If an event filter is being listened for and the network changes, no further events will be emitted until the network is back where it belongs.
Provider special network
"any"
There is now a special network name,
"any"
, which if specified means the Provider will allow the backend network to change, meaning the network is not immutable.If the network changes, a
"network"
event is emitted, and all calls pending on the network are deferred an additional event loop, which allows the callback to unregister events before any caller has access to the new network object. This also means that no events on the new network will be triggered before the"network"
event. However, if your callback schedules something for the next event loop (e.g.await
) it will occur after the network has possibly been read by another caller.Some developers may not need to care about the current or changing networks, so this option is for them. But it is important that this type of operation is thought through.
The design pattern for many applications will likely be "on network change, shut down all events and cancel all inflight requests, and rebuild the hierarchy of events on the new network, set up the UI and provide feedback to the user".
For example, if you are monitoring an ERC-20 contract, the address may differ on the two networks, the UI will likely need the balances updated, available "approved" balances may need to be updated internally, a new banner should be included to indicate whether the network is a testnet and in that case that the funds are fake. New event filters will need to be setup (the old ones torn down) so that new incoming transfers are added to the UI transaction history as well. Make sure important caches your app manages are also discarded, such as ENS names and approved accounts.
I plan to provide code snippets at some point to illustrate this design pattern. But this is something that will be further down the road.
Simplest Solution
Most users never change their network, mostly this is something developers do during testing. So to keep like simple, you can simply force a page refresh when the network changes. Only developers should really notice this and it makes sure your UI and any network banners, etc. get a fresh start at setting up their world.
The do this, you can use something like:
Block Skew
As a somewhat related note, historically, if the
"block"
event was being listened for, the callback would be triggered for every block between the last poll cycle and the current poll cycle. So, if block 1000 was the last block from the previous poll, but the current block number is 1003, a"block"
event would be emitted for 1001, 1002 and 1003.Now if more than 1000 blocks passed between two poll cycles, then a block skew error will be emitted and the provider will reset from the current block. Less than 1000 blocks will still behave normally.
This historically only happened when a laptop was closed for a long duration or when changing networks (rinkeby vs ropsten have a large gap in block height), which could cause web pages to become unresponsive as the Provider tried to emit all the
"block"
events.Now changing networks will only possible have a similar effect as the closed-laptop scenario, since the Provider is basically stalled; if the network change occurs for more than 1000 blocks, there will be block skew detected and will skip all the intermediate block events. This may happen if the application is in another tab the user ignores for quite some time.
Note: This does not affect any statically networked backends, like INFURA, Etherscan, etc. since those network backends cannot change; they are defined when the Provider is created. This is mainly for JsonRpcProviders, where a user shuts down their Geth node and brings it up with a new network, or the most common situation, a Web3Provider connected to MetaMask.
The text was updated successfully, but these errors were encountered: