Half-implement builtransaction
MODIFY
HiddenWallet/HiddenWallet.API/Controllers/WalletController.cs
HiddenWallet/HiddenWallet.API/Controllers/WalletController.cs
@@ -6,6 +6,9 @@ using Microsoft.AspNetCore.Mvc;
using HiddenWallet.API.Models;
using HiddenWallet.API.Wrappers;
using HBitcoin.KeyManagement;
+using NBitcoin;
+using System.Globalization;
+using HBitcoin.Models;
namespace HiddenWallet.API.Controllers
{
@@ -215,5 +218,57 @@ namespace HiddenWallet.API.Controllers
return new ObjectResult(new FailureResponse { Message = ex.Message, Details = ex.ToString() });
}
}
+
+ [Route("build-transaction/{account}")]
+ [HttpPost]
+ public IActionResult History(string account, [FromBody]BuildTransactionRequest request)
+ {
+ try
+ {
+ if (request == null || request.Password == null || request.Address == null || request.Amount == null || request.FeeType == null || request.AllowUnconfirmed == null)
+ {
+ return new ObjectResult(new FailureResponse { Message = "Bad request", Details = "" });
+ }
+
+ var fail = GetAccount(account, out SafeAccount safeAccount);
+ if (fail != null) return new ObjectResult(fail);
+
+ var address = BitcoinAddress.Create(request.Address, Global.WalletWrapper.Network);
+
+ Money amount = Money.Zero; // in this case all funds are sent from the wallet
+ if (request.Amount != "all")
+ {
+ var tmpAmount = new Money(decimal.Parse(request.Amount.Replace('.', ','), NumberStyles.Any, CultureInfo.InvariantCulture), MoneyUnit.BTC);
+ if (tmpAmount <= Money.Zero) throw new NotSupportedException("Amount must be > 0 or \"all\"");
+ amount = tmpAmount;
+ }
+
+ FeeType feeType;
+ if(request.FeeType.Equals("high", StringComparison.OrdinalIgnoreCase))
+ {
+ feeType = FeeType.High;
+ }
+ else if (request.FeeType.Equals("medium", StringComparison.OrdinalIgnoreCase))
+ {
+ feeType = FeeType.Medium;
+ }
+ else if (request.FeeType.Equals("low", StringComparison.OrdinalIgnoreCase))
+ {
+ feeType = FeeType.Low;
+ }
+ else
+ {
+ throw new NotSupportedException("Wrong FeeType");
+ }
+
+ var allowUnconfirmed = bool.Parse(request.AllowUnconfirmed);
+
+ return new ObjectResult(Global.WalletWrapper.BuildTransaction(request.Password, safeAccount, address, amount, feeType, allowUnconfirmed));
+ }
+ catch (Exception ex)
+ {
+ return new ObjectResult(new FailureResponse { Message = ex.Message, Details = ex.ToString() });
+ }
+ }
}
}

MODIFY
HiddenWallet/HiddenWallet.API/Wrappers/WalletWrapper.cs
HiddenWallet/HiddenWallet.API/Wrappers/WalletWrapper.cs
@@ -33,6 +33,8 @@ namespace HiddenWallet.API.Wrappers
public bool WalletExists => File.Exists(Config.WalletFilePath);
public bool IsDecrypted => !_walletJobTask.IsCompleted && _password != null;
+ public Network Network => _walletJob.Safe.Network;
+
private Money _availableAlice = Money.Zero;
private Money _availableBob = Money.Zero;
private Money _incomingAlice = Money.Zero;
@@ -265,5 +267,22 @@ namespace HiddenWallet.API.Wrappers
}
else return new StatusResponse { HeaderHeight = 0, TrackingHeight = 0, ConnectedNodeCount = 0, MemPoolTransactionCount = 0, WalletState = WalletState.NotStarted.ToString(), ChangeBump = 0 };
}
+
+ public BuildTransactionResponse BuildTransaction(string password, SafeAccount safeAccount, BitcoinAddress address, Money amount, FeeType feeType, bool allowUnconfirmed)
+ {
+ if (password != _password) throw new InvalidOperationException("Wrong password");
+ var result = _walletJob.BuildTransactionAsync(address.ScriptPubKey, amount, feeType, safeAccount, allowUnconfirmed).Result;
+
+ return new BuildTransactionResponse
+ {
+ Valid = result.Success,
+ FailingReason = result.FailingReason,
+ SpendsUnconfirmed = result.SpendsUnconfirmed,
+ Fee = result.Fee.ToString(false, true),
+ FeePercentOfSent = result.FeePercentOfSent.ToString("0.##"),
+ Hex = result.Transaction.ToHex(),
+ Transaction = result.Transaction.ToString()
+ };
+ }
}
}

