Closed biern closed 6 years ago
I'm also wondering this.
One possibility is to have getAsyncProvider call an FFI function w/ a global variable. (yuck)
Another one is that httpProvider
is String -> Eff e Provider
so it might be possible to use something like an IORef
.
Here's a working example. I'm not fond of the two unsafe calls, but they should be okay.
data HttpProvider
http :: Proxy HttpProvider
http = Proxy
userSetHttpProvider :: Ref String
userSetHttpProvider = unsafePerformEff $ newRef "https://mainnet.infura.io/"
setHttpProvider :: forall e. String -> Eff (ref :: REF | e) Unit
setHttpProvider newProvider = writeRef userSetHttpProvider newProvider
getHttpProvider :: forall e. Eff (ref :: REF | e) String
getHttpProvider = readRef userSetHttpProvider
instance isAsyncHttp :: IsAsyncProvider HttpProvider where
getAsyncProvider = unsafeCoerceWeb3 <<< Web3 <<< liftEff $ httpProvider =<< getHttpProvider
runWeb3_ :: forall e a. Web3 HttpProvider e a -> Aff (eth :: ETH | e) a
runWeb3_ = runWeb3 http
I'm more in favor of something what @XertroV is proposing. Our basic assumption at this point is that in a browser based application you would have little use to dynamically configure the provider because of metamask. As I see it, there are a few possible solutions for dynamic configuration
Ref
Eff
to either Aff
or Web3
, allowing for the possibility of reading an environment variable, reading from a Ref, querying configuration from a another server, etc.We typically use environment variables for all of our configuration, so we haven't really run up against these kinds of problems. How does this sound?
-- Edit To better address the problem, can you describe a situation in which want to dynamically change the provider configuration which is not already handled by metamask, and where you don't have access to environment variables? It would help me understand what we're up against.
Thanks @XertroV for sharing the snippet and @blinky3713 for explaining the motivation behind getAsyncProvider
!
To better address the problem, can you describe a situation in which want to dynamically change the provider configuration which is not already handled by metamask, and where you don't have access to environment variables? It would help me understand what we're up against.
Well, my main use case is just to fallback to HTTPProvider in situations where metamask is not available. Right now I'm storing the provider url just in the app state, but I can easily read it from environment variable as well, so wouldn't be a problem for now.
Seeing how getAsyncProvided
is implemented I was wondering though how would I go about implementing a network switcher for the end user at a later point, similar to what myetherwallet.com does, but @XertroV snippet using REFs answers that question.
Currently in the app that I'm working on I'm maintaining a very limited set of bindings to Web3 and had a considerably different workflow regarding web3 initialization and usage:
So far I had no problems with this approach. I'm not sure which workflow is more correct or reliable.
Just getAsyncProvider
feels a bit hacky. It can only be parametrized by reading state from Eff
and if I read the code correctly is initialized on each web3 call (please correct me if I'm wrong here).
I'd really like to use your library, it looks like a ton of good work. I already tried the contract typings generator and it works great!
The assumption is that you would do something like
data HttpProvider
instance asyncProviderHttp :: IsAsyncProvider HttpProvider where
getAsyncProvider = do
url <- {getEnv "NODE_URL", readRef nodeURL, etc}
httpProvider url
I'm not sure that it's initialized on each web3 call, only if the web3 object isn't defined or you are changing the provider url. see https://github.com/f-o-a-m/purescript-web3/blob/master/src/Network/Ethereum/Web3/Provider.js#L14
I think that unless you need to be able to do something which is not currently possible, or if there is something wrong with the implementation of the way things are now, we're going to probably keep it like this for now. The reason why we want the type level parameterization of the provider is that it will soon be the case that metamask will offer some services that your ethereum client will not, like signing messages for example, and perhaps other things useful for state channels.
Hi! I have a use case, where I would like to parametrize the http provider URL based on a user config. if I understand the code correctly:
runWeb3
requires a provider proxy as a first argument.getAsyncProvider
function implementationgetAsyncProvider
is sort of a provider factory that takes no arguments. If that's correct, how is it possible to create a provider that has a dynamic configuration? (eg. network depends on the application state).