walletconnect-monorepo icon indicating copy to clipboard operation
walletconnect-monorepo copied to clipboard

QR code modal doesnt open after closing once

Open anoushk1234 opened this issue 2 years ago • 10 comments

Same as #243 after provider.enable() if user clicks on the x and closes the modal it doesnt open again, someone claims to hv fixed it in the above issue and closed it but it still persists and no one has bothered to look at the replies and open it again, please fix this it's terrible UX there are more issues opened with same problem #538

Even a site such as OpenSea faces the same issue, here im attaching a screenshot image

anoushk1234 avatar Feb 05 '22 12:02 anoushk1234

Same problem here

pauloreis7 avatar Feb 24 '22 19:02 pauloreis7

I posted a workaround for the @walletconnect/core and @walletconnect/qrcode-modal packages but could likely be applied to the provider if you can find a reference to _qrcodeModal from core on the provider instance.

https://github.com/WalletConnect/walletconnect-monorepo/issues/538#issuecomment-1068628023

0x62 avatar Mar 16 '22 15:03 0x62

+1

swaxtic avatar Mar 31 '22 11:03 swaxtic

+2

Loque18 avatar Apr 24 '22 07:04 Loque18

+3

jamesonnuss avatar May 19 '22 06:05 jamesonnuss

@anoushk1234 @swaxtic @Loque18 @jamesonnuss I came up with a workaround for this that uses import WalletConnectProvider from '@walletconnect/web3-provider'

There are a few parts to this...

First I made a small getter for the provider so I could reference the instance throughout my app(the modal_closed event listener is important here):

import WalletConnectProvider from '@walletconnect/web3-provider'

// Get the WalletConnectProvider instance if already instantiated, otherwise instantiate it and return it
let walletConnectProvider: WalletConnectProvider
export let shouldForceModalOpen: boolean = false

export const getWalletConnectProvider: () => WalletConnectProvider = () => {
    if (!walletConnectProvider) {
        walletConnectProvider = new WalletConnectProvider({
            infuraId: `YOUR INFURA ID`,
	})

        // Listen for the QR Code Modal's 'modal_closed' event (I found it when looking here: https://github.com/WalletConnect/walletconnect-monorepo/blob/7573fa9e1d91588d4af3409159b4fd2f9448a0e2/packages/providers/web3-provider/src/index.ts#L222)
	walletConnectProvider.wc.on('modal_closed', () => {
	    shouldForceModalOpen = true
	    console.log('QR Code Modal closed')
	})
    }

    return walletConnectProvider
}

Then I added this to the top level of my app to check if the user is already connected so I can persist their session across page refreshes(if they're not connected, they'll need to click a 'Connect Wallet Client' button I added to the header):

const provider = await getWalletConnectProvider()
if (provider.connector._connected) {
    // Load account data and populate wallet/evm stores
    await loadAccountData()
}

This is the callback for the Connect Wallet Client button that's shown in the header if the user is not already connected:

import { shouldForceModalOpen, getWalletConnectProvider, loadAccountData } from '$lib/wallet/utils'

const handleConnectWalletClient: () => Promise<void> = async () => {
    if (shouldForceModalOpen) {
        const provider = getWalletConnectProvider()
        // This is the code to manually re-open the QR Code Modal if it has already been closed
	provider.qrcodeModal.open(provider.connector.uri, { bridge: provider.bridge })
    }

    // Load account data and populate wallet/evm stores
    await loadAccountData()
}

Lastly, this is a bit of code where you can call provider.enable() and populate any stores or anything you need to:

export const loadAccountData: () => Promise<void> = async () => {
    try {
        // Get WalletConnectProvider
	const walletConnectProvider = getWalletConnectProvider()
	await walletConnectProvider.enable()

	// I'm using ethers in my app, but I put the web3js code here to be consistent with the WalletConnect docs
        const web3Provider = new providers.Web3Provider(walletConnectProvider);
        
        // Do anything else you need to, such as populating stores, etc... 
    } catch (error) {
        console.error(error)
    }
}

I came across this issue while I was implementing WalletConnect today and couldn't find any workarounds for it online, so hopefully this helps other people who are also dealing with it 👌🏼

avivash avatar May 25 '22 23:05 avivash

@avivash being annoyed with this for some time! now it works!

thanks!

version => @walletconnect/[email protected]

paro-paro avatar Jun 15 '22 16:06 paro-paro

+4

goncharov-vlad avatar Sep 08 '22 14:09 goncharov-vlad

