Make sendtransaction window smarter
MODIFY
HiddenWallet.Daemon/HiddenWallet.Daemon.csproj
HiddenWallet.Daemon/HiddenWallet.Daemon.csproj
<None Remove="wwwroot\**" />
</ItemGroup>
- <ItemGroup>
- <Folder Include="Models\" />
- </ItemGroup>
-
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" />

MODIFY
HiddenWallet.Daemon/Models/BuildTransactionResponse.cs
HiddenWallet.Daemon/Models/BuildTransactionResponse.cs
@@ -13,5 +13,11 @@ namespace HiddenWallet.Daemon.Models
public string FeePercentOfSent { get; set; }
public string Hex { get; set; }
public string Transaction { get; set; }
+ public string ActiveOutputAddress { get; set; }
+ public string ActiveOutputAmount { get; set; }
+ public string ChangeOutputAddress { get; set; }
+ public string ChangeOutputAmount { get; set; }
+ public int NumberOfInputs { get; set; }
+ public TransactionInputModel[] Inputs { get; set; }
}
}

MODIFY
HiddenWallet.Daemon/Wrappers/WalletWrapper.cs
HiddenWallet.Daemon/Wrappers/WalletWrapper.cs
@@ -272,12 +272,30 @@ namespace HiddenWallet.Daemon.Wrappers
if (result.Success)
{
+ var inputs = new List<TransactionInputModel>();
+ foreach(Coin coin in result.SpentCoins)
+ {
+ inputs.Add(new TransactionInputModel
+ {
+ Amount = coin.Amount.ToString(false, true),
+ Address = coin.ScriptPubKey.GetDestinationAddress(Network).ToString(),
+ Hash = coin.Outpoint.Hash.ToString(),
+ Index = (int)coin.Outpoint.N
+ });
+ }
+
return new BuildTransactionResponse
{
SpendsUnconfirmed = result.SpendsUnconfirmed,
Fee = result.Fee.ToString(false, true),
FeePercentOfSent = result.FeePercentOfSent.ToString("0.##"),
Hex = result.Transaction.ToHex(),
+ ActiveOutputAddress = result.ActiveOutput.ScriptPubKey.GetDestinationAddress(Network).ToString(),
+ ActiveOutputAmount = result.ActiveOutput.Value.ToString(false, true),
+ ChangeOutputAddress = result.ChangeOutput?.ScriptPubKey?.GetDestinationAddress(Network)?.ToString() ?? "",
+ ChangeOutputAmount = result.ChangeOutput?.Value?.ToString(false, true) ?? "0",
+ NumberOfInputs = result.SpentCoins.Count(),
+ Inputs = inputs.ToArray(),
Transaction = result.Transaction.ToString()
};
}

MODIFY
HiddenWallet.Gui/HiddenWallet.GUI.njsproj
HiddenWallet.Gui/HiddenWallet.GUI.njsproj
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<Name>HiddenWallet.Gui</Name>
<RootNamespace>HiddenWallet.GUI</RootNamespace>
+ <EnableTypeScript>true</EnableTypeScript>
+ <TypeScriptSourceMap>true</TypeScriptSourceMap>
+ <TypeScriptModuleKind>CommonJS</TypeScriptModuleKind>
+ <ToolsVersionPromptShown>0.0</ToolsVersionPromptShown>
+ <TypeScriptToolsVersion>2.3</TypeScriptToolsVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<ItemGroup>
<TypeScriptCompile Include="app\js\broadcast-window.ts" />
<TypeScriptCompile Include="app\js\cleanup.ts" />
+ <TypeScriptCompile Include="app\js\copypaste.ts" />
<TypeScriptCompile Include="app\js\decryption-phase.ts" />
<TypeScriptCompile Include="app\js\default.ts" />
<TypeScriptCompile Include="app\js\hw-client.ts" />

