Skip to content

Commit

Permalink
Merge pull request #1649 from bitmark-inc/Improve-connection-revocation
Browse files Browse the repository at this point in the history
Improve connection revocation
hoangbtmrk authored Apr 26, 2024
2 parents 8bf2542 + 4ce5228 commit 268b555
Showing 7 changed files with 137 additions and 53 deletions.
7 changes: 7 additions & 0 deletions lib/common/injector.dart
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ import 'package:autonomy_flutter/gateway/merchandise_api.dart';
import 'package:autonomy_flutter/gateway/postcard_api.dart';
import 'package:autonomy_flutter/gateway/pubdoc_api.dart';
import 'package:autonomy_flutter/gateway/tzkt_api.dart';
import 'package:autonomy_flutter/screen/bloc/connections/connections_bloc.dart';
import 'package:autonomy_flutter/screen/bloc/identity/identity_bloc.dart';
import 'package:autonomy_flutter/screen/chat/chat_bloc.dart';
import 'package:autonomy_flutter/screen/collection_pro/collection_pro_bloc.dart';
@@ -417,4 +418,10 @@ Future<void> setup() async {
injector.registerFactory<IdentityBloc>(
() => IdentityBloc(injector(), injector()));
injector.registerFactory<AuChatBloc>(() => AuChatBloc(injector()));

injector.registerLazySingleton<ConnectionsBloc>(() => ConnectionsBloc(
injector<CloudDatabase>(),
injector(),
injector(),
));
}
7 changes: 7 additions & 0 deletions lib/database/cloud_database.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions lib/database/dao/connection_dao.dart
Original file line number Diff line number Diff line change
@@ -76,6 +76,9 @@ abstract class ConnectionDao {
@delete
Future<void> deleteConnections(List<Connection> connections);

@Query('DELETE FROM Connection WHERE `key` LIKE :topic')
Future<void> deleteConnectionsByTopic(String topic);

@Query('DELETE FROM Connection WHERE accountNumber = :accountNumber '
'COLLATE NOCASE')
Future<void> deleteConnectionsByAccountNumber(String accountNumber);
25 changes: 8 additions & 17 deletions lib/screen/app_router.dart
Original file line number Diff line number Diff line change
@@ -258,6 +258,7 @@ class AppRouter {
injector(),
injector<AuditService>(),
);
final connectionsBloc = injector<ConnectionsBloc>();
final identityBloc = IdentityBloc(injector<AppDatabase>(), injector());
final postcardDetailBloc = PostcardDetailBloc(
injector(),
@@ -368,6 +369,7 @@ class AppRouter {
BlocProvider(
create: (_) => personaBloc,
),
BlocProvider(lazy: false, create: (_) => connectionsBloc),
],
child: HomeNavigationPage(
key: homePageNoTransactionKey,
@@ -391,6 +393,7 @@ class AppRouter {
BlocProvider(
create: (_) => personaBloc,
),
BlocProvider(lazy: false, create: (_) => connectionsBloc),
],
child: HomeNavigationPage(
key: homePageKey,
@@ -559,11 +562,8 @@ class AppRouter {
BlocProvider.value(value: tezosBloc),
BlocProvider.value(value: usdcBloc),
BlocProvider.value(
value: ConnectionsBloc(
injector<CloudDatabase>(),
injector(),
injector(),
))
value: connectionsBloc,
),
],
child: PersonaConnectionsPage(
payload:
@@ -572,12 +572,8 @@ class AppRouter {
case connectionDetailsPage:
return CupertinoPageRoute(
settings: settings,
builder: (context) => BlocProvider(
create: (_) => ConnectionsBloc(
injector<CloudDatabase>(),
injector(),
injector(),
),
builder: (context) => BlocProvider.value(
value: connectionsBloc,
child: ConnectionDetailsPage(
connectionItem: settings.arguments! as ConnectionItem,
)));
@@ -589,12 +585,7 @@ class AppRouter {
providers: [
BlocProvider.value(value: accountsBloc),
BlocProvider.value(value: usdcBloc),
BlocProvider.value(
value: ConnectionsBloc(
injector<CloudDatabase>(),
injector(),
injector(),
)),
BlocProvider.value(value: connectionsBloc),
BlocProvider(
create: (_) => WalletDetailBloc(
injector(), injector(), injector())),
116 changes: 82 additions & 34 deletions lib/screen/bloc/connections/connections_bloc.dart
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ import 'package:autonomy_flutter/database/entity/connection.dart';
import 'package:autonomy_flutter/model/p2p_peer.dart';
import 'package:autonomy_flutter/service/tezos_beacon_service.dart';
import 'package:autonomy_flutter/service/wc2_service.dart';
import 'package:autonomy_flutter/util/log.dart';
import 'package:collection/collection.dart';

part 'connections_state.dart';
@@ -32,12 +33,38 @@ class ConnectionsBloc extends AuBloc<ConnectionsEvent, ConnectionsState> {
personaConnections.add(connection);
}
}

// PersonaConnectionsPage is showing combined connections based on appName
final resultGroup =
groupBy(personaConnections, (Connection conn) => conn.appName);
final connectionItems = resultGroup.values
.map((conns) =>
ConnectionItem(representative: conns.first, connections: conns))
.toList();
return connectionItems;
}

Future<List<ConnectionItem>> _getBeaconConnections(
String personaUUID, int index) async {
final connections = await _cloudDB.connectionDao
.getConnectionsByType(ConnectionType.beaconP2PPeer.rawValue);

List<Connection> personaConnections = [];
for (var connection in connections) {
if (connection.beaconConnectConnection?.personaUuid == personaUUID &&
connection.beaconConnectConnection?.index == index) {
personaConnections.add(connection);
}
}

// PersonaConnectionsPage is showing combined connections based on appName
final resultGroup =
groupBy(personaConnections, (Connection conn) => conn.appName);
final connectionItems = resultGroup.values
.map((conns) =>
ConnectionItem(representative: conns.first, connections: conns))
.toList();

return connectionItems;
}

@@ -48,45 +75,25 @@ class ConnectionsBloc extends AuBloc<ConnectionsEvent, ConnectionsState> {
) : super(ConnectionsState()) {
on<GetETHConnectionsEvent>((event, emit) async {
emit(state.resetConnectionItems());
// PersonaConnectionsPage is showing combined connections based on app
final connectionItems = await _getWc2Connections(

final auConnections = await _getWc2Connections(
event.address, ConnectionType.walletConnect2);
final wc2Connections =
await _getWc2Connections(event.address, ConnectionType.dappConnect2);
connectionItems.addAll(wc2Connections);

final connectionItems = [...auConnections, ...wc2Connections];
emit(state.copyWith(connectionItems: connectionItems));
});

on<GetXTZConnectionsEvent>((event, emit) async {
emit(state.resetConnectionItems());
final personaUUID = event.personUUID;

final connections = await _cloudDB.connectionDao
.getConnectionsByType(ConnectionType.beaconP2PPeer.rawValue);

List<Connection> personaConnections = [];
for (var connection in connections) {
if (connection.beaconConnectConnection?.personaUuid == personaUUID &&
connection.beaconConnectConnection?.index == event.index) {
personaConnections.add(connection);
}
}

// PersonaConnectionsPage is showing combined connections based on app
final resultGroup =
groupBy(personaConnections, (Connection conn) => conn.appName);
final connectionItems = resultGroup.values
.map((conns) =>
ConnectionItem(representative: conns.first, connections: conns))
.toList();

final auConnections = await _getWc2Connections(
event.address, ConnectionType.walletConnect2);
connectionItems.addAll(auConnections);
final wc2Connections =
await _getWc2Connections(event.address, ConnectionType.dappConnect2);
connectionItems.addAll(wc2Connections);
final beaconConnections =
await _getBeaconConnections(event.personUUID, event.index);

final connectionItems = [...auConnections, ...beaconConnections];

emit(state.copyWith(connectionItems: connectionItems));
});
@@ -95,7 +102,6 @@ class ConnectionsBloc extends AuBloc<ConnectionsEvent, ConnectionsState> {
Set<P2PPeer> bcPeers = {};

for (var connection in event.connectionItem.connections) {
unawaited(_cloudDB.connectionDao.deleteConnection(connection));
if ([
ConnectionType.walletConnect2.rawValue,
ConnectionType.dappConnect2.rawValue
@@ -106,18 +112,60 @@ class ConnectionsBloc extends AuBloc<ConnectionsEvent, ConnectionsState> {
}
}

final bcPeer = connection.beaconConnectConnection?.peer;
if (bcPeer != null) {
bcPeers.add(bcPeer);
if (connection.connectionType ==
ConnectionType.beaconP2PPeer.rawValue) {
unawaited(_cloudDB.connectionDao.deleteConnection(connection));

final bcPeer = connection.beaconConnectConnection?.peer;
if (bcPeer != null) {
bcPeers.add(bcPeer);
}
}
}

if (event.connectionItem.representative.connectionType ==
ConnectionType.beaconP2PPeer.rawValue) {
for (var peer in bcPeers) {
unawaited(_tezosBeaconService.removePeer(peer));
}
state.connectionItems?.remove(event.connectionItem);
emit(state.copyWith(connectionItems: state.connectionItems));
}
});

on<SessionDeletedEvent>((event, emit) async {
unawaited(
_cloudDB.connectionDao.deleteConnectionsByTopic('%${event.topic}%'));

if (state.connectionItems == null || state.connectionItems!.isEmpty) {
return;
}

for (var peer in bcPeers) {
unawaited(_tezosBeaconService.removePeer(peer));
for (var item in state.connectionItems!) {
item.connections
.removeWhere((connection) => connection.key.contains(event.topic));
}

state.connectionItems?.remove(event.connectionItem);
state.connectionItems?.removeWhere((item) => item.connections.isEmpty);

emit(state.copyWith(connectionItems: state.connectionItems));
});

_wc2Service.sessionDeleteNotifier.addListener(_onSessionDeletedFunc);
}

Future<void> _onSessionDeletedFunc() async {
final topic = _wc2Service.sessionDeleteNotifier.value;
if (topic == null) {
return;
}
log.info('SessionDeletedEvent: $topic');
add(SessionDeletedEvent(topic));
}

@override
Future<void> close() {
_wc2Service.sessionDeleteNotifier.removeListener(_onSessionDeletedFunc);
return super.close();
}
}
6 changes: 6 additions & 0 deletions lib/screen/bloc/connections/connections_state.dart
Original file line number Diff line number Diff line change
@@ -32,6 +32,12 @@ class DeleteConnectionsEvent extends ConnectionsEvent {
DeleteConnectionsEvent(this.connectionItem);
}

class SessionDeletedEvent extends ConnectionsEvent {
final String topic;

SessionDeletedEvent(this.topic);
}

class ConnectionItem {
final Connection representative;
final List<Connection> connections;
26 changes: 24 additions & 2 deletions lib/service/wc2_service.dart
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@ import 'package:autonomy_flutter/util/wallet_connect_ext.dart';
import 'package:autonomy_flutter/util/wc2_ext.dart';
import 'package:autonomy_flutter/util/wc2_tezos_ext.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
import 'package:web3dart/credentials.dart';

@@ -76,6 +77,9 @@ class Wc2Service {

final List<String> _approvedConnectionKey = [];

final ValueNotifier<String?> sessionDeleteNotifier =
ValueNotifier<String?>(null);

void addApprovedTopic(List<String> keys) {
_approvedConnectionKey.addAll(keys);
}
@@ -107,9 +111,9 @@ class Wc2Service {
_wcClient.onSessionRequest.subscribe((request) {
log.info('[Wc2Service] Finish handle request $request');
});
_wcClient.onSessionDelete.subscribe(_onSessionDeleted);

_registerEthRequest('${Wc2Chain.ethereum}:${Environment.web3ChainId}');
_registerEthRequest('${Wc2Chain.ethereum}:5');

_registerFeralfileRequest(
'${Wc2Chain.autonomy}:${Environment.appTestnetConfig ? 1 : 0}');
@@ -325,7 +329,19 @@ class Wc2Service {

Future<List<String>> _getAllConnectionKey() async {
final connections = await _cloudDB.connectionDao.getWc2Connections();
return connections.map((e) => e.key).toList();
final activeTopics = _wcClient.getActiveSessions().keys;
log.info('[Wc2Service] activeTopics: $activeTopics');
final inactiveConnections = connections
.where((element) =>
!activeTopics.any((topic) => element.key.contains(topic)))
.toList();
await _cloudDB.connectionDao.deleteConnections(inactiveConnections);
final keys = connections
.where((element) => !inactiveConnections.contains(element))
.map((e) => e.key)
.toList();
log.info('[Wc2Service] connection keys: $keys');
return keys;
}

List<SessionRequest> getPendingRequests() =>
@@ -447,6 +463,12 @@ class Wc2Service {

//#endregion

Future<void> _onSessionDeleted(SessionDelete? session) async {
if (session?.topic != null) {
sessionDeleteNotifier.value = session!.topic;
}
}

//#region Events handling

Future<void> _onSessionProposal(SessionProposalEvent? proposal) async {

0 comments on commit 268b555

Please sign in to comment.