web3modal-react-native icon indicating copy to clipboard operation
web3modal-react-native copied to clipboard

Excessive 'MyApp wants to open ...' dialogs displayed during wallet selection (iOS)

Open ozgurrgul opened this issue 1 year ago • 11 comments

Describe the bug During wallet selection, sometimes 'MyApp wants to open ...' dialog shown excessive times. This doesn't happen always.

SDK Version (if relevant)

"@tanstack/react-query": "^5.52.2",
"@walletconnect/react-native-compat": "2.15.1",
"@web3modal/wagmi-react-native": "^2.0.2",
"wagmi": "^2.12.7",
"@react-native-community/netinfo": "6.0.0",
"react-native-get-random-values": "^1.11.0",

To Reproduce Steps to reproduce the behavior:

  1. Go to 'WalletConnect'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior It should only show dialog once

Screenshots

Smartphone (please complete the following information):

  • Device: iPhone
  • OS: 17

Additional context This problem occurs when we call web3Modal.open({ view: 'Connect' }); method and rest is handled by WalletConnect. Problem can be seen in the video:

https://github.com/user-attachments/assets/9abdcf8a-5503-40d5-9793-aacfbe06ae32

WalletConnectProvider.tsx:

import { WagmiProvider } from 'wagmi';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createWeb3Modal, defaultWagmiConfig, Web3Modal } from '@web3modal/wagmi-react-native';
import React, { ReactNode } from 'react';
import { WALLET_CONNECT_PROJECT_ID } from '~/shared/environment';
import { mainnet, polygon, bsc, avalanche } from '@wagmi/core/chains';

const SUPPORTED_CHAIN_CONFIGS = [mainnet, polygon, bsc, avalanche] as const;
export const WALLET_CONNECT_METADATA: ConfigOptions['metadata'] = {
  name: 'Bitvavo',
  description: 'Connect your wallet',
  url: 'https://bitvavo.com/',
  icons: ['https://bitvavo.com/press/blue/bitvavo-mark/bitvavo-mark-blue.png'],
  redirect: {
    native: `${NAVIGATION_SCHEMA}://`
  }
};

const queryClient = new QueryClient();

const wagmiConfig = defaultWagmiConfig({
  chains: SUPPORTED_CHAIN_CONFIGS,
  projectId: WALLET_CONNECT_PROJECT_ID,
  metadata: WALLET_CONNECT_METADATA
});

createWeb3Modal({
  projectId: WALLET_CONNECT_PROJECT_ID,
  wagmiConfig,
  enableAnalytics: false
});

export const WalletConnectProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  return (
    <WagmiProvider config={wagmiConfig}>
      <QueryClientProvider client={queryClient}>
        {children}
        <Web3Modal />
      </QueryClientProvider>
    </WagmiProvider>
  );
};

WalletConnect.tsx;

import React from 'react';
import { Web3Modal } from '@web3modal/wagmi-react-native';
import { Steps } from '../ui/Steps';
import { WalletConnectProvider } from './WalletConnectProvider';
import { useWalletConnectConnectionManager } from './useWalletConnectConnectionManager';

const WalletConnectInner = () => {
  const {
    open,
    isConnected,
    disconnect: wcDisconnect,
    sign: wcSign,
    address,
    loading
  } = useWalletConnectConnectionManager();


  const sign = async () => {
    if (!address) return;
    const signature = await wcSign();
    if (!signature) return;
    // omitted
  };

  const disconnect = () => {
    wcDisconnect();
  };

  const getContent = () => {
    if (loading) {
      return <Steps.Loading />;
    }
    if (isConnected) {
      return <Steps.Connected onPressOpenWallet={sign} onPressDisconnect={disconnect} />;
    }

    return <Steps.NotConnected onPressOpenWallet={open} />;
  };

  return (
    <WalletConnectProvider>
      {getContent()}
      <Web3Modal />
    </WalletConnectProvider>
  );
};

export const WalletConnect = () => {
  return (
    <WalletConnectProvider>
      <WalletConnectInner />
    </WalletConnectProvider>
  );
};

useWalletConnectConnectionManager.ts:

