WalletConnect / WalletConnectSharp

A C# implementation of the WalletConnect protocol
Apache License 2.0
143 stars 59 forks source link

Reconnecting to a stopped connection gets the app frozen #145

Closed axenteoctavian closed 2 months ago

axenteoctavian commented 10 months ago

I am trying to reconnect to my last session from the file but if the session is not available anymore the app gets frozen.

Steps to reproduce:

  1. Connect my phone to WC app (by scanning QR)

  2. Close WC app

  3. Stop connection from phone

  4. Start WC app again At start-up I'm doing some stuff: call init and subscribe to session_delete event

    _client = await WalletConnectSignClient.Init(_dappOptions);
    _client.On("session_delete", delegate ()
    {
    //...
    });

    -> This step will reconnect to my last saved session

  5. After few seconds the event is triggered

  6. Right after this my WC app gets frozen for few seconds. I suppose some background task is blocking the flow.

Do you have any idea what the error might be?

Thank you!

skibitsky commented 10 months ago

Hello,

It may have been fixed, or your reconnection steps differ. Can you share more about your reconnection method or upgrade WalletConnectSharp?

This is the code I used to

Client = await WalletConnectSignClient.Init(_clientOptions);                                             

// From v2.1.3 we use EventHandlers instead of WalletConnectSharp.Events, 
// Therefore the syntax is different than in your code snippet.
// For me this event is only triggered when wallet kills connection while dapp is running.                                                                        
Client.SessionDeleted += (sender, session) => { WCLogger.Log($"Session deleted. Topic: {session.Topic}"); };

var sessions = Client.Find(_connectOptions.RequiredNamespaces);                                          

if (sessions.Length > 0)                                                                                 
{                                                                                                        
    Session = sessions.First(x => x.Acknowledged ?? false);                                              
}                                                                                                        
else                                                                                                     
{                                                                                                        
    _connectedData = await Client.Connect(_connectOptions);                                              
    // ...                                                            
}                                                                                                        
axenteoctavian commented 9 months ago

Hi @skibitsky, sorry for the late response.

I tried you syntax and WC version 2.1.6 and I have the same broken state if I follow my steps.

I see in your comments that "event is only triggered when wallet kills connection while dapp is running" and this is working fine for me also. My problem is when dapp closed -> wallet kills connection -> dapp open (reconnect) -> SessionDeleted event triggered => FROZEN.

Thank you! 😀

skibitsky commented 9 months ago

@axenteoctavian how exactly do you restore session after dapp restart?

axenteoctavian commented 9 months ago

@axenteoctavian how exactly do you restore session after dapp restart?

@skibitsky here is the code snippet:

_client = await WalletConnectSignClient.Init(_dappOptions);
_client.SessionDeleted += (sender, session) =>
{
    Address = string.Empty;
};

if (_client.Find(_dappConnectOptions.RequiredNamespaces).Length > 0)
{
    _walletConnectSession = _client.Find(_dappConnectOptions.RequiredNamespaces)[0];

  var selectedNamespace = _walletConnectSession.Namespaces[WALLETCONNECT_MULTIVERSX_NAMESPACE];
  if (selectedNamespace != null && selectedNamespace.Accounts.Length > 0)
  {
      var currentSession = selectedNamespace.Accounts[0];
      var parameters = currentSession.Split(':');
      Address = parameters[2];
  }
}
else 
{
   _walletConnectSession = await _walletConnect.Approval;
   //...
}

My full code is open source (using the old events) My DApp: https://github.com/RemarkableTools/Mx.NET.Examples/blob/dbc90af9778bfd86027cfb955e1d47c193ccdf7a/examples/WinForms/MainForm.cs#L68

My interface SDK: https://github.com/RemarkableTools/Mx.NET.SDK.WalletProviders/blob/d8379b7f4ac63a3bc81393a046b88973516f3c04/src/Mx.NET.SDK.WalletConnect/WalletConnectGeneric.cs#L84

axenteoctavian commented 2 months ago

Hello @skibitsky! Can you please help with this issue, it is very important for me. Thank you!

skibitsky commented 2 months ago

Hello @axenteoctavian,

Would it be possible for you to upgrade to the latest version of WalletConnectSharp? We have shipped numerous fixes and improvements over the past 6+ months.

Additionally, we have introduced the AddressProvider utility to help you keep track of the active account, simplifying your code.

axenteoctavian commented 2 months ago

Hi @skibitsky, thank you for the answer. I just tested yesterday the last version of the SDK but the same problem occurs (reconnecting to a stopped connection gets the app frozen). Regarding the AddressProvider, I will check that out. :smiley:

skibitsky commented 2 months ago

Do you have a sample project that uses the latest version?

axenteoctavian commented 2 months ago

I just updated my projects. Here is the application where I try to reconnect: https://github.com/RemarkableTools/Mx.NET.Examples/blob/c0dbdd7f0d786f037766257f17ac85eac0122853/examples/WinForms/MainForm.cs#L73 And here is my SDK built on top of WalletConnectSharp: https://github.com/RemarkableTools/Mx.NET.SDK.WalletProviders/blob/faf2cbcbe745f13b8844cec2264c3e401bf3529b/src/Mx.NET.SDK.WalletConnect/WalletConnectGeneric.cs#L98

All works as expected it's reconnecting to the last connection. But then realizes the connection was interrupted and the SessionDelete is triggered in Engine.cs async Task IEnginePrivate.OnSessionDeleteRequest(string topic, JsonRpcRequest<SessionDelete> payload), after this my app gets frozen, probably some thread is stuck or something.

skibitsky commented 2 months ago

What wallet do you use for testing?

axenteoctavian commented 2 months ago

It's xPortal application from MultiversX

skibitsky commented 2 months ago

How long does it take for the app to freeze after reconnecting? It doesn't happen on my end.

What I tried so far:

  1. I run your WinForms app locally from the IDE
  2. Generate QR code
  3. Scan the QR code with our React sample wallet (need to enable testnets in the settings)
  4. In the wallet: approve connection, sign a message
  5. Restart the app, see green Wallet connection restored message. It doesn't crash.
axenteoctavian commented 2 months ago

Thank you for taking the time to test this. :pray:

You reconnect to a good connection. From step 4 try this:

  1. Stop the WinForms
  2. Stop the connection from the app
  3. Start the WinForms -> here should try to reconnect to the stopped connection (the one from storage), then SessionDelete should be triggered and here is where the app freezes
skibitsky commented 2 months ago

WalletConnectSharp utilizes multithreading, and there is no guarantee that events will be triggered on the main thread. Accessing WinForms UI elements from the OnSessionDeleteEvent method may be the issue. Typically, UI elements can only be accessed from the main thread.

I logged Environment.CurrentManagedThreadId in your code, and as you can see, OnSessionDeleteEvent is triggered on another thread. image

axenteoctavian commented 2 months ago

Hmm, I see... fixed it. Thank you @skibitsky! 🙏