diff --git a/BTCPayServer/Controllers/UIVaultController.cs b/BTCPayServer/Controllers/UIVaultController.cs index 73f0db864..db2158881 100644 --- a/BTCPayServer/Controllers/UIVaultController.cs +++ b/BTCPayServer/Controllers/UIVaultController.cs @@ -50,9 +50,10 @@ namespace BTCPayServer.Controllers if (network == null) return NotFound(); var websocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); + var vaultClient = new VaultClient(websocket); var hwi = new Hwi.HwiClient(network.NBitcoinNetwork) { - Transport = new HwiWebSocketTransport(websocket) + Transport = new VaultHWITransport(vaultClient) }; Hwi.HwiDeviceClient device = null; HwiEnumerateEntry deviceEntry = null; diff --git a/BTCPayServer/HwiWebSocketTransport.cs b/BTCPayServer/HwiWebSocketTransport.cs deleted file mode 100644 index 53446de94..000000000 --- a/BTCPayServer/HwiWebSocketTransport.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Net.WebSockets; -using System.Threading; -using System.Threading.Tasks; -using Newtonsoft.Json.Linq; - -namespace BTCPayServer -{ - public class HwiWebSocketTransport : Hwi.Transports.ITransport - { - private readonly WebSocketHelper _webSocket; - - public HwiWebSocketTransport(WebSocket webSocket) - { - _webSocket = new WebSocketHelper(webSocket); - } - public async Task SendCommandAsync(string[] arguments, CancellationToken cancel) - { - JObject request = new JObject(); - request.Add("params", new JArray(arguments)); - await _webSocket.Send(request.ToString(), cancel); - return await _webSocket.NextMessageAsync(cancel); - } - } -} diff --git a/BTCPayServer/VaultClient.cs b/BTCPayServer/VaultClient.cs new file mode 100644 index 000000000..10a54d98a --- /dev/null +++ b/BTCPayServer/VaultClient.cs @@ -0,0 +1,129 @@ +#nullable enable +using System; +using System.Net.WebSockets; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Amazon.S3.Model.Internal.MarshallTransformations; +using ExchangeSharp; +using Newtonsoft.Json.Linq; + +namespace BTCPayServer +{ + public enum VaultMessageType + { + Ok, + Error, + Processing + } + public enum VaultServices + { + HWI, + NFC + } + + public class VaultNotConnectedException : VaultException + { + public VaultNotConnectedException() : base("BTCPay Vault isn't connected") + { + + } + } + public class VaultException : Exception + { + public VaultException(string message) : base(message) + { + + } + } + public class VaultClient + { + public VaultClient(WebSocket websocket) + { + Websocket = new WebSocketHelper(websocket); + } + + public WebSocketHelper Websocket { get; } + + public async Task GetNextCommand(CancellationToken cancellationToken) + { + return await Websocket.NextMessageAsync(cancellationToken); + } + + public async Task SendMessage(JObject mess, CancellationToken cancellationToken) + { + await Websocket.Send(mess.ToString(), cancellationToken); + } + + public Task Show(VaultMessageType type, string message, CancellationToken cancellationToken) + { + return Show(type, message, null, cancellationToken); + } + public async Task Show(VaultMessageType type, string message, string? debug, CancellationToken cancellationToken) + { + + await SendMessage(new JObject() + { + ["command"] = "showMessage", + ["message"] = message, + ["type"] = type.ToString(), + ["debug"] = debug + }, cancellationToken); + } + + string? _ServiceUri; + public async Task AskPermission(VaultServices service, CancellationToken cancellationToken) + { + var uri = service switch + { + VaultServices.HWI => "http://127.0.0.1:65092/hwi-bridge/v1", + VaultServices.NFC => "http://127.0.0.1:65092/nfc-bridge/v1", + _ => throw new NotSupportedException() + }; + + await this.SendMessage(new JObject() + { + ["command"] = "sendRequest", + ["uri"] = uri + "/request-permission" + }, cancellationToken); + var result = await GetNextMessage(cancellationToken); + if (result["httpCode"] is { } p) + { + var ok = p.Value() == 200; + if (ok) + _ServiceUri = uri; + return ok; + } + return null; + } + + public async Task SendVaultRequest(string? path, JObject? body, CancellationToken cancellationToken) + { + var isAbsolute = path is not null && Uri.IsWellFormedUriString(path, UriKind.Absolute); + var query = new JObject() + { + ["command"] = "sendRequest", + ["uri"] = isAbsolute ? path : _ServiceUri + path + }; + if (body is not null) + query["body"] = body; + await this.SendMessage(query, cancellationToken); + var resp = await GetNextMessage(cancellationToken); + if (resp["httpCode"] is not { } p) + throw new VaultNotConnectedException(); + if (p.Value() != 200) + throw new VaultException($"Unexpected response code from vault {p.Value()}"); + return resp["body"] as JToken; + } + + public async Task GetNextMessage(CancellationToken cancellationToken) + { + return JObject.Parse(await this.Websocket.NextMessageAsync(cancellationToken)); + } + + public Task SendSimpleMessage(string command, CancellationToken cancellationToken) + { + return SendMessage(new JObject() { ["command"] = command }, cancellationToken); + } + } +} diff --git a/BTCPayServer/VaultHWITransport.cs b/BTCPayServer/VaultHWITransport.cs new file mode 100644 index 000000000..143e42d18 --- /dev/null +++ b/BTCPayServer/VaultHWITransport.cs @@ -0,0 +1,26 @@ +using System.Net.WebSockets; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; + +namespace BTCPayServer +{ + public class VaultHWITransport : Hwi.Transports.ITransport + { + private readonly VaultClient _vaultClient; + + public VaultHWITransport(VaultClient vaultClient) + { + _vaultClient = vaultClient; + } + public async Task SendCommandAsync(string[] arguments, CancellationToken cancel) + { + var resp = await _vaultClient.SendVaultRequest("http://127.0.0.1:65092/hwi-bridge/v1", + new JObject() + { + ["params"] = new JArray(arguments) + }, cancel); + return (string)((JValue)resp).Value; + } + } +} diff --git a/BTCPayServer/Views/Shared/VaultElements.cshtml b/BTCPayServer/Views/Shared/VaultElements.cshtml index 4326bc534..42878a246 100644 --- a/BTCPayServer/Views/Shared/VaultElements.cshtml +++ b/BTCPayServer/Views/Shared/VaultElements.cshtml @@ -8,6 +8,12 @@
+
+ +
+
+ +