5 Commits

Author SHA1 Message Date
843f824b2f package: Increased version 2023-06-22 13:29:37 +10:00
71a04edc02 README.md: Added default settings to config file
- Added default settings for HideScreen and Timeout to the config file
- Users can modify these values in the file if needed
2023-06-22 13:26:58 +10:00
30c5690c24 main: Custom timeouts 2023-06-22 13:20:11 +10:00
af9327a1fa main: Restart node if it hangs 2023-06-22 12:55:46 +10:00
07345d7f33 Merge branch 'newBranding' 2023-06-21 21:32:08 +10:00
4 changed files with 380 additions and 212 deletions

View File

@@ -12,7 +12,7 @@
<PackageIcon>HSDBatcher.png</PackageIcon> <PackageIcon>HSDBatcher.png</PackageIcon>
<RepositoryUrl>https://github.com/Nathanwoodburn/FireWallet</RepositoryUrl> <RepositoryUrl>https://github.com/Nathanwoodburn/FireWallet</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<Version>3.3</Version> <Version>3.4</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -91,7 +91,7 @@ namespace FireWallet
toolStripDropDownButtonHelp.DropDown.BackColor = ColorTranslator.FromHtml(Theme["background"]); toolStripDropDownButtonHelp.DropDown.BackColor = ColorTranslator.FromHtml(Theme["background"]);
// Load node // Load node
if (await LoadNode() != true) this.Close(); if (await LoadNode(ss) != true) this.Close();
// If node load caused app to close, exit load function // If node load caused app to close, exit load function
if (this.Disposing || this.IsDisposed) return; if (this.Disposing || this.IsDisposed) return;
@@ -181,15 +181,17 @@ namespace FireWallet
} }
#endregion #endregion
#region Settings #region Settings
private async Task<bool> LoadNode() private async Task<bool> LoadNode(SplashScreen? ss)
{ {
HSD = false; HSD = false;
if (!File.Exists(dir + "node.txt")) if (!File.Exists(dir + "node.txt"))
{ {
ss.Hide();
NodeForm cf = new NodeForm(); NodeForm cf = new NodeForm();
timerNodeStatus.Stop(); timerNodeStatus.Stop();
cf.ShowDialog(); cf.ShowDialog();
timerNodeStatus.Start(); timerNodeStatus.Start();
ss.Show();
} }
if (!File.Exists(dir + "node.txt")) if (!File.Exists(dir + "node.txt"))
{ {
@@ -231,6 +233,13 @@ namespace FireWallet
break; break;
} }
if (NodeSettings.ContainsKey("Timeout"))
{
int timeout = Convert.ToInt32(NodeSettings["Timeout"]);
httpClient.Timeout = TimeSpan.FromSeconds(timeout);
}
else httpClient.Timeout = TimeSpan.FromSeconds(10);
if (NodeSettings.ContainsKey("HSD")) if (NodeSettings.ContainsKey("HSD"))
{ {
if (NodeSettings["HSD"].ToLower() == "true") if (NodeSettings["HSD"].ToLower() == "true")
@@ -309,6 +318,8 @@ namespace FireWallet
if (hideScreen) if (hideScreen)
{ {
HSDProcess.StartInfo.RedirectStandardError = true; HSDProcess.StartInfo.RedirectStandardError = true;
// Send errors to log
HSDProcess.ErrorDataReceived += (sender, e) => AddLog("HSD Error: " + e.Data);
} }
else else
{ {
@@ -759,17 +770,17 @@ namespace FireWallet
toolStripStatusLabelLedger.Text = "Cold Wallet"; toolStripStatusLabelLedger.Text = "Cold Wallet";
toolStripStatusLabelLedger.Visible = true; toolStripStatusLabelLedger.Visible = true;
buttonRevealAll.Visible = false; buttonRevealAll.Visible = false;
buttonRedeemAll.Visible = false;
buttonSendAll.Visible = false;
} }
else else
{ {
WatchOnly = false; WatchOnly = false;
toolStripStatusLabelLedger.Visible = false; toolStripStatusLabelLedger.Visible = false;
buttonRevealAll.Visible = true; buttonRevealAll.Visible = true;
buttonRedeemAll.Visible = true;
buttonSendAll.Visible = true;
} }
if (WatchOnly) if (WatchOnly)
{ {
buttonAddressVerify.Visible = true; buttonAddressVerify.Visible = true;
@@ -852,6 +863,120 @@ namespace FireWallet
toolStripStatusLabelaccount.Text = "Account: Not Logged In"; toolStripStatusLabelaccount.Text = "Account: Not Logged In";
textBoxaccountpassword.Focus(); textBoxaccountpassword.Focus();
} }
private async void buttonRevealAll_Click(object sender, EventArgs e)
{
buttonRevealAll.Enabled = false;
string content = "{\"method\": \"sendreveal\"}";
string response = await APIPost("", true, content);
AddLog(response);
if (response == "Error")
{
AddLog("Error sending reveal");
NotifyForm notifyForm = new NotifyForm("Error sending reveal");
notifyForm.ShowDialog();
notifyForm.Dispose();
buttonRevealAll.Enabled = true;
return;
}
JObject resp = JObject.Parse(response);
if (resp["error"].ToString() != "")
{
AddLog("Error sending reveal");
AddLog(resp["error"].ToString());
JObject error = JObject.Parse(resp["error"].ToString());
NotifyForm notifyForm = new NotifyForm("Error sending reveal\n" + error["message"].ToString());
notifyForm.ShowDialog();
notifyForm.Dispose();
buttonRevealAll.Enabled = true;
return;
}
if (resp.ContainsKey("result"))
{
JObject result = JObject.Parse(resp["result"].ToString());
string hash = result["hash"].ToString();
NotifyForm notifyForm = new NotifyForm("Reveal sent\n" + hash, "Explorer", UserSettings["explorer-tx"] + hash);
notifyForm.ShowDialog();
notifyForm.Dispose();
}
buttonRevealAll.Enabled = true;
}
private async void buttonRedeemAll_Click(object sender, EventArgs e)
{
buttonRedeemAll.Enabled = false;
string content = "{\"method\": \"sendbatch\", \"params\":[[[\"REDEEM\"]]]}";
AddLog(content);
string response = await APIPost("", true, content);
if (response == "Error")
{
AddLog("Error sending batch");
NotifyForm notifyForm = new NotifyForm("Error sending batch");
notifyForm.ShowDialog();
notifyForm.Dispose();
buttonRedeemAll.Enabled = true;
return;
}
JObject resp = JObject.Parse(response);
if (resp["error"].ToString() != "")
{
AddLog("Error sending batch");
AddLog(resp["error"].ToString());
JObject error = JObject.Parse(resp["error"].ToString());
NotifyForm notifyForm = new NotifyForm("Error sending batch\n" + error["message"].ToString());
notifyForm.ShowDialog();
notifyForm.Dispose();
buttonRedeemAll.Enabled = true;
return;
}
if (resp.ContainsKey("result"))
{
JObject result = JObject.Parse(resp["result"].ToString());
string hash = result["hash"].ToString();
NotifyForm notifyForm = new NotifyForm("Batch sent\n" + hash, "Explorer", UserSettings["explorer-tx"] + hash);
notifyForm.ShowDialog();
notifyForm.Dispose();
}
buttonRedeemAll.Enabled = true;
}
private async void buttonSendAll_Click(object sender, EventArgs e)
{
buttonSendAll.Enabled = false;
string content = "{\"method\": \"sendbatch\", \"params\":[[[\"REVEAL\"],[\"REDEEM\"],[\"RENEW\"]]]}";
AddLog(content);
string response = await APIPost("", true, content);
if (response == "Error")
{
AddLog("Error sending batch");
NotifyForm notifyForm = new NotifyForm("Error sending batch");
notifyForm.ShowDialog();
notifyForm.Dispose();
buttonSendAll.Enabled = true;
return;
}
JObject resp = JObject.Parse(response);
if (resp["error"].ToString() != "")
{
AddLog("Error sending batch");
AddLog(resp["error"].ToString());
JObject error = JObject.Parse(resp["error"].ToString());
NotifyForm notifyForm = new NotifyForm("Error sending batch\n" + error["message"].ToString());
notifyForm.ShowDialog();
notifyForm.Dispose();
buttonSendAll.Enabled = true;
return;
}
if (resp.ContainsKey("result"))
{
JObject result = JObject.Parse(resp["result"].ToString());
string hash = result["hash"].ToString();
NotifyForm notifyForm = new NotifyForm("Batch sent\n" + hash, "Explorer", UserSettings["explorer-tx"] + hash);
notifyForm.ShowDialog();
notifyForm.Dispose();
}
buttonSendAll.Enabled = true;
}
#endregion #endregion
#region API #region API
HttpClient httpClient = new HttpClient(); HttpClient httpClient = new HttpClient();
@@ -925,7 +1050,6 @@ namespace FireWallet
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, "http://" + ip + ":" + port + "/" + path); HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, "http://" + ip + ":" + port + "/" + path);
req.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes("x:" + key))); req.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes("x:" + key)));
req.Content = new StringContent(content); req.Content = new StringContent(content);
// Send request // Send request
@@ -944,6 +1068,10 @@ namespace FireWallet
catch (Exception ex) catch (Exception ex)
{ {
AddLog("Post Error: " + ex.Message); AddLog("Post Error: " + ex.Message);
if (ex.Message.Contains("The request was canceled due to the configured HttpClient.Timeout"))
{
await RestartNode();
}
return "Error"; return "Error";
} }
} }
@@ -988,9 +1116,148 @@ namespace FireWallet
catch (Exception ex) catch (Exception ex)
{ {
AddLog("Get Error: " + ex.Message); AddLog("Get Error: " + ex.Message);
if (ex.Message.Contains("The request was canceled due to the configured HttpClient.Timeout"))
{
await RestartNode();
}
return "Error"; return "Error";
} }
} }
private async Task<bool> RestartNode()
{
if (!HSD)
{
NotifyForm nf = new NotifyForm("NODE Not responding");
nf.ShowDialog();
nf.Dispose();
return false;
}
this.Enabled = false;
this.Visible = false;
// Show splash
SplashScreen ss = new SplashScreen(false);
bool splash = false;
if (UserSettings.ContainsKey("hide-splash"))
{
if (UserSettings["hide-splash"] == "false")
{
// Show splash screen
ss.Show();
splash = true;
}
}
else
{
// Show splash screen
ss.Show();
splash = true;
}
// Kill node
if (HSDProcess != null)
{
HSDProcess.Kill();
AddLog("Killed HSD");
Thread.Sleep(1000);
try
{
HSDProcess.Dispose();
}
catch
{
AddLog("Dispose failed");
}
}
else AddLog("HSD was not running");
HSDProcess = new Process();
bool hideScreen = true;
if (NodeSettings.ContainsKey("HideScreen"))
{
if (NodeSettings["HideScreen"].ToLower() == "false")
{
hideScreen = false;
}
}
try
{
HSDProcess.StartInfo.CreateNoWindow = hideScreen;
if (hideScreen)
{
HSDProcess.StartInfo.RedirectStandardError = true;
HSDProcess.ErrorDataReceived += (sender, e) => AddLog("HSD Error: " + e.Data);
}
else HSDProcess.StartInfo.RedirectStandardError = false;
HSDProcess.StartInfo.RedirectStandardInput = true;
HSDProcess.StartInfo.RedirectStandardOutput = false;
HSDProcess.StartInfo.UseShellExecute = false;
HSDProcess.StartInfo.FileName = "node.exe";
if (NodeSettings.ContainsKey("HSD-command"))
{
AddLog("Using custom HSD command");
string command = NodeSettings["HSD-command"];
command = command.Replace("{default-dir}", dir + "hsd\\bin\\hsd");
string bobPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Bob\\hsd_data";
if (Directory.Exists(bobPath))
{
command = command.Replace("{Bob}", bobPath);
}
else if (command.Contains("{Bob}"))
{
AddLog("Bob not found, using default HSD command");
command = dir + "hsd\\bin\\hsd --agent=FireWallet --index-tx --index-address --api-key " + NodeSettings["Key"];
}
command = command.Replace("{key}", NodeSettings["Key"]);
HSDProcess.StartInfo.Arguments = command;
}
else
{
AddLog("Using default HSD command");
HSDProcess.StartInfo.Arguments = dir + "hsd\\bin\\hsd --agent=FireWallet --index-tx --index-address --api-key " + NodeSettings["Key"];
string bobPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Bob\\hsd_data";
if (Directory.Exists(bobPath))
{
HSDProcess.StartInfo.Arguments = HSDProcess.StartInfo.Arguments + " --prefix " + bobPath;
}
}
HSDProcess.Start();
// Wait for HSD to start
await Task.Delay(2000);
// Check if HSD is running
if (HSDProcess.HasExited)
{
AddLog("HSD Failed to start");
AddLog(HSDProcess.StandardError.ReadToEnd());
NotifyForm Notifyinstall = new NotifyForm("HSD Failed to start\nPlease check the logs");
Notifyinstall.ShowDialog();
Notifyinstall.Dispose();
// Wait for the notification to show
await Task.Delay(1000);
this.Close();
await Task.Delay(1000);
return false;
}
}
catch (Exception ex)
{
AddLog("HSD Failed to start");
AddLog(ex.Message);
this.Close();
await Task.Delay(1000);
}
if (splash) ss.CloseSplash();
this.Enabled = true;
this.Visible = true;
return true;
}
private async Task<string> GetAddress() private async Task<string> GetAddress()
{ {
string content = "{\"account\":\"default\"}"; string content = "{\"account\":\"default\"}";
@@ -1006,10 +1273,7 @@ namespace FireWallet
JObject resp = JObject.Parse(APIresponse); JObject resp = JObject.Parse(APIresponse);
return resp["address"].ToString(); return resp["address"].ToString();
} }
catch catch { return "Error"; }
{
return "Error";
}
} }
private async void GetTXHistory() private async void GetTXHistory()
@@ -1197,6 +1461,7 @@ namespace FireWallet
} }
private async Task<string> GetFee() private async Task<string> GetFee()
{ {
// This doesn't work
try try
{ {
string response = await APIPost("", false, "{\"method\": \"estimatefee\",\"params\": [ 3 ]}"); string response = await APIPost("", false, "{\"method\": \"estimatefee\",\"params\": [ 3 ]}");
@@ -1998,6 +2263,9 @@ namespace FireWallet
private async void UpdateDomains() private async void UpdateDomains()
{ {
string response = await APIGet("wallet/" + Account + "/name?own=true", true); string response = await APIGet("wallet/" + Account + "/name?own=true", true);
try
{
JArray names = JArray.Parse(response); JArray names = JArray.Parse(response);
Domains = new string[names.Count]; Domains = new string[names.Count];
DomainsRenewable = new string[names.Count]; DomainsRenewable = new string[names.Count];
@@ -2029,8 +2297,6 @@ namespace FireWallet
})); }));
break; break;
} }
foreach (JObject name in names) foreach (JObject name in names)
{ {
Domains[i] = name["name"].ToString(); Domains[i] = name["name"].ToString();
@@ -2068,7 +2334,6 @@ namespace FireWallet
// Add to domains renewable // Add to domains renewable
DomainsRenewable[renewable] = Domains[i]; DomainsRenewable[renewable] = Domains[i];
renewable++; renewable++;
} }
else else
{ {
@@ -2101,37 +2366,10 @@ namespace FireWallet
i++; i++;
} }
} }
private async void buttonRevealAll_Click(object sender, EventArgs e) catch (Exception ex)
{ {
string content = "{\"method\": \"sendreveal\"}"; AddLog("Error getting domains");
string response = await APIPost("", true, content); AddLog(ex.Message);
AddLog(response);
if (response == "Error")
{
AddLog("Error sending reveal");
NotifyForm notifyForm = new NotifyForm("Error sending reveal");
notifyForm.ShowDialog();
notifyForm.Dispose();
return;
}
JObject resp = JObject.Parse(response);
if (resp["error"].ToString() != "")
{
AddLog("Error sending reveal");
AddLog(resp["error"].ToString());
JObject error = JObject.Parse(resp["error"].ToString());
NotifyForm notifyForm = new NotifyForm("Error sending reveal\n" + error["message"].ToString());
notifyForm.ShowDialog();
notifyForm.Dispose();
return;
}
if (resp.ContainsKey("result"))
{
JObject result = JObject.Parse(resp["result"].ToString());
string hash = result["hash"].ToString();
NotifyForm notifyForm = new NotifyForm("Reveal sent\n" + hash, "Explorer", UserSettings["explorer-tx"] + hash);
notifyForm.ShowDialog();
notifyForm.Dispose();
} }
} }
private void textBoxDomainSearch_KeyDown(object sender, KeyEventArgs e) private void textBoxDomainSearch_KeyDown(object sender, KeyEventArgs e)
@@ -2377,82 +2615,6 @@ namespace FireWallet
} }
#endregion #endregion
private async void buttonRedeemAll_Click(object sender, EventArgs e)
{
buttonRedeemAll.Enabled = false;
string content = "{\"method\": \"sendbatch\", \"params\":[[[\"REDEEM\"]]]}";
AddLog(content);
string response = await APIPost("", true, content);
if (response == "Error")
{
AddLog("Error sending batch");
NotifyForm notifyForm = new NotifyForm("Error sending batch");
notifyForm.ShowDialog();
notifyForm.Dispose();
buttonRedeemAll.Enabled = true;
return;
}
JObject resp = JObject.Parse(response);
if (resp["error"].ToString() != "")
{
AddLog("Error sending batch");
AddLog(resp["error"].ToString());
JObject error = JObject.Parse(resp["error"].ToString());
NotifyForm notifyForm = new NotifyForm("Error sending batch\n" + error["message"].ToString());
notifyForm.ShowDialog();
notifyForm.Dispose();
buttonRedeemAll.Enabled = true;
return;
}
if (resp.ContainsKey("result"))
{
JObject result = JObject.Parse(resp["result"].ToString());
string hash = result["hash"].ToString();
NotifyForm notifyForm = new NotifyForm("Batch sent\n" + hash, "Explorer", UserSettings["explorer-tx"] + hash);
notifyForm.ShowDialog();
notifyForm.Dispose();
}
buttonRedeemAll.Enabled = true;
}
private async void buttonSendAll_Click(object sender, EventArgs e)
{
buttonSendAll.Enabled = false;
string content = "{\"method\": \"sendbatch\", \"params\":[[[\"REVEAL\"],[\"REDEEM\"],[\"RENEW\"]]]}";
AddLog(content);
string response = await APIPost("", true, content);
if (response == "Error")
{
AddLog("Error sending batch");
NotifyForm notifyForm = new NotifyForm("Error sending batch");
notifyForm.ShowDialog();
notifyForm.Dispose();
buttonSendAll.Enabled = true;
return;
}
JObject resp = JObject.Parse(response);
if (resp["error"].ToString() != "")
{
AddLog("Error sending batch");
AddLog(resp["error"].ToString());
JObject error = JObject.Parse(resp["error"].ToString());
NotifyForm notifyForm = new NotifyForm("Error sending batch\n" + error["message"].ToString());
notifyForm.ShowDialog();
notifyForm.Dispose();
buttonSendAll.Enabled = true;
return;
}
if (resp.ContainsKey("result"))
{
JObject result = JObject.Parse(resp["result"].ToString());
string hash = result["hash"].ToString();
NotifyForm notifyForm = new NotifyForm("Batch sent\n" + hash, "Explorer", UserSettings["explorer-tx"] + hash);
notifyForm.ShowDialog();
notifyForm.Dispose();
}
buttonSendAll.Enabled = true;
}
} }
} }

