Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WalletConnect Provider #775

Closed
fritzschoff opened this issue Mar 31, 2020 · 32 comments
Closed

Add WalletConnect Provider #775

fritzschoff opened this issue Mar 31, 2020 · 32 comments
Labels
enhancement New feature or improvement.

Comments

@fritzschoff
Copy link

fritzschoff commented Mar 31, 2020

I'm supporting MetaMask and WalletConnect in my Angular 9 DApp. And I was asking myself, is there a way for ethers.js to instantiate a provider/signer which fits the need of WalletConnect?
You need this npm package: walletconnect
And then you can do the following:

this.provider = new WalletConnect({
            bridge: "https://bridge.walletconnect.org",
        });
        // Check if connection is already established
        if (!this.provider.connected) {
            // create new session
            this.provider.createSession().then(() => {
                // get uri for QR Code modal
                const uri = this.provider.uri;
                // display QR Code modal
                WalletConnectQRCodeModal.open(uri, () => {
                    console.log("QR Code Modal closed");
                });
            });

            // Subscribe to connection events
            this.provider.on("connect", (error, payload) => {
                if (error) {
                    throw error;
                }

                // Close QR Code Modal
                WalletConnectQRCodeModal.close();

                // Get provided accounts and chainId
                const { accounts, chainId } = payload.params[0];
            });

            this.provider.on("session_update", (error, payload) => {
                if (error) {
                    throw error;
                }

                // Get updated accounts and chainId
                const { accounts, chainId } = payload.params[0];
            });

            this.provider.on("disconnect", (error, payload) => {
                if (error) {
                    throw error;
                }
                this.web3Store.update({ isConnected: false })
            })
        }

It is a bit annoying to have two "connectors to web3". Would be nice if ethers.js can handle this case.
For instance. React has such a wrapper lib that can work with ethers.js and web3.js web3react
I guess this is the provider they create depending on the lib you are using(ethers.js, web3.js): WalletConnectProvider
I'm not an expert ethers.js so this seems a bit random. But maybe some experienced devs have an idea.

@ricmoo ricmoo added enhancement New feature or improvement. next version (v5) labels Apr 1, 2020
@ricmoo
Copy link
Member

ricmoo commented Apr 1, 2020

I need to look more into Wallet Connect, but this seems like a good idea, adding a WalletConnectSigner. I'll look into it next week. :)

@fritzschoff
Copy link
Author

fritzschoff commented Apr 2, 2020

How to instantiate a provider from walletConnect Docs
Some results after playing around with this npm lib.
Screenshot from 2020-04-02 23-11-22
Screenshot from 2020-04-02 23-11-17

Seems to work, but didn't tested yet

@pedrouid
Copy link

I’d love to help with this... I was actually looking into the Provider documentation to actually make the WalletConnect provider based on ethers instead of web3-provider-engine.

Do you think that would be doable? The reason I’ve depended on web3-provider-engine until now is because it was the most stable solution for web3.js but I wonder if you had success with getting compatibility accross libraries

@fritzschoff
Copy link
Author

@pedrouid I 'm trying to implement your lib into my dapp. web3modal . It works fine with meta mask, but for wallet it is almost like a new instance, cause functions like getSigner() doesn't exist

@pedrouid
Copy link

Have you tried wrapping the @walletconnect/web3-provider with ethers Web3Provider?

Example

import { providers } from "ethers"
import WalletConnectProvider from "@walletconnect/web3-provider"

const provider = new providers.Web3Provider(
  new WalletConnectProvider({
    infuraId: "27e484dcd9e3efcfd25a83a78777cdf1" // Required
  })
)

PS - please use the version 1.0.0-rc.4 for better results

@fritzschoff
Copy link
Author

fritzschoff commented Jun 23, 2020

can't somehow make the web3-provider work since the qr-image lib is throwing an error when I want to serve app. Seems an issue about recent releases. @pedrouid As you can see above I already was able to implement the web3provider from ethers with walletconnect.

@ricmoo
Copy link
Member

ricmoo commented Jun 23, 2020

What is the error? Ethers should certainly not be interfering with a QR code library...

@fritzschoff
Copy link
Author

fritzschoff commented Jun 23, 2020

It's a wallet connect error, not a ethers error. The qr-image module doesn't have the zlib module exported anymore, didn't investigate in that too much

@pedrouid
Copy link

Hey @fritzschoff, there was a report about a weird issue with qrcode-modal from one of the dependencies reported here:
WalletConnect/walletconnect-monorepo#299

I've published 1.0.9 on NPM under the next tag. Could you test if this fixed your issue?

@fritzschoff
Copy link
Author

Nice work!! Thanks, I will test it

