Ethers.js: Detecting if a provider has a valid signer

Created on 11 Mar 2020  路  5Comments  路  Source: ethers-io/ethers.js

Is there a way to check if a given provider has a valid signer (i.e., if I can send signed transactions with it?)

The reason for this is that I'm using web3-react, that injects an ethers provider. Besides this, my dapp connects to Infura by default, and then to MetaMask when the user clicks some button. So I want to be able to render some components when MetaMask is being used but not when using Infura (since it's "read-only").

Is this possible? Thanks!

discussion

All 5 comments

The signer has a provider property, but a Signer may have an alternate way to send. So, in theory no, but in practice checking that signer.provider is not null should probably work for most cases. In general, I would hope most people don't need to know this though, and it should be safe to just call signer.sendTransaction; if it cannot send the transaction, it should notify the user in some meaningful way.

The other option is to use the signer.connect(provider) method to connect it to the desired Provider, but things like MetaMask do not support .connect (it will throw).

How are you getting the signer? That process should reveal what you need...

I'm actually going the other way around.

I use useWeb3Context from web3-react, which returns an object that, among other things, has a library property. If web3-react was configured to use ethers.js, then library is an instance of a provider. So I do library.getSigner() to get the signer. This always returns something but it might not be usable.

More specifically, a common pattern I use is to connect by default to Infura and then, if the user clicks a button to connect MetaMask, I switch the connector to MetaMask. In ethers terms, the first case returns a InfuraProvider and the second case returns a JsonRpcProvider. Since (if I understand this correctly) InfuraProvider is a subclass of JsonRpcProvider, the getSigner method is always available. The problem is that when you are using Infura and then try to sign something, it will throw because there's not an available account, obviously.

The web3-react context also gives you an account variable, that might be undefined. So one way to handle this is to "know" if the provider instance came with an associated account. The problem with this is that you need to keep track of two things that aren't that related. Also, you can't do this in a type-safe way, at least without doing a custom wrapper or something like that.

if it cannot send the transaction, it should notify the user in some meaningful way.

With respect to this... not all UIs handle the "read-only" scenario that way. I think it's a pretty common practice to just hide some elements before the user connects 鈥攁t least I've done that many times.

Sorry for the long response! Hopefully this explains my situation better.

Hi @fvictorio! Out of curiosity, what did your approach for this end up looking like?

@jparklev I just make part of the state of the application the fact that the user is connected or not. How you do this depends on your app, of course.

For these purposes I thin the "part of state" makes the most sense, so I'm going to close this now. But please feel free to continue discussion or propose ideas (that don't break the abstraction ethers tries to employ); I monitor closed issues. Or re-open it.

Thanks! :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dev1644 picture dev1644  路  42Comments

bpierre picture bpierre  路  43Comments

Pczek picture Pczek  路  45Comments

MicahZoltu picture MicahZoltu  路  24Comments

Levino picture Levino  路  35Comments