mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-02-02 03:06:29 +00:00
add persistent fusion server prefs
This commit is contained in:
parent
a4c1814224
commit
c54b4d39d3
4 changed files with 262 additions and 61 deletions
|
@ -17,6 +17,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/pages/cashfusion/fusion_rounds_selection_sheet.dart';
|
||||
import 'package:stackwallet/providers/cash_fusion/fusion_progress_ui_state_provider.dart';
|
||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/fusion_wallet_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
|
@ -49,6 +50,8 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
late final FocusNode serverFocusNode;
|
||||
late final TextEditingController portController;
|
||||
late final FocusNode portFocusNode;
|
||||
late final TextEditingController fusionRoundController;
|
||||
late final FocusNode fusionRoundFocusNode;
|
||||
|
||||
bool _enableSSLCheckbox = false;
|
||||
bool _enableStartButton = false;
|
||||
|
@ -59,11 +62,18 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
void initState() {
|
||||
serverController = TextEditingController();
|
||||
portController = TextEditingController();
|
||||
fusionRoundController = TextEditingController();
|
||||
|
||||
serverFocusNode = FocusNode();
|
||||
portFocusNode = FocusNode();
|
||||
fusionRoundFocusNode = FocusNode();
|
||||
|
||||
// TODO set controller text values to saved info
|
||||
final info = ref.read(prefsChangeNotifierProvider).fusionServerInfo;
|
||||
serverController.text = info.host;
|
||||
portController.text = info.port.toString();
|
||||
_enableSSLCheckbox = info.ssl;
|
||||
_option = info.rounds == 0 ? FusionOption.continuous : FusionOption.custom;
|
||||
fusionRoundController.text = info.rounds.toString();
|
||||
|
||||
_enableStartButton =
|
||||
serverController.text.isNotEmpty && portController.text.isNotEmpty;
|
||||
|
@ -75,9 +85,11 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
void dispose() {
|
||||
serverController.dispose();
|
||||
portController.dispose();
|
||||
fusionRoundController.dispose();
|
||||
|
||||
serverFocusNode.dispose();
|
||||
portFocusNode.dispose();
|
||||
fusionRoundFocusNode.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
@ -166,8 +178,9 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
focusNode: serverFocusNode,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_enableStartButton = value.isNotEmpty &
|
||||
portController.text.isNotEmpty;
|
||||
_enableStartButton = value.isNotEmpty &&
|
||||
portController.text.isNotEmpty &&
|
||||
fusionRoundController.text.isNotEmpty;
|
||||
});
|
||||
},
|
||||
style: STextStyles.field(context),
|
||||
|
@ -197,8 +210,9 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
keyboardType: TextInputType.number,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_enableStartButton = value.isNotEmpty &
|
||||
serverController.text.isNotEmpty;
|
||||
_enableStartButton = value.isNotEmpty &&
|
||||
serverController.text.isNotEmpty &&
|
||||
fusionRoundController.text.isNotEmpty;
|
||||
});
|
||||
},
|
||||
style: STextStyles.field(context),
|
||||
|
@ -311,6 +325,40 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
),
|
||||
),
|
||||
),
|
||||
if (_option == FusionOption.custom)
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
if (_option == FusionOption.custom)
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
child: TextField(
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
controller: fusionRoundController,
|
||||
focusNode: fusionRoundFocusNode,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly
|
||||
],
|
||||
keyboardType: TextInputType.number,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_enableStartButton = value.isNotEmpty &&
|
||||
serverController.text.isNotEmpty &&
|
||||
portController.text.isNotEmpty;
|
||||
});
|
||||
},
|
||||
style: STextStyles.field(context),
|
||||
decoration: standardInputDecoration(
|
||||
"Number of fusions",
|
||||
fusionRoundFocusNode,
|
||||
context,
|
||||
).copyWith(
|
||||
labelText: "Enter number of fusions.."),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
|
@ -336,12 +384,28 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
}
|
||||
}
|
||||
|
||||
unawaited(fusionWallet.fuse(
|
||||
serverHost: serverController.text,
|
||||
serverPort: int.parse(portController.text),
|
||||
serverSsl: _enableSSLCheckbox,
|
||||
roundCount: 0, // TODO update fusion rounds.
|
||||
));
|
||||
final int rounds =
|
||||
_option == FusionOption.continuous
|
||||
? 0
|
||||
: int.parse(fusionRoundController.text);
|
||||
|
||||
final newInfo = FusionInfo(
|
||||
host: serverController.text,
|
||||
port: int.parse(portController.text),
|
||||
ssl: _enableSSLCheckbox,
|
||||
rounds: rounds,
|
||||
);
|
||||
|
||||
// update user prefs (persistent)
|
||||
ref
|
||||
.read(prefsChangeNotifierProvider)
|
||||
.fusionServerInfo = newInfo;
|
||||
|
||||
unawaited(
|
||||
fusionWallet.fuse(
|
||||
fusionInfo: newInfo,
|
||||
),
|
||||
);
|
||||
|
||||
// TODO: navigate to progress screen
|
||||
},
|
||||
|
|
|
@ -20,8 +20,8 @@ import 'package:flutter_svg/svg.dart';
|
|||
import 'package:stackwallet/pages/cashfusion/fusion_rounds_selection_sheet.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/cashfusion/sub_widgets/fusion_dialog.dart';
|
||||
import 'package:stackwallet/providers/cash_fusion/fusion_progress_ui_state_provider.dart';
|
||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/providers/ui/check_box_state_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/fusion_wallet_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
|
@ -58,9 +58,8 @@ class _DesktopCashFusion extends ConsumerState<DesktopCashFusionView> {
|
|||
late final TextEditingController fusionRoundController;
|
||||
late final FocusNode fusionRoundFocusNode;
|
||||
|
||||
String _fusionRoundTerm = "";
|
||||
|
||||
bool _enableStartButton = false;
|
||||
bool _enableSSLCheckbox = false;
|
||||
|
||||
FusionOption _roundType = FusionOption.continuous;
|
||||
|
||||
|
@ -74,7 +73,13 @@ class _DesktopCashFusion extends ConsumerState<DesktopCashFusionView> {
|
|||
portFocusNode = FocusNode();
|
||||
fusionRoundFocusNode = FocusNode();
|
||||
|
||||
// TODO set controller text values to saved info
|
||||
final info = ref.read(prefsChangeNotifierProvider).fusionServerInfo;
|
||||
serverController.text = info.host;
|
||||
portController.text = info.port.toString();
|
||||
_enableSSLCheckbox = info.ssl;
|
||||
_roundType =
|
||||
info.rounds == 0 ? FusionOption.continuous : FusionOption.custom;
|
||||
fusionRoundController.text = info.rounds.toString();
|
||||
|
||||
_enableStartButton =
|
||||
serverController.text.isNotEmpty && portController.text.isNotEmpty;
|
||||
|
@ -285,25 +290,25 @@ class _DesktopCashFusion extends ConsumerState<DesktopCashFusionView> {
|
|||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
child: TextField(
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
controller: serverController,
|
||||
focusNode: serverFocusNode,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_enableStartButton = value.isNotEmpty &
|
||||
portController.text.isNotEmpty;
|
||||
});
|
||||
},
|
||||
style: STextStyles.field(context),
|
||||
decoration: standardInputDecoration(
|
||||
"Server",
|
||||
serverFocusNode,
|
||||
context,
|
||||
desktopMed: true,
|
||||
)
|
||||
// .copyWith(labelStyle: ),
|
||||
),
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
controller: serverController,
|
||||
focusNode: serverFocusNode,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_enableStartButton = value.isNotEmpty &&
|
||||
portController.text.isNotEmpty &&
|
||||
fusionRoundController.text.isNotEmpty;
|
||||
});
|
||||
},
|
||||
style: STextStyles.field(context),
|
||||
decoration: standardInputDecoration(
|
||||
"Server",
|
||||
serverFocusNode,
|
||||
context,
|
||||
desktopMed: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
|
@ -322,8 +327,9 @@ class _DesktopCashFusion extends ConsumerState<DesktopCashFusionView> {
|
|||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_enableStartButton = value.isNotEmpty &
|
||||
serverController.text.isNotEmpty;
|
||||
_enableStartButton = value.isNotEmpty &&
|
||||
serverController.text.isNotEmpty &&
|
||||
fusionRoundController.text.isNotEmpty;
|
||||
});
|
||||
},
|
||||
style: STextStyles.field(context),
|
||||
|
@ -340,10 +346,9 @@ class _DesktopCashFusion extends ConsumerState<DesktopCashFusionView> {
|
|||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
final value =
|
||||
ref.read(checkBoxStateProvider.state).state;
|
||||
ref.read(checkBoxStateProvider.state).state =
|
||||
!value;
|
||||
setState(() {
|
||||
_enableSSLCheckbox = !_enableSSLCheckbox;
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
|
@ -355,13 +360,14 @@ class _DesktopCashFusion extends ConsumerState<DesktopCashFusionView> {
|
|||
child: Checkbox(
|
||||
materialTapTargetSize:
|
||||
MaterialTapTargetSize.shrinkWrap,
|
||||
value: ref
|
||||
.watch(checkBoxStateProvider.state)
|
||||
.state,
|
||||
value: _enableSSLCheckbox,
|
||||
onChanged: (newValue) {
|
||||
ref
|
||||
.watch(checkBoxStateProvider.state)
|
||||
.state = newValue!;
|
||||
setState(
|
||||
() {
|
||||
_enableSSLCheckbox =
|
||||
!_enableSSLCheckbox;
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -464,14 +470,21 @@ class _DesktopCashFusion extends ConsumerState<DesktopCashFusionView> {
|
|||
enableSuggestions: false,
|
||||
controller: fusionRoundController,
|
||||
focusNode: fusionRoundFocusNode,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_fusionRoundTerm = value;
|
||||
_enableStartButton = value
|
||||
.isNotEmpty &&
|
||||
serverController
|
||||
.text.isNotEmpty &&
|
||||
portController.text.isNotEmpty;
|
||||
});
|
||||
},
|
||||
style: STextStyles.field(context),
|
||||
decoration: standardInputDecoration(
|
||||
"",
|
||||
"Number of fusions",
|
||||
fusionRoundFocusNode,
|
||||
context,
|
||||
desktopMed: true,
|
||||
|
@ -507,12 +520,28 @@ class _DesktopCashFusion extends ConsumerState<DesktopCashFusionView> {
|
|||
}
|
||||
}
|
||||
|
||||
unawaited(fusionWallet.fuse(
|
||||
serverHost: serverController.text,
|
||||
serverPort: int.parse(portController.text),
|
||||
serverSsl: ref.read(checkBoxStateProvider),
|
||||
roundCount: 0, // TODO update fusion rounds.
|
||||
));
|
||||
final int rounds =
|
||||
_roundType == FusionOption.continuous
|
||||
? 0
|
||||
: int.parse(fusionRoundController.text);
|
||||
|
||||
final newInfo = FusionInfo(
|
||||
host: serverController.text,
|
||||
port: int.parse(portController.text),
|
||||
ssl: _enableSSLCheckbox,
|
||||
rounds: rounds,
|
||||
);
|
||||
|
||||
// update user prefs (persistent)
|
||||
ref
|
||||
.read(prefsChangeNotifierProvider)
|
||||
.fusionServerInfo = newInfo;
|
||||
|
||||
unawaited(
|
||||
fusionWallet.fuse(
|
||||
fusionInfo: newInfo,
|
||||
),
|
||||
);
|
||||
// unawaited(fusionWallet.stepThruUiStates());
|
||||
|
||||
await showDialog<void>(
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
|
@ -19,6 +20,77 @@ import 'package:stackwallet/utilities/stack_file_system.dart';
|
|||
|
||||
const String kReservedFusionAddress = "reserved_fusion_address";
|
||||
|
||||
class FusionInfo {
|
||||
final String host;
|
||||
final int port;
|
||||
final bool ssl;
|
||||
|
||||
/// set to 0 for continuous
|
||||
final int rounds;
|
||||
|
||||
const FusionInfo({
|
||||
required this.host,
|
||||
required this.port,
|
||||
required this.ssl,
|
||||
required this.rounds,
|
||||
}) : assert(rounds >= 0);
|
||||
|
||||
// TODO update defaults
|
||||
static const DEFAULTS = FusionInfo(
|
||||
host: "cashfusion.stackwallet.com",
|
||||
port: 8787,
|
||||
ssl: false,
|
||||
rounds: 0, // 0 is continuous
|
||||
);
|
||||
|
||||
factory FusionInfo.fromJsonString(String jsonString) {
|
||||
final json = jsonDecode(jsonString);
|
||||
return FusionInfo(
|
||||
host: json['host'] as String,
|
||||
port: json['port'] as int,
|
||||
ssl: json['ssl'] as bool,
|
||||
rounds: json['rounds'] as int,
|
||||
);
|
||||
}
|
||||
|
||||
String toJsonString() {
|
||||
return {
|
||||
'host': host,
|
||||
'port': port,
|
||||
'ssl': ssl,
|
||||
'rounds': rounds,
|
||||
}.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toJsonString();
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return other is FusionInfo &&
|
||||
other.host == host &&
|
||||
other.port == port &&
|
||||
other.ssl == ssl &&
|
||||
other.rounds == rounds;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return Object.hash(
|
||||
host.hashCode,
|
||||
port.hashCode,
|
||||
ssl.hashCode,
|
||||
rounds.hashCode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A mixin for the BitcoinCashWallet class that adds CashFusion functionality.
|
||||
mixin FusionWalletInterface {
|
||||
// Passed in wallet data.
|
||||
|
@ -292,17 +364,20 @@ mixin FusionWalletInterface {
|
|||
/// Fuse the wallet's UTXOs.
|
||||
///
|
||||
/// This function is called when the user taps the "Fuse" button in the UI.
|
||||
Future<void> fuse(
|
||||
{required String serverHost,
|
||||
required int serverPort,
|
||||
required bool serverSsl,
|
||||
required int roundCount}) async {
|
||||
Future<void> fuse({
|
||||
required FusionInfo fusionInfo,
|
||||
}) async {
|
||||
// Initial attempt for CashFusion integration goes here.
|
||||
|
||||
// Use server host and port which ultimately come from text fields.
|
||||
// TODO validate.
|
||||
fusion.FusionParams serverParams = fusion.FusionParams(
|
||||
serverHost: serverHost, serverPort: serverPort, serverSsl: serverSsl, roundCount: roundCount);
|
||||
serverHost: fusionInfo.host,
|
||||
serverPort: fusionInfo.port,
|
||||
serverSsl: fusionInfo.ssl,
|
||||
);
|
||||
|
||||
// TODO use as required. Zero indicates continuous
|
||||
final roundCount = fusionInfo.rounds;
|
||||
|
||||
// Instantiate a Fusion object with custom parameters.
|
||||
final mainFusionObject = fusion.Fusion(serverParams);
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:flutter/cupertino.dart';
|
|||
import 'package:stackwallet/db/hive/db.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/tor_status_changed_event.dart';
|
||||
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
|
||||
import 'package:stackwallet/services/mixins/fusion_wallet_interface.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount_unit.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
|
||||
|
@ -64,6 +65,7 @@ class Prefs extends ChangeNotifier {
|
|||
await _setAmountUnits();
|
||||
await _setMaxDecimals();
|
||||
_useTor = await _getUseTor();
|
||||
_fusionServerInfo = await _getFusionServerInfo();
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
@ -931,4 +933,35 @@ class Prefs extends ChangeNotifier {
|
|||
) as bool? ??
|
||||
false;
|
||||
}
|
||||
|
||||
// fusion server info
|
||||
|
||||
FusionInfo _fusionServerInfo = FusionInfo.DEFAULTS;
|
||||
|
||||
FusionInfo get fusionServerInfo => _fusionServerInfo;
|
||||
|
||||
set fusionServerInfo(FusionInfo fusionServerInfo) {
|
||||
if (this.fusionServerInfo != fusionServerInfo) {
|
||||
DB.instance.put<dynamic>(
|
||||
boxName: DB.boxNamePrefs,
|
||||
key: "fusionServerInfo",
|
||||
value: fusionServerInfo.toJsonString(),
|
||||
);
|
||||
_fusionServerInfo = fusionServerInfo;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<FusionInfo> _getFusionServerInfo() async {
|
||||
final saved = await DB.instance.get<dynamic>(
|
||||
boxName: DB.boxNamePrefs,
|
||||
key: "fusionServerInfo",
|
||||
) as String?;
|
||||
|
||||
if (saved == null) {
|
||||
return FusionInfo.DEFAULTS;
|
||||
} else {
|
||||
return FusionInfo.fromJsonString(saved);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue