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
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,
});
}
30 changes: 30 additions & 0 deletions lib/electrumx_rpc/electrum_request_timeouts.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/// 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(minutes: 2),
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;
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