Hi there,I have a pretty simple workround,just need css and jquery(or js),here is my workround: I use Vue3 in my project,code screenshot: image There is a sign in button in my page,when I click sign in button,signInflag is set to true,and then trigger this watch function:

  1. It must be delayed,settimeout is important, 500ms is enough, otherwise walletconnect-wrapper will not be added to the dom walletconnect-wrapper is : image
  2. create a closeBtn,the style of it is from original walletconnect close button image
  3. and appent to header,override the original close button image
  4. bind a click event to closeBtn,because of closeBtn is a dynamic element,you must to use $().on('click',()=>{}) image
  5. and then set signInFlag to false,in order to trigger watch function next time.

Full code is here:

watch(() => signInflag.value, (newValue) => {
  if (newValue) {
    setTimeout(() => {
      $('#walletconnect-wrapper').css({ 'z-index': '99999999999999', 'opacity': '1' })
      let closeBtn = '<div id="closeQrcodeModalBtn" style="opacity:0;z-index:999999;position: absolute;top: 0px;right: 0px;background: white;border-radius: 26px;padding: 6px;box-sizing: border-box;width: 26px;height: 26px;cursor: pointer; "></div>'
      $('.walletconnect-modal__header').append(closeBtn)
      $('#closeQrcodeModalBtn').on('click', () => {
        $('#walletconnect-wrapper').css({ 'z-index': '-1', 'opacity': '0' })
        signInflag.value = false;
      })
    }, 500);
  }
})

There is no problem with my use, it can be solved perfectly, no complicated js is needed at all, although it is a bad hack, but until the official solution of walletconnect, it can be regarded as a feasible solution, I hope it can help friends who encounter the same problem .

Himawarinoyakusoku avatar Sep 19 '22 06:09 Himawarinoyakusoku

Just recreate WalletConnect instance with catch

private createWalletConnect() {
    const walletConnect = new WalletConnect({
      bridge: 'https://bridge.walletconnect.org',
      qrcodeModal: QRCodeModal,
    });

    walletConnect.on('connect', this.onConnect);
    walletConnect.on('disconnect', this.onDisconnect);
    walletConnect.on('session_update', (_, payload) => this.onSessionUpdate(payload));

    return walletConnect;
  }

connect() {
    if (this.wallet) {
      throw new Error('Wallet is already connected');
    }

    this.walletConnect
      .connect()
      // Reopening WalletConnect modal doesn't work
      // Workaround: https://github.com/Uniswap/web3-react/issues/124#issuecomment-817631654
      .catch(() => { this.walletConnect = this.createWalletConnect(); });
  }

goncharov-vlad avatar Sep 19 '22 10:09 goncharov-vlad

Seems like combining these two is a better fix:

  • https://github.com/Uniswap/web3-react/issues/124#issuecomment-817631654
  • https://github.com/Uniswap/web3-react/issues/124#issuecomment-984882534

hantuzun avatar Dec 12 '22 20:12 hantuzun

@anoushk1234 is this still an issue after trying @goncharov-vlad solution?

finessevanes avatar Jan 13 '23 04:01 finessevanes

@anoushk1234 is this still an issue after trying @goncharov-vlad solution?

havent tried it out but it if it's working then that's great

anoushk1234 avatar Feb 20 '23 17:02 anoushk1234

const isRequestActive: Ref<UnwrapRef> = ref(false); if (isRequestActive.value) { console.warn("NEW A request is already active. Please wait."); return; }

console.log('if AFTER', );

try {
    // Example: Requesting account access
    const accounts = await (window.ethereum as any)?.request({ method: 'eth_requestAccounts' }).then((account) => console.log('account', account)).catch((error: unknown) => console.error('error', error)).finally(() => console.log('finally', ));
    // Proceed with additional actions like showing balance, switching chains, etc.
    console.log('NEW accounts', accounts);
    isRequestActive.value = true;
} catch (error) {
    console.error("NEW Error interacting with MetaMask:", error);
    // Handle error appropriately
    isRequestActive.value = false;
} finally {
    console.log('NEW finally isRequestActive.value', isRequestActive.value);
    isRequestActive.value = false;
}
console.log('metaMaskCall end', );

For catching error here the magic is done in this line of code above: 

const accounts = await (window.ethereum as any)?.request({ method: 'eth_requestAccounts' }).then((account) => console.log('account', account)).catch((error: unknown) => console.error('error', error)).finally(() => console.log('finally', ));

We caught this error in .catch method of request.

this code is for Vue 3 with typescript

TetianaMolchanova avatar Feb 28 '24 18:02 TetianaMolchanova