import { useWeb3Modal } from '@web3modal/wagmi-react-native';
import { useDisconnect, useAccount, useSignMessage } from 'wagmi';

export const useWalletConnectConnectionManager = () => {
  const web3Modal = useWeb3Modal();
  const mDisconnect = useDisconnect();
  const account = useAccount();
  const { signMessageAsync } = useSignMessage();
  const { isConnected } = account;
  const selectedChain = account.chain;

  const open = () => {
    web3Modal.open({ view: 'Connect' });
  };

  const disconnect = () => {
    mDisconnect.disconnect();
  };

  const sign = async () => {
    try {
      const sig = await signMessageAsync({ message: 'Test' });

      return sig;
      // eslint-disable-next-line no-empty
    } catch (e) {
      return null;
    }
  };

  return {
    isConnected,
    loading: account.isConnecting || account.isReconnecting,
    selectedChain,
    address: account.address,
    open,
    disconnect,
    sign
  };
};

Some logs appearing in case it helps:

Warning: Encountered two children with the same key, `f2436c67184f158d1beda5df53298ee84abfc367581e4505134b5bcf5f46697d:e9ff15be73584489ca4a66f64d32c4537711797e30b6660dbcb71ea72a42b1f4:bc949c5d968ae81310268bf9193f9c9fb7bb4e1283e1284af8f2bd4992535fd6:ef333840daf915aafdc4a004525502d6d49d77bd9c65e0642dbaefb3c2893bef`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version. 
Warning: Encountered two children with the same key, `9414d5a85c8f4eabc1b5b15ebe0cd399e1a2a9d35643ab0ad22a6e4a32f596f0:84b43e8ddfcd18e5fcb5d21e7277733f9cccef76f7d92c836d0e481db0c70c04:18450873727504ae9315a084fa7624b5297d2fe5880f0982979c17345a138277:fd20dc426fb37566d803205b19bbc1d4096b248ac04548e3cfb6b3a38bd033aa`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.  
  
Task orphaned for request <NSMutableURLRequest: 0x305be9d80> { URL: data:image/webp;base64,UklGRsgQAABXRUJQVlA4ILwQAABQcgCdASqQAZABPkkkjkUioiEUKXx8KASEs7d4BNpW9CZkpB8Z9W19e3P8zgHpdMFzoj0P+ ... AAAAAAA= }
Task orphaned for request <NSMutableURLRequest: 0x305be9bc0> { URL: data:image/webp;base64,UklGRlQUAABXRUJQVlA4IEgUAABwdgCdASqQAZABPkkkkUWioiITC0QoKASEsrdz2QUiPEDmJQwum5L8xoKMRfc6pY9h+YHv+ ... F7AAAA== }
Task orphaned for request <NSMutableURLRequest: 0x305be9bb0> { URL: data:image/webp;base64,UklGRiIIAABXRUJQVlA4WAoAAAAQAAAAjwEAjwEAQUxQSMEEAAABoATb2uI2+lrdGZLkckvtMCdaucIsexVTOHGytIMqr1OcK ... AAAAAAA= }
Task orphaned for request <NSMutableURLRequest: 0x305be9b80> { URL: data:image/webp;base64,UklGRjYRAABXRUJQVlA4ICoRAAAQYgCdASqQAZABPkkkkUWioiGSKjQ0KASEsrd+M/y3Yz9adfKhid/4j+4/tn4jlJO2f2T9r ... AAAAAA== }
 
[MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 disconnect listeners added. Use emitter.setMaxListeners() to increase limit]

ozgurrgul avatar Sep 16 '24 11:09 ozgurrgul

hey @ozgurrgul 👋 can you check if upgrading this solves the issue?

"@walletconnect/react-native-compat": "2.16.1",
"@web3modal/wagmi-react-native": "2.0.4",
"wagmi": "2.12.11",

ignaciosantise avatar Sep 16 '24 17:09 ignaciosantise

I bumped the versions as instructed but unfortunately the same issue still persists when I test.

ozgurrgul avatar Sep 16 '24 18:09 ozgurrgul

@ozgurrgul Okey, can you check having just one Web3Modal component? If you want to use the modal in two or more views, you should put it in the root view of your app.

I see you use Web3Modal component in WalletConnectProvider.tsx and in WalletConnect.tsx.