@fritzschoff
Copy link
Author

     const walletConnectProvider = new WalletConnectProvider({
        infuraId: infura.id, // Required
        qrcode: true
      });
      await walletConnectProvider.enable();
      this.provider = new providers.Web3Provider(walletConnectProvider)

I'm closing this issue, since it is working like a charm now with the method above.
"@walletconnect/web3-provider": "^1.2.0-alpha.0",
"ethers": "^5.0.8",

@pedrouid
Copy link

Great to hear 🙌 I will go ahead and publish 1.2.0 then

@James-Unicrypt
Copy link

any update on how to get a signer with this approach?

@fritzschoff
Copy link
Author

provider.getSigner()

@EvilJordan
Copy link

EvilJordan commented Sep 26, 2020

My goal is to use ethers (and all my configured keys for that provider's APIs) and the web3modal to connect to walletconnect.
To be clear, one needs to import all of the following to get this to work, right:

  • ethers
  • web3modal
  • web3-provider

My confusion is around the web3-provider package and why it's necessary if ethers is the preferred choice/involved.

@EvilJordan
Copy link

@fritzschoff Did you get ethers working with web3modal? If so, can you post your code? I've been struggling with this for months.

@fritzschoff
Copy link
Author

fritzschoff commented Jan 13, 2021

It has been a while but you should be able to const provider = await web3modal.connect() and this provider variable, you can use with ethers new providers.Web3Providee(provider) . Writing this of the top of my head, so might be a typo here and there. This issue was about wallet connect,no? I had issues with how they bundled their library. If I would used it, I ended up the nodejs modules in the browser which obviously doesn't work. But for that @pedrouid maybe can help you or you check your webpack config, or what ever you are using

@dievardump
Copy link

dievardump commented Aug 28, 2021

Hello :) I've just opened a discussion #1966 about this.

The solution found in this thread forces users to have an infuraId

However, the standalone client already allows things like eth_sendTransaction, signTransaction etc... so I would like to know if it would be possible to actually have a WalletConnect Provider in ethers.js that uses those and completely saves us from the obligation to have a centralized (infura) dependency?

@EvilJordan
Copy link

Super-sad to run into the same problem months later, google, and find myself in the thread 🤪.
For some reason, this code does not use the provided infuraId and, instead, uses the built-in ethers-provided id:

const providerOptions = {
        walletconnect: {
            package: window.WalletConnectProvider.default,
            options: {
                infuraId: 'xxx'
            }
        }
    };

 web3Modal = new window.Web3Modal.default({
      cacheProvider: true,
      providerOptions,
      disableInjectedProvider: false
  });

provider = await web3Modal.connect();
const wallet = new ethers.providers.Web3Provider(provider);

This is using:
ethers-5.5.1
web3modal@1.9.4
walletconnect/web3-provider@1.6.6

@ricmoo
Copy link
Member

ricmoo commented Nov 7, 2021

This seems like an issue with Web3Modal. Is it passing the infuraId along correctly?

@EvilJordan
Copy link

Unclear.
The provided key appears in the web3Modal.providerController.providerOptions.walletconnect.options.infuraId object (as expected), but the resulting provider object from the await web3Modal.connect() call doesn't seem to provide any insight into what's going on.

@EvilJordan
Copy link

I have apparently solved the issue, somehow as I am not seeing any calls out to infura or any other service in my network tab, but everything is working as expected, and quickly. I hate computers.

@Shazambom
Copy link

Shazambom commented Dec 9, 2021

I've also run into this problem and it doesn't seem like any of the above solutions has helped me.

This is my connection code:

const providerOptions = {
    walletconnect: {
        package: WalletConnectProvider,
        options: {
            infuraId: WALLET_CONNECT_API_KEY,
        }
    }
};
const web3Modal = new Web3Modal({
    network: 'mainnet',
    cacheProvider: false,
    disableInjectedProvider: false,
    providerOptions
});
const provider = await web3Modal.connect();
this.provider = new ethers.providers.Web3Provider(provider, "any");

I see the infuraId in the rpc call to infura. I can get the signer from the provider and even the address of the wallet from the signer. But if I try and perform any blockchain operation like getBalance() or getTransactionCount() I get a ton of 401 HTTP errors from https://mainnet.infura.io with the error from ethers being:
PollingBlockTracker - encountered an error while attempting to update latest block: undefined

I get errors when I call functions like this:
await this.provider.getSigner().getBalance().then((bal) => {return parseFloat(ethers.utils.formatEther(bal))}));

I wonder what @EvilJordan's solution was...

Dependencies:
"web3modal": "^1.9.4"
"@walletconnect/web3-provider": "^1.6.6"
"ethers": "^5.5.1"

