add wallet level toggle to flag outgoing transactions as opt-in RBF

This commit is contained in:
julian 2024-06-19 14:42:08 -06:00
parent 44c5f1551e
commit 3f2fe2b2ce
4 changed files with 69 additions and 4 deletions

View file

@ -28,6 +28,7 @@ import '../../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_inter
import '../../../../../wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
import '../../../../../widgets/custom_buttons/draggable_switch_button.dart';
import '../../../../../widgets/desktop/desktop_dialog.dart';
@ -81,6 +82,27 @@ class _MoreFeaturesDialogState extends ConsumerState<MoreFeaturesDialog> {
}
}
bool _switchRbfToggledLock = false; // Mutex.
Future<void> _switchRbfToggled(bool newValue) async {
if (_switchRbfToggledLock) {
return;
}
_switchRbfToggledLock = true; // Lock mutex.
try {
// Toggle enableOptInRbf in wallet info.
await ref.read(pWalletInfo(widget.walletId)).updateOtherData(
newEntries: {
WalletInfoKeys.enableOptInRbf: newValue,
},
isar: ref.read(mainDBProvider).isar,
);
} finally {
// ensure _switchRbfToggledLock is set to false no matter what
_switchRbfToggledLock = false;
}
}
@override
Widget build(BuildContext context) {
final wallet = ref.watch(
@ -198,6 +220,38 @@ class _MoreFeaturesDialogState extends ConsumerState<MoreFeaturesDialog> {
],
),
),
if (wallet is RbfInterface)
_MoreFeaturesItemBase(
child: Row(
children: [
const SizedBox(width: 3),
SizedBox(
height: 20,
width: 40,
child: DraggableSwitchButton(
isOn: ref.watch(
pWalletInfo(widget.walletId)
.select((value) => value.otherData),
)[WalletInfoKeys.enableOptInRbf] as bool? ??
false,
onValueChanged: _switchRbfToggled,
),
),
const SizedBox(
width: 16,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Flag outgoing transactions with opt-in RBF",
style: STextStyles.w600_20(context),
),
],
),
],
),
),
const SizedBox(
height: 28,
),

View file

@ -510,4 +510,5 @@ abstract class WalletInfoKeys {
static const String enableLelantusScanning = "enableLelantusScanningKey";
static const String firoSparkCacheSetTimestampCache =
"firoSparkCacheSetTimestampCacheKey";
static const String enableOptInRbf = "enableOptInRbfKey";
}

View file

@ -28,6 +28,7 @@ import '../impl/peercoin_wallet.dart';
import '../intermediate/bip39_hd_wallet.dart';
import 'cpfp_interface.dart';
import 'paynym_interface.dart';
import 'rbf_interface.dart';
mixin ElectrumXInterface<T extends ElectrumXCurrencyInterface>
on Bip39HDWallet<T> {
@ -633,6 +634,11 @@ mixin ElectrumXInterface<T extends ElectrumXCurrencyInterface>
outputs: [],
);
// TODO: [prio=high]: check this opt in rbf
final sequence = this is RbfInterface && (this as RbfInterface).flagOptInRBF
? 0xffffffff - 10
: 0xffffffff - 1;
// Add transaction inputs
for (var i = 0; i < utxoSigningData.length; i++) {
final txid = utxoSigningData[i].utxo.txid;
@ -664,7 +670,7 @@ mixin ElectrumXInterface<T extends ElectrumXCurrencyInterface>
input = coinlib.P2PKHInput(
prevOut: prevOutpoint,
publicKey: utxoSigningData[i].keyPair!.publicKey,
sequence: 0xffffffff - 1,
sequence: sequence,
);
// TODO: fix this as it is (probably) wrong!
@ -675,14 +681,14 @@ mixin ElectrumXInterface<T extends ElectrumXCurrencyInterface>
// program: coinlib.MultisigProgram.decompile(
// utxoSigningData[i].redeemScript!,
// ),
// sequence: 0xffffffff - 1,
// sequence: sequence,
// );
case DerivePathType.bip84:
input = coinlib.P2WPKHInput(
prevOut: prevOutpoint,
publicKey: utxoSigningData[i].keyPair!.publicKey,
sequence: 0xffffffff - 1,
sequence: sequence,
);
case DerivePathType.bip86:
@ -700,7 +706,7 @@ mixin ElectrumXInterface<T extends ElectrumXCurrencyInterface>
InputV2.isarCantDoRequiredInDefaultConstructor(
scriptSigHex: input.scriptSig.toHex,
scriptSigAsm: null,
sequence: 0xffffffff - 1,
sequence: sequence,
outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor(
txid: utxoSigningData[i].utxo.txid,
vout: utxoSigningData[i].utxo.vout,

View file

@ -8,6 +8,7 @@ import '../../../utilities/amount/amount.dart';
import '../../../utilities/enums/fee_rate_type_enum.dart';
import '../../../utilities/logger.dart';
import '../../crypto_currency/interfaces/electrumx_currency_interface.dart';
import '../../isar/models/wallet_info.dart';
import '../../models/tx_data.dart';
import 'electrumx_interface.dart';
@ -15,6 +16,9 @@ typedef TxSize = ({int real, int virtual});
mixin RbfInterface<T extends ElectrumXCurrencyInterface>
on ElectrumXInterface<T> {
bool get flagOptInRBF =>
info.otherData[WalletInfoKeys.enableOptInRbf] as bool? ?? false;
Future<TxSize?> getVSize(String txid) async {
final tx = await electrumXCachedClient.getTransaction(
txHash: txid,