Removing it from WalletConnect should be enough

ignaciosantise avatar Sep 16 '24 18:09 ignaciosantise

any news @ozgurrgul ?

ignaciosantise avatar Sep 18 '24 15:09 ignaciosantise

hi @ignaciosantise, good catch I didn't notice WalletConnectProvider was used in 2 place

I moved WalletConnectProvider to our root, this issue still continues.

I also tried using W3mButton only to see if it solves, but still same.

Interesting things is this issue only happen on our prod build and not locally. I am not able to replicate the issue on our developer build in the same phone.

Also, this issue doesn't happen for every wallet. For example for Trust Wallet/Metamask I don't see this issue but for Rainbow/OKX it happens every time.

ozgurrgul avatar Sep 19 '24 15:09 ozgurrgul

okey, it's really weird. I cannot reproduce on our sample apps from Testflight. Does it also happen on Android? Which version of react native are you using?

ignaciosantise avatar Sep 19 '24 16:09 ignaciosantise

We are using RN 0.72.13. (Unfortunately I am not able to test on Android since I don't have a test device currently, but I will try to test tomorrow and let you know)

ozgurrgul avatar Sep 19 '24 21:09 ozgurrgul

I am not able to reproduce this issue on Android (at least for Rainbow wallet case).

ozgurrgul avatar Sep 23 '24 07:09 ozgurrgul

@ozgurrgul could you create a minimal reproducible example? So i can try to reproduce it locally.

Can you also add a log here? That code should be executed once, but it seems it's entering in a loop 🤔

ignaciosantise avatar Sep 23 '24 13:09 ignaciosantise

hey @ozgurrgul 👋 can you provide a minimal reproducible example?

ignaciosantise avatar Oct 17 '24 18:10 ignaciosantise

HI @ignaciosantise, sorry I was AFK due to to personal reasons.

could you create a minimal reproducible example? So i can try to reproduce it locally. I have tried to create a reproducible example and I wasn't able to repro the issue

Can you also add a log here?

I might be able to, but it's just we build our app on CI, so I will need to build locally which I don't have access to signing certificates, but I will give it a try. Since this issue is only happening on our prod build it's hard to debug.

ozgurrgul avatar Oct 25 '24 10:10 ozgurrgul

Apart from that there is another issue that is preventing me to debug above.

We noticed that, recently when a user selects Trust wallet or any other wallet from the list, the wallet doesn't open to initiate a connection. Or when you open the wallet manually, it doesn't have any indication of WC connection too, so it gets stuck on ConnectingView. Try again button doesn't work as well.

I put a log here since I am able to repro locally:

image image image

So it seems await ConnectionController.state.wcPromise; waits indefinitely? and console.log("initializeConnection 3") doesn't get called into logs hence it doesn't continue to execute in the codeblock.

Is it possible to check this too? If you want, I can also create separate bug ticket.

"wagmi": "2.12.11",
"@walletconnect/react-native-compat": "2.17.1",
"@reown/appkit-wagmi-react-native": "1.0.2",

Video:

https://github.com/user-attachments/assets/2c3073c7-61af-491c-b7c7-45e94f9a0346

import { WagmiProvider } from 'wagmi';
import { mainnet } from '@wagmi/core/chains';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createAppKit, defaultWagmiConfig, AppKit, AppKitButton } from '@reown/appkit-wagmi-react-native';
import { ReactNode } from 'react';
import { WALLET_CONNECT_PROJECT_ID } from '~/shared/environment';
import { WALLET_CONNECT_METADATA } from '~/store/addressBook/web3/AddressBookWeb3Constants';

const queryClient = new QueryClient();

const chains = [mainnet] as const;

const wagmiConfig = defaultWagmiConfig({
  chains,
  projectId: WALLET_CONNECT_PROJECT_ID,
  metadata: WALLET_CONNECT_METADATA
});

createAppKit({
  projectId: WALLET_CONNECT_PROJECT_ID,
  wagmiConfig,
  enableAnalytics: false
});

export const WalletConnectProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  return (
    <WagmiProvider config={wagmiConfig}>
      <QueryClientProvider client={queryClient}>
        {children}
        <AppKit />
        <AppKitButton />
      </QueryClientProvider>
    </WagmiProvider>
  );
};