@EvilJordan
Copy link

EvilJordan commented Dec 9, 2021 via email

@Shazambom
Copy link

I figured it out. I was using the wrong key. I went to infura's website and got a key there and everything worked.

@giovanni-caiazzo
Copy link

Hi all, I was trying to follow this for my React Native project. I have ethers installed with @walletconnect/react-native-dapp. The problem is that @walletconnect/react-native-dapp does not expose the provider that @walletconnect/web3-provider exposes and the rpcUrl field of its connector object is empty. I am stumped, because I have no idea on how to use WalletConnect as a signer with ethers and @walletconnect/web3-provider is not compatible with react native projects because it requires some DOM properties

@shawnmitchell
Copy link

Hi all, I was trying to follow this for my React Native project. I have ethers installed with @walletconnect/react-native-dapp. The problem is that @walletconnect/react-native-dapp does not expose the provider that @walletconnect/web3-provider exposes and the rpcUrl field of its connector object is empty. I am stumped, because I have no idea on how to use WalletConnect as a signer with ethers and @walletconnect/web3-provider is not compatible with react native projects because it requires some DOM properties

I'm using this from a member of DeveloperDAO. It has a bunch of shims and allows me to create a web3-provider instance.

https://github.com/clxyder/walletconnect-expo-example

@giovanni-caiazzo
Copy link

giovanni-caiazzo commented Feb 14, 2022

Thanks, I also found a solution which is a bit different. @walletconnect/web3-provider must be used together with @walletconnect/react-native-dapp so that you can set (example for BSC chain):

const provider = new WalletConnectProvider({
        rpc: {
            56: 'https://bsc-dataseed1.binance.org:443',
        },
        chainId: 56,
        connector: connector,
        qrcode: false,
    });

where connector is the instance passed by @walletconnect/react-native-dapp and qrcode: false is needed because otherwise it tries to call window.document.

Also for expo users: unfortunately to get walletconnect working on Android 11+ you need at least to expo prebuild to add

<queries>
    <intent>
      <action android:name="android.intent.action.VIEW"/>
      <category android:name="android.intent.category.BROWSABLE"/>
      <data android:scheme="https"/>
    </intent>
    <intent>
      <action android:name="android.intent.action.VIEW"/>
      <category android:name="android.intent.category.BROWSABLE"/>
      <data android:scheme="http"/>
    </intent>
    <intent>
      <action android:name="android.intent.action.VIEW"/>
      <category android:name="android.intent.category.BROWSABLE"/>
      <data android:scheme="wc"/>
    </intent>
    <intent>
      <action android:name="android.intent.action.VIEW"/>
      <category android:name="android.intent.category.BROWSABLE"/>
      <data android:scheme="mqtt"/>
    </intent>
    <intent>
      <action android:name="android.intent.action.VIEW"/>
      <category android:name="android.intent.category.BROWSABLE"/>
      <data android:scheme="wamp"/>
    </intent>
  </queries>

Otherwise your app can't see which apps are installed that support wallet connect and can't also send websocket requests (this last part I am not too sure, but at least you need the wc intent)

@shawnmitchell
Copy link

shawnmitchell commented Feb 14, 2022

          const walletConnectProvider = new WalletConnectWeb3Provider({
            infuraId: "ca5bfb223**********ced407f803d",
            chainId: 4,
            connector: connector,
            pollingInterval: 8000
          });
          await walletConnectProvider.enable();
          const provider = new providers.Web3Provider(
            walletConnectProvider
          );
          setSigner(provider.getSigner());

this works for me. setSigner() is setting useState state and I can use that signer to request signatures from metamask in iOS and Android. connector is from useWalletConnect() and providers is import { providers } from 'ethers';

@intergalacticspacehighway

@shawnmitchell @giovanni-caiazzo I tried following what you have done but getting the below error. Have you seen this before?

IMG_441ECAFD003A-1

@Musheer-4screen
Copy link

@intergalacticspacehighway I'm facing the same issue. Did you found any solution?

@shawnmitchell @giovanni-caiazzo I tried following what you have done but getting the below error. Have you seen this before?

IMG_441ECAFD003A-1

@KarthickSakthi
Copy link

The same case I need toimplement in my Dapp . The above is Complex!!.. I need to implement both Metamask connection and WalletConnect Connection using Ether.js.

Need to implement the Provider for Metamask and WalletConnect Dynamically!. if the user Connected via metamask, ether.js provider will be for Metamask and getSigner() too. if user Connected via WalletConnect means now provider in Ether.js will be WalletConnect! Dynamically.

How Do I achieve this using Ether.js??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or improvement.
Projects
None yet
Development

No branches or pull requests