MODIFY
HiddenWallet/HiddenWallet.GUI/app/html/wallet-content.html
HiddenWallet/HiddenWallet.GUI/app/html/wallet-content.html
<input id="address-to-send" type="text" class="form-control" placeholder="186n7me3QKajQZJnUsVsezVhVrSwyFCCZ" required />
<br />
<label>Amount (BTC):</label> <br />
- <button class="btn btn-sm btn-primary" onclick="setAmountToAll()">MAX</button>
+ <button class="btn btn-sm btn-primary" onclick="setAmountToAll()">MAX</button>&nbsp
<input id="amount-to-send" type="text" onkeypress='return event.charCode >= 48 && event.charCode <= 57 || event.keyCode == 46' placeholder="0.1" required />
- <br /> <br />
+ &nbsp
<label>Fee:&nbsp</label>
<label class="radio-inline">
<input id="fast-fee-radio" type="radio" name="fee-radio" checked>Fast
<label class="radio-inline">
<input id="slow-fee-radio" type="radio" name="fee-radio">Slow
</label>
- <br />
+ <br /> <br />
+ <input type="password" id="send-password" class="form-control" placeholder="Password" />
<br />
<button class="btn btn-lg btn-primary btn-block" onclick="buildTransaction()">Build Transaction</button>
</div>
\ No newline at end of file