ozgurrgul avatar Oct 25 '24 10:10 ozgurrgul

hey @ozgurrgul 👋 sorry for the delay. Can you check if the QR code is generated? Open the modal -> All Wallets -> QR Code button at top right. Because i think you have an issue when trying to generate the connection uri

Some questions:

  • Does WALLET_CONNECT_PROJECT_ID contain the project id? can you check that is not null?
  • Did you add any bundle_id in your Cloud dashboard?

ignaciosantise avatar Oct 31 '24 17:10 ignaciosantise

Does WALLET_CONNECT_PROJECT_ID contain the project id? can you check that is not null?

It contains the correct project id (otherwise, WC doesn't show any wallets).

Did you add any bundle_id in your Cloud dashboard?

Yes, we have 3 bundle ids added in the Reown dashboard (for prod, staging, dev).

ozgurrgul avatar Nov 04 '24 08:11 ozgurrgul

@ozgurrgul if you go to the QR view, does the code load?

ignaciosantise avatar Nov 04 '24 14:11 ignaciosantise

@ignaciosantise It's hanging on loading/blinking state and QR code doesn't load

ozgurrgul avatar Nov 04 '24 14:11 ozgurrgul

@ozgurrgul okey, then the issue is when trying to connect to the socket.

  • Do you see any error related to sockets?
  • Are you using a VPN? if so, can you check turning it off?
  • Can you create a new project id and test? (without setting bundle ids)

ignaciosantise avatar Nov 04 '24 15:11 ignaciosantise

  1. No I don't see any socket issues (at least not visible in console or screen)

  2. No VPN

  3. Oh wow It actually works with a brand new project id! what could be the issue here?

  • Trustwallet opens (buttons working)

ozgurrgul avatar Nov 04 '24 17:11 ozgurrgul

okey good, it might be related to the bundleIds validation. Can you go to your original Cloud project and add the bundleIds in the allowed domains list?

ignaciosantise avatar Nov 04 '24 17:11 ignaciosantise

Adding bundle ids to domain list like this? Yes it worked for the original project

image

ozgurrgul avatar Nov 04 '24 17:11 ozgurrgul

@ozgurrgul Amazing! The Cloud team is already aware of this issue, i'll ping them again. But this workaround will make your project work 🤝

Guess we can close the issue?

ignaciosantise avatar Nov 04 '24 17:11 ignaciosantise

Guess we can close the issue?

Unfortunately we can't yet, it seems.

So there are 2 different issues:

  1. Excessive amount of redirections to TrustWallet etc (the original issue)
  2. When a user selects TrustWallet etc from the list, the app doesn't respond

The above domain workaround only fixed second item (and the original issue is now visible and still persists). The fix also introduces another issue for our prod builds, which walletConnect list is empty:

WhatsApp Image 2024-11-04 at 23 12 07

So, to summary, when we add the domain from dashboard, the the issue:

  • We can click on the TrustWallet or any other wallet and it works
  • I was able to interact with TrustWallet and it still tried to open it too many times

Now:w

  • After the dashboard fix, wallet list is empty in our prod build or local development which there is no wallet to click. There was initially wallets visible, but now I can't see any wallet item anymore

Relevant log: WhatsApp Image 2024-11-05 at 00 21 58

ozgurrgul avatar Nov 04 '24 23:11 ozgurrgul

@ozgurrgul the wallet list should be solved now, we had an issue yesterday -> https://status.reown.com/incidents/n059gtnp0jvs

ignaciosantise avatar Nov 05 '24 15:11 ignaciosantise

I was able to interact with TrustWallet and it still tried to open it too many times

So this issue keeps happening?

ignaciosantise avatar Nov 05 '24 15:11 ignaciosantise

Ah I see, that timing of the incident was very coincident.

So this issue keeps happening?

I checked our build and the issue seem to be disappeared. Thanks for all the help!

ozgurrgul avatar Nov 06 '24 09:11 ozgurrgul

Amazing 🎉 I'm closing the issue then 🤝

ignaciosantise avatar Nov 06 '24 13:11 ignaciosantise