Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions packages/reown_appkit/lib/modal/appkit_modal_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1607,18 +1607,18 @@ class ReownAppKitModal
if (_currentSession == null) {
throw ReownAppKitModalException('Session is null');
}
if (!NamespaceUtils.isValidChainId(chainId)) {
throw Errors.getSdkError(
Errors.UNSUPPORTED_CHAINS,
context: 'chainId should conform to "CAIP-2" format',
).toSignError();
}
//
_appKit.core.logger.d(
'[$runtimeType] request, chainId: $chainId, '
'${jsonEncode(request.toJson())}',
);
try {
if (!NamespaceUtils.isValidChainId(chainId)) {
throw Errors.getSdkError(
Errors.UNSUPPORTED_CHAINS,
context: 'chainId should conform to "CAIP-2" format',
).toSignError();
}
if (_currentSession!.sessionService.isMagic) {
return await _magicService.request(chainId: chainId, request: request);
}
Expand Down Expand Up @@ -1655,12 +1655,13 @@ class ReownAppKitModal
} catch (e) {
if (_isUserRejectedError(e)) {
onModalError.broadcast(UserRejectedRequest());
} else {
if (e is CoinbaseServiceException) {
// If the error is due to no session on Coinbase Wallet we disconnnect the session on Modal.
// This is the only way to detect a missing session since Coinbase Wallet is not sending any event.
throw ReownAppKitModalException('Coinbase Wallet Error');
}
} else if (e is CoinbaseServiceException) {
// If the error is due to no session on Coinbase Wallet we disconnect the session on Modal.
// This is the only way to detect a missing session since Coinbase Wallet is not sending any event.
throw ReownAppKitModalException('Coinbase Wallet Error');
} else if (e is ReownSignError) {
onModalError.broadcast(ModalError(e.message));
return;
}
rethrow;
Comment on lines +1658 to 1666
}
Expand Down
46 changes: 27 additions & 19 deletions packages/reown_appkit/lib/modal/pages/activity_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,32 +114,40 @@ class _ActivityListViewBuilderState extends State<ActivityListViewBuilder> {
widget.appKitModal.onModalError.broadcast(
ModalError('Error fetching activity'),
);
final namespace = NamespaceUtils.getNamespaceFromChain(
widget.appKitModal.selectedChain?.chainId ?? '',
);
GetIt.I<IAnalyticsService>().sendEvent(
ErrorFetchTransactionsEvent(
address: widget.appKitModal.session!.getAddress(namespace),
projectId: widget.appKitModal.appKit!.core.projectId,
cursor: _currentCursor,
),
);
final session = widget.appKitModal.session;
final appKit = widget.appKitModal.appKit;
if (session != null && appKit != null) {
final namespace = NamespaceUtils.getNamespaceFromChain(
widget.appKitModal.selectedChain?.chainId ?? '',
);
GetIt.I<IAnalyticsService>().sendEvent(
ErrorFetchTransactionsEvent(
address: session.getAddress(namespace),
projectId: appKit.core.projectId,
cursor: _currentCursor,
),
);
}
}
setState(() {});
}