MODIFY
HiddenWallet/HiddenWallet.GUI/app/js/hw-client.js
HiddenWallet/HiddenWallet.GUI/app/js/hw-client.js
-function httpGetWallet(path) {
+function httpGetWallet(path, returnString = false) {
var theUrl = "http://localhost:5000/api/v1/wallet/" + path;
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", theUrl, false); // false for synchronous request
xmlHttp.send(null);
- return JSON.parse(xmlHttp.responseText);
+ if (returnString) return xmlHttp.responseText;
+ else return JSON.parse(xmlHttp.responseText);
}
-function httpPostWallet(path, data) {
+function httpPostWallet(path, data, returnString = false) {
var theUrl = "http://localhost:5000/api/v1/wallet/" + path;
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", theUrl, false); // false for synchronous request
xmlHttp.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xmlHttp.send(JSON.stringify(data));
- return JSON.parse(xmlHttp.responseText);
+ if (returnString) return xmlHttp.responseText;
+ else return JSON.parse(xmlHttp.responseText);
}
\ No newline at end of file

MODIFY
HiddenWallet/HiddenWallet.GUI/app/js/wallet-phase.js
HiddenWallet/HiddenWallet.GUI/app/js/wallet-phase.js
@@ -37,6 +37,7 @@ function walletShow(menuItem) {
else if (menuItem === 'send') {
writeHint('Would you consider feeding the developer with some pizza? 186n7me3QKajQZJnUsVsezVhVrSwyFCCZ');
document.getElementById("menu").innerHTML = document.getElementById("wallet-menu-frame").contentWindow.document.getElementById("send-active").outerHTML;
+ document.getElementById("content").innerHTML = document.getElementById("wallet-content-frame").contentWindow.document.getElementById("send-content").outerHTML;
}
else if (menuItem === 'history') {
document.getElementById("menu").innerHTML = document.getElementById("wallet-menu-frame").contentWindow.document.getElementById("history-active").outerHTML;
@@ -53,7 +54,6 @@ function updateWalletContent() {
if (bobOrAlice == "alice-active") {
var resp = httpGetWallet("balances/alice");
- var balance = resp.Available;
var labelType = "default";
if (resp.Incoming > 0) labelType = "danger";
document.getElementById("balances").innerHTML = '<h4><span class="label label-' + labelType + '" style="display:block;">Available: ' + resp.Available + ' BTC, Incoming: ' + resp.Incoming + ' BTC </span></h4>';
@@ -71,16 +71,6 @@ function updateWalletContent() {
node.appendChild(textNode);
document.getElementById("receive-addresses").appendChild(node);
}
- //for (i = 0; i < resp.Addresses.length; i++) {
- // var trNode = document.createElement("tr");
- // var tdNode = document.createElement("td");
- // tdNode.innerText = resp.Addresses[i];
- // trNode.appendChild(tdNode);
- // document.getElementById("receive-addresses").appendChild(trNode);
- //}
- }
- else if (menuId === "send-active") {
- document.getElementById("content").innerHTML = document.getElementById("wallet-content-frame").contentWindow.document.getElementById("send-content").outerHTML;
}
else if (menuId === "history-active") {
document.getElementById("content").innerHTML = document.getElementById("wallet-content-frame").contentWindow.document.getElementById("history-content").outerHTML;
@@ -103,7 +93,6 @@ function updateWalletContent() {
}
else if (bobOrAlice == "bob-active") {
var resp = httpGetWallet("balances/bob");
- var balance = resp.Available;
var labelType = "default";
if (resp.Incoming > 0) labelType = "danger";
document.getElementById("balances").innerHTML = '<h4><span class="label label-' + labelType + '" style="display:block;">Available: ' + resp.Available + ' BTC, Incoming: ' + resp.Incoming + ' BTC </span></h4>';
@@ -122,9 +111,6 @@ function updateWalletContent() {
document.getElementById("receive-addresses").appendChild(node);
}
}
- else if (menuId === "send-active") {
- document.getElementById("content").innerHTML = document.getElementById("wallet-content-frame").contentWindow.document.getElementById("send-content").outerHTML;
- }
else if (menuId === "history-active") {
document.getElementById("content").innerHTML = document.getElementById("wallet-content-frame").contentWindow.document.getElementById("history-content").outerHTML;
var resp = httpGetWallet("history/bob");
@@ -156,6 +142,7 @@ function buildTransaction() {
var amount = document.getElementById("amount-to-send").value;
var fastFeeChecked = document.getElementById("fast-fee-radio").checked;
var slowFeeChecked = document.getElementById("slow-fee-radio").checked;
+ var password = document.getElementById("send-password").value;
if (!address) {
alert("Wrong address!");
@@ -170,4 +157,34 @@ function buildTransaction() {
alert("Wrong fee tpye!");
return;
}
+ // (cannot happen)
+ if (password == null) {
+ alert("Wrong fee tpye!");
+ return;
+ }
+
+ var feeType;
+ if (fastFeeChecked) feeType = "high";
+ if (slowFeeChecked) feeType = "low";
+
+ var obj = new Object();
+ obj.password = password;
+ obj.address = address;
+ obj.amount = amount;
+ obj.feeType = feeType;
+ obj.allowUnconfirmed = false;
+
+ var response;
+ var tabs = document.getElementById("tabs");
+ if (tabs.childElementCount > 0) {
+ var bobOrAlice = tabs.firstElementChild.id;
+
+ if (bobOrAlice == "alice-active") {
+ response = httpPostWallet("build-transaction/alice", obj, true);
+ }
+ if (bobOrAlice == "bob-active") {
+ response = httpPostWallet("build-transaction/bob", obj, true);
+ }
+ }
+ alert(response);
}
\ No newline at end of file

Half-implement builtransaction