MODIFY
HiddenWallet.Gui/app/html/broadcast-transaction-window.html
HiddenWallet.Gui/app/html/broadcast-transaction-window.html
<body>
<div class="container">
<h4><span class="label label-success">Transaction built successfully</span></h4>
+ <h4>
+ <span class="label label-info">Spending</span>
+ <span class="label label-success" id="number-of-inputs"></span>
+ <span class="label label-info" id="coins-label"></span>
+ </h4>
+ <h4>
+ <span class="label label-info">Sending</span>
+ <span class="label label-success" id="active-output-amount"></span>
+ <span class="label label-info">BTC to</span>
+ <span class="label label-success" id="active-output-address"></span>
+ </h4>
+ <h4>
+ <span class="label label-info">Receiving</span>
+ <span class="label label-success" id="change-output-amount"></span>
+ <span class="label label-info">BTC change</span>
+ </h4>
<h4>
<span class="label label-info">Fee:</span>
- <span class="label" id="fee"></span>
+ <span class="label label-success" id="fee"></span>
<span class="label label-info">BTC</span>
</h4>
<h4>
<span class="label label-info">Fee percentage of sending amount:</span>
- <span class="label" id="fee-percent-of-sent"></span>
+ <span class="label label-success" id="fee-percent-of-sent"></span>
<span class="label label-info">%</span>
</h4>
<h4>
<span class="label label-info">Does it spend unconfirmed output?</span>
- <span class="label" id="spends-unconfirmed"></span>
+ <span class="label label-success" id="spends-unconfirmed"></span>
</h4>
<h4><span class="label label-info">Programmer nonsense:</span> </h4>
<textarea id= "transaction" rows="9" cols="76" disabled></textarea><br />
<span class="mdi mdi-tor"></span> Broadcast
</button>
</div>
+ <script src="../js/copypaste.js"></script>
<script src="../js/broadcast-window.js"></script>
<script src="../js/hw-client.js"></script>
</body>

MODIFY
HiddenWallet.Gui/app/js/broadcast-window.ts
HiddenWallet.Gui/app/js/broadcast-window.ts
@@ -8,32 +8,59 @@ require('electron').ipcRenderer.on('broadcast-response', (event, response) => {
hex = response.Hex;
let fee: HTMLElement = document.getElementById("fee");
+ let activeOutputAmount: HTMLElement = document.getElementById("active-output-amount");
+ let changeOutputAmount: HTMLElement = document.getElementById("change-output-amount");
+ let activeOutputAddress: HTMLElement = document.getElementById("active-output-address");
let feePercent: HTMLElement = document.getElementById("fee-percent-of-sent");
let spends: HTMLElement = document.getElementById("spends-unconfirmed");
let transaction: HTMLElement = document.getElementById("transaction");
+ let numberOfInputs: HTMLElement = document.getElementById("number-of-inputs");
+ let coinsLabel: HTMLElement = document.getElementById("coins-label");
fee.innerText = response.Fee;
- if (parseFloat(response.FeePercentOfSent) > 1) {
+ if (parseFloat(response.FeePercentOfSent) > 5) {
+ feePercent.classList.remove("label-success");
feePercent.classList.add("label-danger");
+ fee.classList.remove("label-success");
fee.classList.add("label-danger");
}
- else {
+ else if (parseFloat(response.FeePercentOfSent) > 1) {
+ feePercent.classList.remove("label-success");
feePercent.classList.add("label-warning");
+ fee.classList.remove("label-success");
fee.classList.add("label-warning");
}
feePercent.innerText = response.FeePercentOfSent;
if (response.SpendsUnconfirmed == true) {
+ spends.classList.remove("label-success");
spends.classList.add("label-danger");
}
+
+ if (response.NumberOfInputs > 1) {
+ coinsLabel.innerText = "coins";
+ numberOfInputs.classList.remove("label-success");
+ numberOfInputs.classList.add("label-danger");
+ }
else {
- spends.classList.add("label-warning");
+ coinsLabel.innerText = "coin";
}
+ numberOfInputs.innerText = response.NumberOfInputs;
spends.innerText = response.SpendsUnconfirmed;
+ activeOutputAmount.innerText = response.ActiveOutputAmount;
+ activeOutputAddress.innerText = response.ActiveOutputAddress;
+
+ if (response.ChangeOutputAmount != 0)
+ {
+ changeOutputAmount.classList.remove("label-success");
+ changeOutputAmount.classList.add("label-warning");
+ }
+ changeOutputAmount.innerText = response.ChangeOutputAmount;
+
transaction.innerText =
`${response.Transaction}
@@ -62,6 +89,7 @@ function broadcastTransaction() {
if (result.Success) {
alert("SUCCESS! Transaction is successfully broadcasted!");
+ window.close();
}
else {
let failText = "FAIL! " + result.Message;
@@ -75,6 +103,5 @@ Details: ${result.Details}`;
}
alert(failText);
}
- window.close();
});
}
\ No newline at end of file