Future<void> _loadMoreActivities() async {
if (_isLoadingActivities || !_hasMoreActivities) return;

final chainId = widget.appKitModal.selectedChain?.chainId ?? '';
final namespace = NamespaceUtils.getNamespaceFromChain(chainId);
GetIt.I<IAnalyticsService>().sendEvent(
LoadMoreTransactionsEvent(
address: widget.appKitModal.session!.getAddress(namespace),
projectId: widget.appKitModal.appKit!.core.projectId,
cursor: _currentCursor,
),
);
final session = widget.appKitModal.session;
final appKit = widget.appKitModal.appKit;
if (session != null && appKit != null) {
final chainId = widget.appKitModal.selectedChain?.chainId ?? '';
final namespace = NamespaceUtils.getNamespaceFromChain(chainId);
GetIt.I<IAnalyticsService>().sendEvent(
LoadMoreTransactionsEvent(
address: session.getAddress(namespace),
projectId: appKit.core.projectId,
cursor: _currentCursor,
),
);
}
await _fetchActivities();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:reown_core/models/basic_models.dart';
import 'package:reown_core/relay_client/websocket/i_websocket_handler.dart';
import 'package:stream_channel/stream_channel.dart';
Expand All @@ -23,6 +24,8 @@ class WebSocketHandler implements IWebSocketHandler {

StreamController<String>? _inputController;
StreamController<String>? _outputController;
StreamSubscription<String>? _inputSubscription;
StreamSubscription<String>? _outputSubscription;

@override
Future<void> setup({required String url}) async {
Expand Down Expand Up @@ -51,17 +54,47 @@ class WebSocketHandler implements IWebSocketHandler {
_outputController = StreamController<String>.broadcast(sync: true);

// Split the incoming stream to support multiple listeners
_socket!.stream.cast<String>().listen(
_inputSubscription = _socket!.stream.cast<String>().listen(
(data) => _inputController?.add(data),
onError: (error) => _inputController?.addError(error),
onDone: () => _inputController?.close(),
onError: (error) {
try {
_inputController?.addError(error);
} catch (e) {
debugPrint('[WebSocketHandler] inputController.addError failed: $e');
}
},
onDone: () {
try {
_inputController?.close();
} catch (e) {
debugPrint('[WebSocketHandler] inputController.close failed: $e');
}
},
);

// Route outgoing messages through the output controller
_outputController!.stream.listen(
(data) => _socket?.sink.add(data),
onError: (error) => _socket?.sink.addError(error),
onDone: () => _socket?.sink.close(),
_outputSubscription = _outputController!.stream.listen(
(data) {
try {
_socket?.sink.add(data);
} catch (e) {
debugPrint('[WebSocketHandler] sink.add failed: $e');
}
},
onError: (error) {
try {
_socket?.sink.addError(error);
} catch (e) {
debugPrint('[WebSocketHandler] sink.addError failed: $e');
}
},
onDone: () {
try {
_socket?.sink.close();
} catch (e) {
debugPrint('[WebSocketHandler] sink.close failed: $e');
}
},
);

_channel = StreamChannel(_inputController!.stream, _outputController!.sink);
Expand All @@ -75,30 +108,50 @@ class WebSocketHandler implements IWebSocketHandler {
}
}

await _socket?.ready;

// Check if the request was successful (status code 200)
// try {} catch (e) {
// throw ReownCoreError(
// code: 400,
// message: 'WebSocket connection failed, missing or invalid project id.',
// );
// }
try {
await _socket?.ready;
} catch (e) {
await close();
throw ReownCoreError(
code: -1,
message: 'WebSocket connection failed: ${e.toString()}',
);
}
}

@override
Future<void> close() async {
// Cancel subscriptions first to prevent writes to closed sinks
try {
await _inputSubscription?.cancel();
} catch (e) {
debugPrint('[WebSocketHandler] inputSubscription.cancel failed: $e');
}
try {
await _outputSubscription?.cancel();
} catch (e) {
debugPrint('[WebSocketHandler] outputSubscription.cancel failed: $e');
}
_inputSubscription = null;
_outputSubscription = null;

try {
await _socket?.sink.close();
} catch (_) {}
} catch (e) {
debugPrint('[WebSocketHandler] socket.sink.close failed: $e');
}

// Close the controllers to prevent further messages and race conditions
try {
await _inputController?.close();
} catch (_) {}
} catch (e) {
debugPrint('[WebSocketHandler] inputController.close failed: $e');
}
try {
await _outputController?.close();
} catch (_) {}
} catch (e) {
debugPrint('[WebSocketHandler] outputController.close failed: $e');
}

_inputController = null;
_outputController = null;
Expand Down
4 changes: 3 additions & 1 deletion packages/reown_walletkit/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,13 @@ class _MyHomePageState extends State<MyHomePage> {
return keyService;
});
GetIt.I.registerSingleton<IWalletKitService>(WalletKitService());
await GetIt.I.allReady(timeout: Duration(seconds: 1));
await GetIt.I.allReady(timeout: Duration(seconds: 5));

final walletKitService = GetIt.I<IWalletKitService>();
await walletKitService.create();
await Future<void>.delayed(Duration.zero); // Yield to prevent UI hang
await walletKitService.setUpAccounts();
await Future<void>.delayed(Duration.zero); // Yield to prevent UI hang
await walletKitService.init();

walletKitService.walletKit.core.relayClient.onRelayClientConnect
Expand Down
Loading