fix: Better handle expired session and auth data for walletconnect (#3228)

* fix: Better handle expired session and auth data for walletconnect

* fix: handle dApp disconnected sessions, reflecting the state locally

* Update lib/src/screens/wallet_connect/services/walletkit_service.dart [skip ci

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
David Adegoke
2026-05-20 18:22:07 +02:00
committed by GitHub
co-authored by Omar Hatem
parent c684318373
commit d325ece6ea
@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:eth_sig_util/util/utils.dart';
import 'package:flutter/material.dart';
@@ -149,6 +150,9 @@ abstract class WalletKitServiceBase with Store {
_refreshPairings();
sessions.clear();
auth.clear();
final newSessions = _walletKit.sessions.getAll();
sessions.addAll(newSessions);
@@ -185,12 +189,16 @@ abstract class WalletKitServiceBase with Store {
final isOnline = _walletKit.core.connectivity.isOnline.value;
if (!isOnline) {
await Future.delayed(const Duration(milliseconds: 500));
_emitEvent();
Future<void> _emitEvent({int retries = 0}) async {
final isOnline = _walletKit.core.connectivity.isOnline.value;
if (!isOnline && retries < 3) {
await Future.delayed(const Duration(milliseconds: 500));
await _emitEvent(retries: ++retries);
return;
}
final sessions = _walletKit.sessions.getAll();
for (var session in sessions) {
final engineSessions = _walletKit.sessions.getAll();
for (var session in engineSessions) {
final chainKeys = walletKeyService.getKeysForChain(appStore.wallet!);
for (var chain in chainKeys) {
for (var chainID in chain.chains) {
@@ -200,13 +208,12 @@ abstract class WalletKitServiceBase with Store {
namespaces: session.namespaces,
);
if (events.contains('accountsChanged')) {
final chainKeys = walletKeyService.getKeysForChain(appStore.wallet!);
_walletKit.emitSessionEvent(
await _walletKit.emitSessionEvent(
topic: session.topic,
chainId: chainID,
event: SessionEventParams(
name: 'accountsChanged',
data: [chainKeys.first.publicKey],
data: [chain.publicKey],
),
);
}
@@ -215,6 +222,7 @@ abstract class WalletKitServiceBase with Store {
try {
await deletePairing(topic: session.pairingTopic);
} catch (_) {}
sessions.removeWhere((s) => s.topic == session.topic);
_refreshPairings();
}
} catch (_) {}
@@ -242,6 +250,10 @@ abstract class WalletKitServiceBase with Store {
_walletKit.core.pairing.onPairingDelete.unsubscribe(_onPairingDelete);
_walletKit.core.pairing.onPairingExpire.unsubscribe(_onPairingDelete);
sessions.clear();
auth.clear();
pairings.clear();
isInitialized = false;
}
@@ -511,23 +523,57 @@ abstract class WalletKitServiceBase with Store {
@action
Future<void> deletePairing({required String topic}) async {
final topicSessions = sessions.where((element) => element.pairingTopic == topic);
final topicSessions =
sessions.where((element) => element.pairingTopic == topic).toList();
await _walletKit.core.pairing.disconnect(topic: topic);
for (var session in topicSessions) {
await _walletKit.disconnectSession(
topic: session.topic,
reason: Errors.getSdkError(Errors.USER_DISCONNECTED).toSignError(),
);
try {
await _walletKit.disconnectSession(
topic: session.topic,
reason: Errors.getSdkError(Errors.USER_DISCONNECTED).toSignError(),
);
} catch (_) {}
}
await _removePairingTopicFromLocalStorage(topic);
sessions.clear();
sessions.addAll(_walletKit.sessions.getAll());
_refreshPairings();
}
@action
Future<void> disconnectSession({required String topic}) async {
await walletKit.disconnectSession(
topic: topic,
reason: Errors.getSdkError(Errors.USER_DISCONNECTED).toSignError(),
);
String? pairingTopic;
for (final s in sessions) {
if (s.topic == topic) {
pairingTopic = s.pairingTopic;
break;
}
}
pairingTopic ??= _walletKit.sessions.get(topic)?.pairingTopic;
try {
await walletKit.disconnectSession(
topic: topic,
reason: Errors.getSdkError(Errors.USER_DISCONNECTED).toSignError(),
);
} catch (e) {
printV('disconnectSession: $e');
}
sessions.clear();
sessions.addAll(_walletKit.sessions.getAll());
if (pairingTopic != null &&
!_walletKit.sessions.getAll().any((s) => s.pairingTopic == pairingTopic)) {
await _removePairingTopicFromLocalStorage(pairingTopic);
try {
await _walletKit.core.pairing.disconnect(topic: pairingTopic);
} catch (_) {}
}
_refreshPairings();
}
@action
@@ -637,6 +683,17 @@ abstract class WalletKitServiceBase with Store {
return jsonList.map((item) => item as String).toList();
}
Future<void> _removePairingTopicFromLocalStorage(String pairingTopic) async {
final key = getKeyForStoringTopicsForWallet();
if (key.isEmpty) return;
final topics = getPairingTopicsForWallet(key);
if (!topics.contains(pairingTopic)) return;
topics.remove(pairingTopic);
await sharedPreferences.setString(key, jsonEncode(topics));
}
Future<void> savePairingTopicToLocalStorage(String pairingTopic) async {
// Get key specific to the current wallet
final key = getKeyForStoringTopicsForWallet();