ADD
HiddenWallet.Gui/app/js/copypaste.ts
+const electron = require('electron');
+const remote = electron.remote;
+const Menu = remote.Menu;
+
+const EditMenu = Menu.buildFromTemplate([{
+ label: 'Copy',
+ role: 'copy',
+}, {
+ label: 'Paste',
+ role: 'paste',
+},
+]);
+
+const CopyMenu = Menu.buildFromTemplate([{
+ label: 'Copy',
+ role: 'copy',
+},
+]);
+
+document.body.addEventListener('contextmenu', (mouseEvent: MouseEvent) => {
+ mouseEvent.preventDefault();
+ mouseEvent.stopPropagation();
+
+ let node: HTMLInputElement = mouseEvent.target as HTMLInputElement;
+
+ while (node) {
+ if ((node.nodeName.match(/^(input|textarea)$/i) || node.isContentEditable) && !node.disabled) {
+ EditMenu.popup(remote.getCurrentWindow());
+ break;
+ }
+ else {
+ CopyMenu.popup(remote.getCurrentWindow());
+ break;
+ }
+ }
+});
+
+// Close the dropdown menu if the user clicks outside of it
+window.onclick = function (mouseEvent: MouseEvent) {
+ let eventTarget: HTMLElement = mouseEvent.target as HTMLElement;
+
+ if (eventTarget.className !== 'dropbtn') {
+
+ var dropdowns: HTMLCollectionOf<Element> = document.getElementsByClassName("dropdown-content");
+
+ for (let i: number = 0; i < dropdowns.length; i++) {
+ var openDropdown: Element = dropdowns[i];
+ if (openDropdown.classList.contains('show')) {
+ openDropdown.classList.remove('show');
+ }
+ }
+ }
+}

MODIFY
HiddenWallet.Gui/app/js/default.ts
HiddenWallet.Gui/app/js/default.ts
@@ -49,57 +49,3 @@ function writeHint(message: string) {
let hint: HTMLElement = document.getElementById('hint');
hint.innerHTML = message;
}
\ No newline at end of file
-
-const electron = require('electron');
-const remote = electron.remote;
-const Menu = remote.Menu;
-
-const EditMenu = Menu.buildFromTemplate([{
- label: 'Copy',
- role: 'copy',
-}, {
- label: 'Paste',
- role: 'paste',
-},
-]);
-
-const CopyMenu = Menu.buildFromTemplate([{
- label: 'Copy',
- role: 'copy',
-},
-]);
-
-document.body.addEventListener('contextmenu', (mouseEvent: MouseEvent) => {
- mouseEvent.preventDefault();
- mouseEvent.stopPropagation();
-
- let node: HTMLInputElement = mouseEvent.target as HTMLInputElement;
-
- while (node) {
- if (node.nodeName.match(/^(input|textarea)$/i) || node.isContentEditable) {
- EditMenu.popup(remote.getCurrentWindow());
- break;
- }
- else {
- CopyMenu.popup(remote.getCurrentWindow());
- break;
- }
- }
-});
-
-// Close the dropdown menu if the user clicks outside of it
-window.onclick = function (mouseEvent: MouseEvent) {
- let eventTarget: HTMLElement = mouseEvent.target as HTMLElement;
-
- if (eventTarget.className !== 'dropbtn') {
-
- var dropdowns: HTMLCollectionOf<Element> = document.getElementsByClassName("dropdown-content");
-
- for (let i: number = 0; i < dropdowns.length; i++) {
- var openDropdown: Element = dropdowns[i];
- if (openDropdown.classList.contains('show')) {
- openDropdown.classList.remove('show');
- }
- }
- }
-}

MODIFY
HiddenWallet.Gui/app/js/wallet-phase.ts
HiddenWallet.Gui/app/js/wallet-phase.ts
@@ -312,7 +312,7 @@ function buildTransaction() {
const remote = require('electron').remote;
const window = remote.getCurrentWindow();
const BrowserWindow = remote.BrowserWindow;
- let broadcastWindow = new BrowserWindow({ width: 600, height: 400, frame: false, resizable: false, alwaysOnTop: true, parent: window, icon: __dirname + '/app/assets/TumbleBit.png' });
+ let broadcastWindow = new BrowserWindow({ width: 600, height: 500, frame: false, resizable: false, alwaysOnTop: true, parent: window, icon: __dirname + '/app/assets/TumbleBit.png' });
broadcastWindow.show();
broadcastWindow.focus();
broadcastWindow.loadURL(`file://${__dirname}/app/html/broadcast-transaction-window.html`);

MODIFY
HiddenWallet.Gui/index.html
HiddenWallet.Gui/index.html
<script src="app/js/hw-client.js"></script>
<script src="app/js/default.js"></script>
+ <script src="app/js/copypaste.js"></script>
<script src="app/js/settings.js"></script>
<script src="app/js/status.js"></script>
<script src="app/js/decryption-phase.js"></script>

Make sendtransaction window smarter