Add Local node host & port settings
MODIFY
WalletWasabi.Gui/Config.cs
WalletWasabi.Gui/Config.cs
using NBitcoin;
using Newtonsoft.Json;
using System;
-using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
-using WalletWasabi.Crypto;
using WalletWasabi.Gui.Models;
using WalletWasabi.Helpers;
using WalletWasabi.Interfaces;
@@ -450,7 +448,6 @@ namespace WalletWasabi.Gui
{
return true;
}
-
if (UseTor != config.UseTor)
{
return true;

MODIFY
WalletWasabi.Gui/Tabs/SettingsView.xaml
WalletWasabi.Gui/Tabs/SettingsView.xaml
<TextBlock>Network</TextBlock>
<DropDown Items="{Binding Networks}" SelectedItem="{Binding Network}" />
</StackPanel>
+
+ <controls:GroupBox Title="{Binding Network, StringFormat=My Node for \{0\} }" TextBlock.FontSize="16" Padding="10" Margin="0 5 10 5">
+ <StackPanel Orientation="Vertical" Spacing="5">
+ <StackPanel Margin="0 10" Spacing="5">
+ <TextBlock>Host</TextBlock>
+ <TextBox Text="{Binding LocalNodeHost}" />
+ </StackPanel>
+ <Separator/>
+ <StackPanel Spacing="5">
+ <TextBlock>Port</TextBlock>
+ <TextBox Text="{Binding LocalNodePort}" />
+ </StackPanel>
+ </StackPanel>
+ </controls:GroupBox>
+
</StackPanel>
</controls:GroupBox>

MODIFY
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
WalletWasabi.Gui/Tabs/SettingsViewModel.cs
@@ -9,7 +9,6 @@ using System.Net.Sockets;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
-using System.Text.RegularExpressions;
using WalletWasabi.Gui.ViewModels;
using WalletWasabi.Gui.ViewModels.Validation;
@@ -22,6 +21,8 @@ namespace WalletWasabi.Gui.Tabs
private string _network;
private string _torHost;
private string _torPort;
+ private string _localNodeHost;
+ private string _localNodePort;
private bool _autocopy;
private bool _useTor;
private bool _isModified;
@@ -38,10 +39,26 @@ namespace WalletWasabi.Gui.Tabs
var config = new Config(Global.Config.FilePath);
Autocopy = Global.UiConfig?.Autocopy is true;
+ this.WhenAnyValue(x => x.Network)
+ .Subscribe(x => {
+ var (configLocalHost, configLocalPort) = Network == NBitcoin.Network.Main.Name
+ ? (config.MainNetBitcoinCoreHost, config.MainNetBitcoinCorePort)
+ : (Network == NBitcoin.Network.TestNet.Name
+ ? (config.TestNetBitcoinCoreHost, config.TestNetBitcoinCorePort)
+ : (config.RegTestBitcoinCoreHost, config.RegTestBitcoinCorePort));
+
+ LocalNodeHost = configLocalHost;
+ LocalNodePort = configLocalPort.ToString();
+ });
+
this.WhenAnyValue(x => x.Network,
x => x.TorHost, x => x.TorPort, x => x.UseTor)
.Subscribe(x => Save());
+ this.WhenAnyValue(
+ x => x.LocalNodeHost, x => x.LocalNodePort)
+ .Subscribe(x => Save());
+
this.WhenAnyValue(
x => x.SomePrivacyLevel, x => x.FinePrivacyLevel, x => x.StrongPrivacyLevel,
x => x.DustThreshold)
@@ -135,6 +152,20 @@ namespace WalletWasabi.Gui.Tabs
set => this.RaiseAndSetIfChanged(ref _torPort, value);
}
+ [ValidateMethod(nameof(ValidateLocalNodeHost))]
+ public string LocalNodeHost
+ {
+ get => _localNodeHost;
+ set => this.RaiseAndSetIfChanged(ref _localNodeHost, value);
+ }
+
+ [ValidateMethod(nameof(ValidateLocalNodePort))]
+ public string LocalNodePort
+ {
+ get => _localNodePort;
+ set => this.RaiseAndSetIfChanged(ref _localNodePort, value);
+ }
+
public bool IsModified
{
get => _isModified;
@@ -185,8 +216,10 @@ namespace WalletWasabi.Gui.Tabs
private void Save()
{
- var isValid = string.IsNullOrEmpty(ValidateTorHost()) &&
- string.IsNullOrEmpty(ValidateTorPort());
+ var isValid = string.IsNullOrEmpty(ValidateTorHost())
+ && string.IsNullOrEmpty(ValidateTorPort())
+ && string.IsNullOrEmpty(ValidateLocalNodeHost())
+ && string.IsNullOrEmpty(ValidateLocalNodePort());
if (!isValid)
{
return;
@@ -209,6 +242,8 @@ namespace WalletWasabi.Gui.Tabs
var network = NBitcoin.Network.GetNetwork(Network);
var torHost = TorHost;
+ var localNodeHost = LocalNodeHost;
+ var localNodePort = LocalNodePort;
var torSocks5Port = int.TryParse(TorPort, out var port) ? (int?)port : null;
var useTor = UseTor;
var somePrivacyLevel = int.TryParse(SomePrivacyLevel, out int level) ? (int?)level : null;
@@ -216,6 +251,12 @@ namespace WalletWasabi.Gui.Tabs
var strongPrivacyLevel = int.TryParse(StrongPrivacyLevel, out level) ? (int?)level : null;
var dustThreshold = decimal.TryParse(DustThreshold, out var threshold) ? (decimal?)threshold : null;
+ var (configLocalHost, configLocalPort) = network == NBitcoin.Network.Main
+ ? (config.MainNetBitcoinCoreHost, config.MainNetBitcoinCorePort)
+ : (network == NBitcoin.Network.TestNet
+ ? (config.TestNetBitcoinCoreHost, config.TestNetBitcoinCorePort)
+ : (config.RegTestBitcoinCoreHost, config.RegTestBitcoinCorePort));
+
if (config.Network != network
|| config.TorHost != torHost
|| config.TorSocks5Port != torSocks5Port
@@ -223,7 +264,10 @@ namespace WalletWasabi.Gui.Tabs
|| config.PrivacyLevelSome != somePrivacyLevel
|| config.PrivacyLevelFine != finePrivacyLevel
|| config.PrivacyLevelStrong != strongPrivacyLevel
- || config.DustThreshold.ToUnit(MoneyUnit.BTC) != dustThreshold)
+ || config.DustThreshold.ToUnit(MoneyUnit.BTC) != dustThreshold
+ || configLocalHost != localNodeHost
+ || configLocalPort.ToString() != localNodePort
+ )
{
config.Network = network;
config.TorHost = torHost;
@@ -234,6 +278,22 @@ namespace WalletWasabi.Gui.Tabs
config.PrivacyLevelStrong = strongPrivacyLevel;
config.DustThreshold = Money.Coins(dustThreshold.Value);
+ switch(network.Name)
+ {
+ case "Main":
+ config.MainNetBitcoinCoreHost = localNodeHost;
+ config.MainNetBitcoinCorePort = int.Parse(localNodePort);
+ break;
+ case "TestNet":
+ config.TestNetBitcoinCoreHost = localNodeHost;
+ config.TestNetBitcoinCorePort = int.Parse(localNodePort);
+ break;
+ case "RegTest":
+ config.RegTestBitcoinCoreHost = localNodeHost;
+ config.RegTestBitcoinCorePort = int.Parse(localNodePort);
+ break;
+ }
+
await config.ToFileAsync();
IsModified = await Global.Config.CheckFileChangeAsync();
@@ -242,44 +302,16 @@ namespace WalletWasabi.Gui.Tabs
}
public string ValidateTorHost()
- {
- if (string.IsNullOrWhiteSpace(TorHost))
- {
- return string.Empty;
- }
-
- var torHost = TorHost.Trim();
- if (Uri.TryCreate(torHost, UriKind.Absolute, out _))
- {
- return string.Empty;
- }
- if (IPAddress.TryParse(torHost, out var ip))
- {
- if (ip.AddressFamily == AddressFamily.InterNetworkV6 && !Socket.OSSupportsIPv6)
- {
- return "OS does not support IPv6 addresses.";
- }
- return string.Empty;
- }
+ => ValidateHost(TorHost);
- return "Invalid host.";
- }
+ public string ValidateLocalNodeHost()
+ => ValidateHost(LocalNodeHost);
public string ValidateTorPort()
- {
- if (string.IsNullOrEmpty(TorPort))
- {
- return string.Empty;
- }
+ => ValidatePort(TorPort);
- var torPort = TorPort.Trim();
- if (ushort.TryParse(torPort, out _))
- {
- return string.Empty;
- }
-
- return "Invalid port.";
- }
+ public string ValidateLocalNodePort()
+ => ValidatePort(LocalNodePort);
public string ValidateSomePrivacyLevel()
=> ValidatePrivacyLevel(SomePrivacyLevel);
@@ -320,6 +352,46 @@ namespace WalletWasabi.Gui.Tabs
return "Invalid dust amount.";
}
+ public string ValidateHost(string host)
+ {
+ if (string.IsNullOrWhiteSpace(host))
+ {
+ return string.Empty;
+ }
+
+ var theHost = host.Trim();
+ if (Uri.TryCreate(theHost, UriKind.Absolute, out _))
+ {
+ return string.Empty;
+ }
+ if (IPAddress.TryParse(theHost, out var ip))
+ {
+ if (ip.AddressFamily == AddressFamily.InterNetworkV6 && !Socket.OSSupportsIPv6)
+ {
+ return "OS does not support IPv6 addresses.";
+ }
+ return string.Empty;
+ }
+
+ return "Invalid host.";
+ }
+
+ public string ValidatePort(string port)
+ {
+ if (string.IsNullOrEmpty(port))
+ {
+ return string.Empty;
+ }
+
+ var thePort = port.Trim();
+ if (ushort.TryParse(thePort, out _))
+ {
+ return string.Empty;
+ }
+
+ return "Invalid port.";
+ }
+
private void OpenConfigFile()
{
IoHelpers.OpenFileInTextEditor(Global.Config.FilePath);

Add Local node host & port settings