View File

@@ -224,15 +224,15 @@
{ {
"Name" = "8:Microsoft Visual Studio" "Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:FireWallet" "ProductName" = "8:FireWallet"
"ProductCode" = "8:{C118B90C-B5A0-4015-B03A-FB226DC02F54}" "ProductCode" = "8:{E636567F-DDA4-4C6E-89B0-38DC64FD5528}"
"PackageCode" = "8:{FF49B317-BBC1-40D9-9AFF-315E3AEED79C}" "PackageCode" = "8:{AEAF1ABA-01E0-4A71-A8CC-0D6DDA44E907}"
"UpgradeCode" = "8:{0C86F725-6B01-4173-AA05-3F0EDF481362}" "UpgradeCode" = "8:{0C86F725-6B01-4173-AA05-3F0EDF481362}"
"AspNetVersion" = "8:" "AspNetVersion" = "8:"
"RestartWWWService" = "11:FALSE" "RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE" "RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE" "InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:3.3" "ProductVersion" = "8:3.4"
"Manufacturer" = "8:Nathan.Woodburn/" "Manufacturer" = "8:Nathan.Woodburn/"
"ARPHELPTELEPHONE" = "8:" "ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:https://l.woodburn.au/discord" "ARPHELPLINK" = "8:https://l.woodburn.au/discord"

View File

@@ -159,6 +159,12 @@ The `{default-dir}` will be replaced with the HSD directory `%appdata%\FireWalle
The `{key}` will be replaced with the API key from the node.txt file. The `{key}` will be replaced with the API key from the node.txt file.
The `{Bob}` will be replaced with the Bob wallet HSD data directory `%appdata%\Bob\hsd_data\` this is used to sync FireWallet with Bob's accounts and also stops you needing to sync the chain twice. The `{Bob}` will be replaced with the Bob wallet HSD data directory `%appdata%\Bob\hsd_data\` this is used to sync FireWallet with Bob's accounts and also stops you needing to sync the chain twice.
Other settings are here. These are the default and if they are not in the file they revert to these values.
```yaml
HideScreen: True # Hide the HSD terminal screen (Set to False for higher reliability)
Timeout: 10 # The time in seconds to wait for any API request
```
## theme.txt ## theme.txt
This file stores the theme settings. This file stores the theme settings.
The theme is the color scheme of the application. The theme is the color scheme of the application.