reown-com / appkit-react-native

AppKit SDK for React Native
https://reown.com/appkit
Apache License 2.0
75 stars 20 forks source link

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

Closed ozgurrgul closed 3 days ago

ozgurrgul commented 1 month ago

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):

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]
linear[bot] commented 1 month ago

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

ignaciosantise commented 1 month ago

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",
linear[bot] commented 1 month ago

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

ozgurrgul commented 1 month ago

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

ignaciosantise commented 1 month ago

@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 commented 1 month ago

any news @ozgurrgul ?

ozgurrgul commented 1 month ago

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.

ignaciosantise commented 1 month ago

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?

ozgurrgul commented 1 month ago

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 commented 1 month ago

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

ignaciosantise commented 1 month ago

@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 commented 3 weeks ago

hey @ozgurrgul πŸ‘‹ can you provide a minimal reproducible example?

ozgurrgul commented 2 weeks ago

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 commented 2 weeks ago

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>
  );
};
ignaciosantise commented 1 week ago

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:

ozgurrgul commented 5 days ago

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).

ignaciosantise commented 5 days ago

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

ozgurrgul commented 5 days ago

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

ignaciosantise commented 5 days ago

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

ozgurrgul commented 5 days ago

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?

ignaciosantise commented 5 days ago

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?

ozgurrgul commented 5 days ago

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

image
ignaciosantise commented 5 days ago

@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?

ozgurrgul commented 4 days ago

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:

Now:w

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

ignaciosantise commented 4 days ago

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

ignaciosantise commented 4 days ago

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

So this issue keeps happening?

ozgurrgul commented 3 days ago

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!

ignaciosantise commented 3 days ago

Amazing πŸŽ‰ I'm closing the issue then 🀝