Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
76464e1
Add Electrum TLS certificate approvals with adapter 5 timeouts
slopbot9k Nov 11, 2026
d9655ca
Reset Electrum failover selection after an invalid approval
slopbot9k Nov 11, 2026
534631d
Give verbose Electrum transaction batches a separate timeout
slopbot9k Nov 11, 2026
1ec7b8a
Cancel Electrum Tor waits without releasing request-owned locks
slopbot9k Nov 11, 2026
2a8fcb7
Preserve pending Electrum requests across failover
slopbot9k Nov 11, 2026
7beb9f5
Drain the shared Electrum client when its header subscription fails
slopbot9k Nov 11, 2026
cc4c8c9
Check a failover approval before retiring the shared Electrum client
slopbot9k Nov 11, 2026
0db8c6a
Close draining Electrum clients when a node changes
slopbot9k Nov 11, 2026
ab7e963
Give each ElectrumXClient its own Electrum connection
slopbot9k Nov 11, 2026
32425eb
Close the notification check's Electrum client after each check
slopbot9k Nov 11, 2026
4902461
Close a deleted wallet's Electrum client
slopbot9k Nov 11, 2026
7ea0485
Serve the mock Electrum client through the connection hook
slopbot9k Nov 11, 2026
7308e45
Rewrite Electrum tests that assumed a shared connection
slopbot9k Nov 11, 2026
db1b030
Test Electrum connection isolation between wallets
slopbot9k Nov 11, 2026
8b00fcf
Update node-change and notification tests for per-wallet connections
slopbot9k Nov 11, 2026
a12b859
Fix per-wallet Electrum connection lifecycle problems
slopbot9k Nov 11, 2026
ea4aa05
Close a cancelled restore's Electrum client immediately
slopbot9k Nov 11, 2026
63281b8
Update loaded wallets when a node is deleted
slopbot9k Nov 11, 2026
a46d0cb
Report a Connect that could not be saved
slopbot9k Nov 12, 2026
827c853
Run one mobile Connect test at a time
slopbot9k Nov 12, 2026
443fe30
Give Firo set downloads three hours
slopbot9k Nov 12, 2026
5be828b
Close a view-only restore's Electrum client when it is not added
slopbot9k Nov 12, 2026
16b0691
Merge remote-tracking branch 'upstream/staging' into electrumx-per-wa…
slopbot9k Nov 12, 2026
6d56c42
Format the view-only restore view
slopbot9k Nov 12, 2026
4b88ce9
Stop describing a certificate approval as a pin
slopbot9k Nov 13, 2026
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
142 changes: 0 additions & 142 deletions lib/electrumx_rpc/client_manager.dart

This file was deleted.

71 changes: 71 additions & 0 deletions lib/electrumx_rpc/draining_electrum_client.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import 'dart:async';

import 'package:electrum_adapter/electrum_adapter.dart';

/// A superseded connection finishes its outstanding RPCs before closing.
/// Every adapter helper, including subscription setup, uses this request hook.
/// Explicit close still cancels immediately for revocation and shutdown.
mixin DrainingElectrumClient on ElectrumClient {
int _requests = 0;
bool _retiring = false;

Future<void> retire() async {
_retiring = true;
if (_requests == 0) await close();
}

@override
Future<dynamic> requestWithTimeout(
String method, {
dynamic parameters,
Duration? timeout,
}) {
_requests++;
try {
final pending = super.requestWithTimeout(
method,
parameters: parameters,
timeout: timeout,
);
// Keep the original future: subscription setup relies on the adapter's
// synchronous completion ordering relative to following notifications.
unawaited(
pending.then<void>(
(_) => _requestFinished(),
onError: (Object _) => _requestFinished(),
),
);
return pending;
} catch (_) {
_requestFinished();
rethrow;
}
}

void _requestFinished() {
if (--_requests == 0 && _retiring) close().ignore();
}
}

class ManagedElectrumClient extends ElectrumClient with DrainingElectrumClient {
ManagedElectrumClient(
super.channel,
super.host,
super.port,
super.useSSL,
super.proxyInfo, {
required super.requestTimeout,
});
}

class ManagedFiroElectrumClient extends FiroElectrumClient
with DrainingElectrumClient {
ManagedFiroElectrumClient(
super.channel,
super.host,
super.port,
super.useSSL,
super.proxyInfo, {
required super.requestTimeout,
});
}
34 changes: 34 additions & 0 deletions lib/electrumx_rpc/electrum_request_timeouts.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/// Response limits shared by individual and batched Electrum requests.
class ElectrumRequestTimeouts {
const ElectrumRequestTimeouts({
this.standard = const Duration(seconds: 60),
this.history = const Duration(minutes: 5),
this.transactionBatch = const Duration(minutes: 5),
this.firoSet = const Duration(hours: 3),
this.broadcast = const Duration(minutes: 5),
});

final Duration standard;
final Duration history;

/// Deadline for the combined response to a verbose transaction batch.
final Duration transactionBatch;

/// Deadline for a Firo set download. The full Spark used-tag set alone is
/// tens of megabytes and arrives as one response, so this is long enough
/// for very slow connections to finish it.
final Duration firoSet;
final Duration broadcast;

Duration forMethod(String method) => switch (method) {
'blockchain.scripthash.get_history' => history,
'blockchain.transaction.broadcast' => broadcast,
'lelantus.getanonymityset' ||
'lelantus.getusedcoinserials' ||
'spark.getusedcoinstags' ||
'spark.getusedcoinstagstxhashes' ||
'spark.getsparkanonymityset' ||
'spark.getsparkanonymitysetsector' => firoSet,
_ => standard,
};
}
Loading
Loading