Skip to content
Draft
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

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

26 changes: 26 additions & 0 deletions ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved

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

77 changes: 36 additions & 41 deletions lib/electrumx_rpc/client_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class ClientManager {

final Map<String, ElectrumClient> _map = {};
final Map<String, TorPlainNetworkOption> _mapNet = {};
final Map<String, String?> _certificates = {};
final Map<String, int> _heights = {};
final Map<String, StreamSubscription<BlockHeader>> _subscriptions = {};
final Map<String, Completer<int>> _heightCompleters = {};
Expand Down Expand Up @@ -42,82 +43,75 @@ class ClientManager {
ElectrumClient client, {
required CryptoCurrency cryptoCurrency,
required TorPlainNetworkOption netType,
String? trustedCertificatePem,
}) async {
final key = _keyHelper(cryptoCurrency);
if (_map[key] != null) {
if (_mapNet[key] == netType) {
throw Exception(
"ElectrumX Client for $key and $netType already exists.",
);
}

await remove(cryptoCurrency: cryptoCurrency);

_map[key] = client;
_mapNet[key] = netType;
} else {
_map[key] = client;
_mapNet[key] = netType;
}

_heightCompleters[key] = Completer<int>();
final previous = _map[key];
final subscription = _subscriptions.remove(key);
_map[key] = client;
_mapNet[key] = netType;
_heights.remove(key);
_certificates[key] = trustedCertificatePem;
final firstHeight = _heightCompleters[key] = Completer<int>();
_subscriptions[key] = client.subscribeHeaders().listen(
(event) {
if (!identical(_map[key], client)) return;
_heights[key] = event.height;

if (!_heightCompleters[key]!.isCompleted) {
_heightCompleters[key]!.complete(event.height);
if (!firstHeight.isCompleted) {
firstHeight.complete(event.height);
}
},
onError: (Object err, StackTrace s) => Logging.instance.e(
"ClientManager listen",
error: err,
stackTrace: s,
),
onError: (Object err, StackTrace s) =>
Logging.instance.e("ClientManager listen", error: err, stackTrace: s),
);
await subscription?.cancel();
await previous?.close();
}

Future<int> getChainHeightFor(CryptoCurrency cryptoCurrency) async {
final key = _keyHelper(cryptoCurrency);

if (_map[key] == null) {
throw Exception(
"No managed ElectrumClient for $key found.",
);
throw Exception("No managed ElectrumClient for $key found.");
}
if (_heightCompleters[key] == null) {
throw Exception(
"No managed _heightCompleters for $key found.",
);
throw Exception("No managed _heightCompleters for $key found.");
}

if (Prefs.instance.useTor) {
if (_mapNet[key]! == TorPlainNetworkOption.clear) {
throw Exception(
"Non-TOR only client for $key found.",
);
throw Exception("Non-TOR only client for $key found.");
}
} else {
if (_mapNet[key]! == TorPlainNetworkOption.tor) {
throw Exception(
"TOR only client for $key found.",
);
throw Exception("TOR only client for $key found.");
}
}

return _heights[key] ?? await _heightCompleters[key]!.future;
}

/// The certificate the managed connection for [cryptoCurrency] was opened
/// with, or null when it relies on the platform's trusted roots.
String? trustedCertificateFor(CryptoCurrency cryptoCurrency) =>
_certificates[_keyHelper(cryptoCurrency)];

Future<(ElectrumClient?, TorPlainNetworkOption?)> remove({
required CryptoCurrency cryptoCurrency,
ElectrumClient? expectedClient,
}) async {
final key = _keyHelper(cryptoCurrency);
await _subscriptions[key]?.cancel();
_subscriptions.remove(key);
if (expectedClient != null && !identical(_map[key], expectedClient)) {
return (null, null);
}
final client = _map.remove(key);
final network = _mapNet.remove(key);
final subscription = _subscriptions.remove(key);
_heights.remove(key);
_heightCompleters.remove(key);

return (_map.remove(key), _mapNet.remove(key));
_certificates.remove(key);
await subscription?.cancel();
return (client, network);
}

Future<void> closeAll() async {
Expand All @@ -138,5 +132,6 @@ class ClientManager {
_subscriptions.clear();
_mapNet.clear();
_map.clear();
_certificates.clear();
}
}
Loading
Loading