From f32e225fa6ba0c80776a514fb5945afdc67050d4 Mon Sep 17 00:00:00 2001 From: lepipele Date: Thu, 26 Apr 2018 10:49:18 -0500 Subject: [PATCH 01/45] Generating Lnd wrapper using NSwag https://github.com/lightningnetwork/lnd/blob/master/lnrpc/rpc.swagger.json --- BTCPayServer/BTCPayServer.csproj | 1 + .../Payments/Lightning/Lnd/LndrpcClient.cs | 8740 +++++++++++++++++ 2 files changed, 8741 insertions(+) create mode 100644 BTCPayServer/Payments/Lightning/Lnd/LndrpcClient.cs diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index f98b986e4..e070297ff 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -113,6 +113,7 @@ + diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndrpcClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndrpcClient.cs new file mode 100644 index 000000000..37ddd82d9 --- /dev/null +++ b/BTCPayServer/Payments/Lightning/Lnd/LndrpcClient.cs @@ -0,0 +1,8740 @@ +//---------------------- +// +// Generated using the NSwag toolchain v11.11.1.0 (NJsonSchema v9.9.11.0 (Newtonsoft.Json v9.0.0.0)) (http://NSwag.org) +// +//---------------------- + +namespace MyNamespace +{ + #pragma warning disable // Disable all warnings + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "11.11.1.0")] + public partial class Client + { + private System.Lazy _settings; + private string _baseUrl = ""; + + public Client(string baseUrl) + { + BaseUrl = baseUrl; + _settings = new System.Lazy(() => + { + var settings = new Newtonsoft.Json.JsonSerializerSettings(); + UpdateJsonSerializerSettings(settings); + return settings; + }); + } + + public string BaseUrl + { + get { return _baseUrl; } + set { _baseUrl = value; } + } + + partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); + partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); + + /// * lncli: `walletbalance` + /// WalletBalance returns total unspent outputs(confirmed and unconfirmed), all + /// confirmed unspent outputs and all unconfirmed unspent outputs under control + /// of the wallet. + /// A server side error occurred. + public System.Threading.Tasks.Task WalletBalanceAsync() + { + return WalletBalanceAsync(System.Threading.CancellationToken.None); + } + + /// * lncli: `walletbalance` + /// WalletBalance returns total unspent outputs(confirmed and unconfirmed), all + /// confirmed unspent outputs and all unconfirmed unspent outputs under control + /// of the wallet. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task WalletBalanceAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/balance/blockchain"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcWalletBalanceResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcWalletBalanceResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `channelbalance` + /// ChannelBalance returns the total funds available across all open channels + /// in satoshis. + /// A server side error occurred. + public System.Threading.Tasks.Task ChannelBalanceAsync() + { + return ChannelBalanceAsync(System.Threading.CancellationToken.None); + } + + /// * lncli: `channelbalance` + /// ChannelBalance returns the total funds available across all open channels + /// in satoshis. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task ChannelBalanceAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/balance/channels"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcChannelBalanceResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcChannelBalanceResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `listchannels` + /// ListChannels returns a description of all the open channels that this node + /// is a participant in. + /// A server side error occurred. + public System.Threading.Tasks.Task ListChannelsAsync(bool? active_only, bool? inactive_only, bool? public_only, bool? private_only) + { + return ListChannelsAsync(active_only, inactive_only, public_only, private_only, System.Threading.CancellationToken.None); + } + + /// * lncli: `listchannels` + /// ListChannels returns a description of all the open channels that this node + /// is a participant in. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task ListChannelsAsync(bool? active_only, bool? inactive_only, bool? public_only, bool? private_only, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/channels?"); + if (active_only != null) urlBuilder_.Append("active_only=").Append(System.Uri.EscapeDataString(System.Convert.ToString(active_only.Value, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + if (inactive_only != null) urlBuilder_.Append("inactive_only=").Append(System.Uri.EscapeDataString(System.Convert.ToString(inactive_only.Value, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + if (public_only != null) urlBuilder_.Append("public_only=").Append(System.Uri.EscapeDataString(System.Convert.ToString(public_only.Value, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + if (private_only != null) urlBuilder_.Append("private_only=").Append(System.Uri.EscapeDataString(System.Convert.ToString(private_only.Value, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + urlBuilder_.Length--; + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcListChannelsResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcListChannelsResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * + /// OpenChannelSync is a synchronous version of the OpenChannel RPC call. This + /// call is meant to be consumed by clients to the REST proxy. As with all + /// other sync calls, all byte slices are intended to be populated as hex + /// encoded strings. + /// A server side error occurred. + public System.Threading.Tasks.Task OpenChannelSyncAsync(LnrpcOpenChannelRequest body) + { + return OpenChannelSyncAsync(body, System.Threading.CancellationToken.None); + } + + /// * + /// OpenChannelSync is a synchronous version of the OpenChannel RPC call. This + /// call is meant to be consumed by clients to the REST proxy. As with all + /// other sync calls, all byte slices are intended to be populated as hex + /// encoded strings. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task OpenChannelSyncAsync(LnrpcOpenChannelRequest body, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/channels"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value)); + content_.Headers.ContentType.MediaType = "application/json"; + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcChannelPoint); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcChannelPoint); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `pendingchannels` + /// PendingChannels returns a list of all the channels that are currently + /// considered "pending". A channel is pending if it has finished the funding + /// workflow and is waiting for confirmations for the funding txn, or is in the + /// process of closure, either initiated cooperatively or non-cooperatively. + /// A server side error occurred. + public System.Threading.Tasks.Task PendingChannelsAsync() + { + return PendingChannelsAsync(System.Threading.CancellationToken.None); + } + + /// * lncli: `pendingchannels` + /// PendingChannels returns a list of all the channels that are currently + /// considered "pending". A channel is pending if it has finished the funding + /// workflow and is waiting for confirmations for the funding txn, or is in the + /// process of closure, either initiated cooperatively or non-cooperatively. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task PendingChannelsAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/channels/pending"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcPendingChannelsResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcPendingChannelsResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * + /// SendPaymentSync is the synchronous non-streaming version of SendPayment. + /// This RPC is intended to be consumed by clients of the REST proxy. + /// Additionally, this RPC expects the destination's public key and the payment + /// hash (if any) to be encoded as hex strings. + /// A server side error occurred. + public System.Threading.Tasks.Task SendPaymentSyncAsync(LnrpcSendRequest body) + { + return SendPaymentSyncAsync(body, System.Threading.CancellationToken.None); + } + + /// * + /// SendPaymentSync is the synchronous non-streaming version of SendPayment. + /// This RPC is intended to be consumed by clients of the REST proxy. + /// Additionally, this RPC expects the destination's public key and the payment + /// hash (if any) to be encoded as hex strings. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task SendPaymentSyncAsync(LnrpcSendRequest body, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/channels/transactions"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value)); + content_.Headers.ContentType.MediaType = "application/json"; + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcSendResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcSendResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `closechannel` + /// CloseChannel attempts to close an active channel identified by its channel + /// outpoint (ChannelPoint). The actions of this method can additionally be + /// augmented to attempt a force close after a timeout period in the case of an + /// inactive peer. If a non-force close (cooperative closure) is requested, + /// then the user can specify either a target number of blocks until the + /// closure transaction is confirmed, or a manual fee rate. If neither are + /// specified, then a default lax, block confirmation target is used. + /// (streaming responses) + /// A server side error occurred. + public System.Threading.Tasks.Task CloseChannelAsync(string channel_point_funding_txid_str, long channel_point_output_index) + { + return CloseChannelAsync(channel_point_funding_txid_str, channel_point_output_index, System.Threading.CancellationToken.None); + } + + /// * lncli: `closechannel` + /// CloseChannel attempts to close an active channel identified by its channel + /// outpoint (ChannelPoint). The actions of this method can additionally be + /// augmented to attempt a force close after a timeout period in the case of an + /// inactive peer. If a non-force close (cooperative closure) is requested, + /// then the user can specify either a target number of blocks until the + /// closure transaction is confirmed, or a manual fee rate. If neither are + /// specified, then a default lax, block confirmation target is used. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// (streaming responses) + /// A server side error occurred. + public async System.Threading.Tasks.Task CloseChannelAsync(string channel_point_funding_txid_str, long channel_point_output_index, System.Threading.CancellationToken cancellationToken) + { + if (channel_point_funding_txid_str == null) + throw new System.ArgumentNullException("channel_point_funding_txid_str"); + + if (channel_point_output_index == null) + throw new System.ArgumentNullException("channel_point_output_index"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/channels/{channel_point.funding_txid_str}/{channel_point.output_index}"); + urlBuilder_.Replace("{channel_point.funding_txid_str}", System.Uri.EscapeDataString(System.Convert.ToString(channel_point_funding_txid_str, System.Globalization.CultureInfo.InvariantCulture))); + urlBuilder_.Replace("{channel_point.output_index}", System.Uri.EscapeDataString(System.Convert.ToString(channel_point_output_index, System.Globalization.CultureInfo.InvariantCulture))); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("DELETE"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcCloseStatusUpdate); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcCloseStatusUpdate); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `updatechanpolicy` + /// UpdateChannelPolicy allows the caller to update the fee schedule and + /// channel policies for all channels globally, or a particular channel. + /// A server side error occurred. + public System.Threading.Tasks.Task UpdateChannelPolicyAsync(LnrpcPolicyUpdateRequest body) + { + return UpdateChannelPolicyAsync(body, System.Threading.CancellationToken.None); + } + + /// * lncli: `updatechanpolicy` + /// UpdateChannelPolicy allows the caller to update the fee schedule and + /// channel policies for all channels globally, or a particular channel. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task UpdateChannelPolicyAsync(LnrpcPolicyUpdateRequest body, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/chanpolicy"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value)); + content_.Headers.ContentType.MediaType = "application/json"; + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(object); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(object); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `feereport` + /// FeeReport allows the caller to obtain a report detailing the current fee + /// schedule enforced by the node globally for each channel. + /// A server side error occurred. + public System.Threading.Tasks.Task FeeReportAsync() + { + return FeeReportAsync(System.Threading.CancellationToken.None); + } + + /// * lncli: `feereport` + /// FeeReport allows the caller to obtain a report detailing the current fee + /// schedule enforced by the node globally for each channel. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task FeeReportAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/fees"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcFeeReportResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcFeeReportResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * + /// GenSeed is the first method that should be used to instantiate a new lnd + /// instance. This method allows a caller to generate a new aezeed cipher seed + /// given an optional passphrase. If provided, the passphrase will be necessary + /// to decrypt the cipherseed to expose the internal wallet seed. + /// * + /// aezeed_passphrase is an optional user provided passphrase that will be used + /// to encrypt the generated aezeed cipher seed. + /// * + /// seed_entropy is an optional 16-bytes generated via CSPRNG. If not + /// specified, then a fresh set of randomness will be used to create the seed. + /// A server side error occurred. + public System.Threading.Tasks.Task GenSeedAsync(byte[] aezeed_passphrase, byte[] seed_entropy) + { + return GenSeedAsync(aezeed_passphrase, seed_entropy, System.Threading.CancellationToken.None); + } + + /// * + /// GenSeed is the first method that should be used to instantiate a new lnd + /// instance. This method allows a caller to generate a new aezeed cipher seed + /// given an optional passphrase. If provided, the passphrase will be necessary + /// to decrypt the cipherseed to expose the internal wallet seed. + /// * + /// aezeed_passphrase is an optional user provided passphrase that will be used + /// to encrypt the generated aezeed cipher seed. + /// * + /// seed_entropy is an optional 16-bytes generated via CSPRNG. If not + /// specified, then a fresh set of randomness will be used to create the seed. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task GenSeedAsync(byte[] aezeed_passphrase, byte[] seed_entropy, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/genseed?"); + if (aezeed_passphrase != null) urlBuilder_.Append("aezeed_passphrase=").Append(System.Uri.EscapeDataString(System.Convert.ToString(aezeed_passphrase, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + if (seed_entropy != null) urlBuilder_.Append("seed_entropy=").Append(System.Uri.EscapeDataString(System.Convert.ToString(seed_entropy, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + urlBuilder_.Length--; + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcGenSeedResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcGenSeedResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `getinfo` + /// GetInfo returns general information concerning the lightning node including + /// it's identity pubkey, alias, the chains it is connected to, and information + /// concerning the number of open+pending channels. + /// A server side error occurred. + public System.Threading.Tasks.Task GetInfoAsync() + { + return GetInfoAsync(System.Threading.CancellationToken.None); + } + + /// * lncli: `getinfo` + /// GetInfo returns general information concerning the lightning node including + /// it's identity pubkey, alias, the chains it is connected to, and information + /// concerning the number of open+pending channels. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task GetInfoAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/getinfo"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcGetInfoResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcGetInfoResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `describegraph` + /// DescribeGraph returns a description of the latest graph state from the + /// point of view of the node. The graph information is partitioned into two + /// components: all the nodes/vertexes, and all the edges that connect the + /// vertexes themselves. As this is a directed graph, the edges also contain + /// the node directional specific routing policy which includes: the time lock + /// delta, fee information, etc. + /// A server side error occurred. + public System.Threading.Tasks.Task DescribeGraphAsync() + { + return DescribeGraphAsync(System.Threading.CancellationToken.None); + } + + /// * lncli: `describegraph` + /// DescribeGraph returns a description of the latest graph state from the + /// point of view of the node. The graph information is partitioned into two + /// components: all the nodes/vertexes, and all the edges that connect the + /// vertexes themselves. As this is a directed graph, the edges also contain + /// the node directional specific routing policy which includes: the time lock + /// delta, fee information, etc. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task DescribeGraphAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/graph"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcChannelGraph); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcChannelGraph); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `getchaninfo` + /// GetChanInfo returns the latest authenticated network announcement for the + /// given channel identified by its channel ID: an 8-byte integer which + /// uniquely identifies the location of transaction's funding output within the + /// blockchain. + /// A server side error occurred. + public System.Threading.Tasks.Task GetChanInfoAsync(string chan_id) + { + return GetChanInfoAsync(chan_id, System.Threading.CancellationToken.None); + } + + /// * lncli: `getchaninfo` + /// GetChanInfo returns the latest authenticated network announcement for the + /// given channel identified by its channel ID: an 8-byte integer which + /// uniquely identifies the location of transaction's funding output within the + /// blockchain. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task GetChanInfoAsync(string chan_id, System.Threading.CancellationToken cancellationToken) + { + if (chan_id == null) + throw new System.ArgumentNullException("chan_id"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/graph/edge/{chan_id}"); + urlBuilder_.Replace("{chan_id}", System.Uri.EscapeDataString(System.Convert.ToString(chan_id, System.Globalization.CultureInfo.InvariantCulture))); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcChannelEdge); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcChannelEdge); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `getnetworkinfo` + /// GetNetworkInfo returns some basic stats about the known channel graph from + /// the point of view of the node. + /// A server side error occurred. + public System.Threading.Tasks.Task GetNetworkInfoAsync() + { + return GetNetworkInfoAsync(System.Threading.CancellationToken.None); + } + + /// * lncli: `getnetworkinfo` + /// GetNetworkInfo returns some basic stats about the known channel graph from + /// the point of view of the node. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task GetNetworkInfoAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/graph/info"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcNetworkInfo); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcNetworkInfo); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `getnodeinfo` + /// GetNodeInfo returns the latest advertised, aggregated, and authenticated + /// channel information for the specified node identified by its public key. + /// A server side error occurred. + public System.Threading.Tasks.Task GetNodeInfoAsync(string pub_key) + { + return GetNodeInfoAsync(pub_key, System.Threading.CancellationToken.None); + } + + /// * lncli: `getnodeinfo` + /// GetNodeInfo returns the latest advertised, aggregated, and authenticated + /// channel information for the specified node identified by its public key. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task GetNodeInfoAsync(string pub_key, System.Threading.CancellationToken cancellationToken) + { + if (pub_key == null) + throw new System.ArgumentNullException("pub_key"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/graph/node/{pub_key}"); + urlBuilder_.Replace("{pub_key}", System.Uri.EscapeDataString(System.Convert.ToString(pub_key, System.Globalization.CultureInfo.InvariantCulture))); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcNodeInfo); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcNodeInfo); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `queryroutes` + /// QueryRoutes attempts to query the daemon's Channel Router for a possible + /// route to a target destination capable of carrying a specific amount of + /// satoshis. The retuned route contains the full details required to craft and + /// send an HTLC, also including the necessary information that should be + /// present within the Sphinx packet encapsulated within the HTLC. + /// / The max number of routes to return. + /// A server side error occurred. + public System.Threading.Tasks.Task QueryRoutesAsync(string pub_key, string amt, int? num_routes) + { + return QueryRoutesAsync(pub_key, amt, num_routes, System.Threading.CancellationToken.None); + } + + /// * lncli: `queryroutes` + /// QueryRoutes attempts to query the daemon's Channel Router for a possible + /// route to a target destination capable of carrying a specific amount of + /// satoshis. The retuned route contains the full details required to craft and + /// send an HTLC, also including the necessary information that should be + /// present within the Sphinx packet encapsulated within the HTLC. + /// / The max number of routes to return. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task QueryRoutesAsync(string pub_key, string amt, int? num_routes, System.Threading.CancellationToken cancellationToken) + { + if (pub_key == null) + throw new System.ArgumentNullException("pub_key"); + + if (amt == null) + throw new System.ArgumentNullException("amt"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/graph/routes/{pub_key}/{amt}?"); + urlBuilder_.Replace("{pub_key}", System.Uri.EscapeDataString(System.Convert.ToString(pub_key, System.Globalization.CultureInfo.InvariantCulture))); + urlBuilder_.Replace("{amt}", System.Uri.EscapeDataString(System.Convert.ToString(amt, System.Globalization.CultureInfo.InvariantCulture))); + if (num_routes != null) urlBuilder_.Append("num_routes=").Append(System.Uri.EscapeDataString(System.Convert.ToString(num_routes.Value, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + urlBuilder_.Length--; + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcQueryRoutesResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcQueryRoutesResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * + /// InitWallet is used when lnd is starting up for the first time to fully + /// initialize the daemon and its internal wallet. At the very least a wallet + /// password must be provided. This will be used to encrypt sensitive material + /// on disk. + /// A server side error occurred. + public System.Threading.Tasks.Task InitWalletAsync(LnrpcInitWalletRequest body) + { + return InitWalletAsync(body, System.Threading.CancellationToken.None); + } + + /// * + /// InitWallet is used when lnd is starting up for the first time to fully + /// initialize the daemon and its internal wallet. At the very least a wallet + /// password must be provided. This will be used to encrypt sensitive material + /// on disk. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task InitWalletAsync(LnrpcInitWalletRequest body, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/initwallet"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value)); + content_.Headers.ContentType.MediaType = "application/json"; + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(object); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(object); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `lookupinvoice` + /// LookupInvoice attempts to look up an invoice according to its payment hash. + /// The passed payment hash *must* be exactly 32 bytes, if not, an error is + /// returned. + /// / The payment hash of the invoice to be looked up. + /// A server side error occurred. + public System.Threading.Tasks.Task LookupInvoiceAsync(string r_hash_str, byte[] r_hash) + { + return LookupInvoiceAsync(r_hash_str, r_hash, System.Threading.CancellationToken.None); + } + + /// * lncli: `lookupinvoice` + /// LookupInvoice attempts to look up an invoice according to its payment hash. + /// The passed payment hash *must* be exactly 32 bytes, if not, an error is + /// returned. + /// / The payment hash of the invoice to be looked up. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task LookupInvoiceAsync(string r_hash_str, byte[] r_hash, System.Threading.CancellationToken cancellationToken) + { + if (r_hash_str == null) + throw new System.ArgumentNullException("r_hash_str"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/invoice/{r_hash_str}?"); + urlBuilder_.Replace("{r_hash_str}", System.Uri.EscapeDataString(System.Convert.ToString(r_hash_str, System.Globalization.CultureInfo.InvariantCulture))); + if (r_hash != null) urlBuilder_.Append("r_hash=").Append(System.Uri.EscapeDataString(System.Convert.ToString(r_hash, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + urlBuilder_.Length--; + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcInvoice); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcInvoice); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `listinvoices` + /// ListInvoices returns a list of all the invoices currently stored within the + /// database. Any active debug invoices are ignored. + /// / Toggles if all invoices should be returned, or only those that are currently unsettled. + /// A server side error occurred. + public System.Threading.Tasks.Task ListInvoicesAsync(bool? pending_only) + { + return ListInvoicesAsync(pending_only, System.Threading.CancellationToken.None); + } + + /// * lncli: `listinvoices` + /// ListInvoices returns a list of all the invoices currently stored within the + /// database. Any active debug invoices are ignored. + /// / Toggles if all invoices should be returned, or only those that are currently unsettled. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task ListInvoicesAsync(bool? pending_only, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/invoices?"); + if (pending_only != null) urlBuilder_.Append("pending_only=").Append(System.Uri.EscapeDataString(System.Convert.ToString(pending_only.Value, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); + urlBuilder_.Length--; + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcListInvoiceResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcListInvoiceResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `addinvoice` + /// AddInvoice attempts to add a new invoice to the invoice database. Any + /// duplicated invoices are rejected, therefore all invoices *must* have a + /// unique payment preimage. + /// A server side error occurred. + public System.Threading.Tasks.Task AddInvoiceAsync(LnrpcInvoice body) + { + return AddInvoiceAsync(body, System.Threading.CancellationToken.None); + } + + /// * lncli: `addinvoice` + /// AddInvoice attempts to add a new invoice to the invoice database. Any + /// duplicated invoices are rejected, therefore all invoices *must* have a + /// unique payment preimage. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task AddInvoiceAsync(LnrpcInvoice body, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/invoices"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value)); + content_.Headers.ContentType.MediaType = "application/json"; + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcAddInvoiceResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcAddInvoiceResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * + /// SubscribeInvoices returns a uni-directional stream (sever -> client) for + /// notifying the client of newly added/settled invoices. + /// (streaming responses) + /// A server side error occurred. + public System.Threading.Tasks.Task SubscribeInvoicesAsync() + { + return SubscribeInvoicesAsync(System.Threading.CancellationToken.None); + } + + /// * + /// SubscribeInvoices returns a uni-directional stream (sever -> client) for + /// notifying the client of newly added/settled invoices. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// (streaming responses) + /// A server side error occurred. + public async System.Threading.Tasks.Task SubscribeInvoicesAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/invoices/subscribe"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcInvoice); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcInvoice); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * + /// NewWitnessAddress creates a new witness address under control of the local wallet. + /// A server side error occurred. + public System.Threading.Tasks.Task NewWitnessAddressAsync() + { + return NewWitnessAddressAsync(System.Threading.CancellationToken.None); + } + + /// * + /// NewWitnessAddress creates a new witness address under control of the local wallet. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task NewWitnessAddressAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/newaddress"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcNewAddressResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcNewAddressResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `listpayments` + /// ListPayments returns a list of all outgoing payments. + /// A server side error occurred. + public System.Threading.Tasks.Task ListPaymentsAsync() + { + return ListPaymentsAsync(System.Threading.CancellationToken.None); + } + + /// * lncli: `listpayments` + /// ListPayments returns a list of all outgoing payments. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task ListPaymentsAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/payments"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcListPaymentsResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcListPaymentsResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * + /// DeleteAllPayments deletes all outgoing payments from DB. + /// A server side error occurred. + public System.Threading.Tasks.Task DeleteAllPaymentsAsync() + { + return DeleteAllPaymentsAsync(System.Threading.CancellationToken.None); + } + + /// * + /// DeleteAllPayments deletes all outgoing payments from DB. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task DeleteAllPaymentsAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/payments"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("DELETE"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(object); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(object); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `decodepayreq` + /// DecodePayReq takes an encoded payment request string and attempts to decode + /// it, returning a full description of the conditions encoded within the + /// payment request. + /// A server side error occurred. + public System.Threading.Tasks.Task DecodePayReqAsync(string pay_req) + { + return DecodePayReqAsync(pay_req, System.Threading.CancellationToken.None); + } + + /// * lncli: `decodepayreq` + /// DecodePayReq takes an encoded payment request string and attempts to decode + /// it, returning a full description of the conditions encoded within the + /// payment request. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task DecodePayReqAsync(string pay_req, System.Threading.CancellationToken cancellationToken) + { + if (pay_req == null) + throw new System.ArgumentNullException("pay_req"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/payreq/{pay_req}"); + urlBuilder_.Replace("{pay_req}", System.Uri.EscapeDataString(System.Convert.ToString(pay_req, System.Globalization.CultureInfo.InvariantCulture))); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcPayReq); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcPayReq); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `listpeers` + /// ListPeers returns a verbose listing of all currently active peers. + /// A server side error occurred. + public System.Threading.Tasks.Task ListPeersAsync() + { + return ListPeersAsync(System.Threading.CancellationToken.None); + } + + /// * lncli: `listpeers` + /// ListPeers returns a verbose listing of all currently active peers. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task ListPeersAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/peers"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcListPeersResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcListPeersResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `connect` + /// ConnectPeer attempts to establish a connection to a remote peer. This is at + /// the networking level, and is used for communication between nodes. This is + /// distinct from establishing a channel with a peer. + /// A server side error occurred. + public System.Threading.Tasks.Task ConnectPeerAsync(LnrpcConnectPeerRequest body) + { + return ConnectPeerAsync(body, System.Threading.CancellationToken.None); + } + + /// * lncli: `connect` + /// ConnectPeer attempts to establish a connection to a remote peer. This is at + /// the networking level, and is used for communication between nodes. This is + /// distinct from establishing a channel with a peer. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task ConnectPeerAsync(LnrpcConnectPeerRequest body, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/peers"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value)); + content_.Headers.ContentType.MediaType = "application/json"; + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(object); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(object); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `disconnect` + /// DisconnectPeer attempts to disconnect one peer from another identified by a + /// given pubKey. In the case that we currently have a pending or active channel + /// with the target peer, then this action will be not be allowed. + /// A server side error occurred. + public System.Threading.Tasks.Task DisconnectPeerAsync(string pub_key) + { + return DisconnectPeerAsync(pub_key, System.Threading.CancellationToken.None); + } + + /// * lncli: `disconnect` + /// DisconnectPeer attempts to disconnect one peer from another identified by a + /// given pubKey. In the case that we currently have a pending or active channel + /// with the target peer, then this action will be not be allowed. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task DisconnectPeerAsync(string pub_key, System.Threading.CancellationToken cancellationToken) + { + if (pub_key == null) + throw new System.ArgumentNullException("pub_key"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/peers/{pub_key}"); + urlBuilder_.Replace("{pub_key}", System.Uri.EscapeDataString(System.Convert.ToString(pub_key, System.Globalization.CultureInfo.InvariantCulture))); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("DELETE"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(object); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(object); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `fwdinghistory` + /// ForwardingHistory allows the caller to query the htlcswitch for a record of + /// all HTLC's forwarded within the target time range, and integer offset + /// within that time range. If no time-range is specified, then the first chunk + /// of the past 24 hrs of forwarding history are returned. + /// A server side error occurred. + public System.Threading.Tasks.Task ForwardingHistoryAsync(LnrpcForwardingHistoryRequest body) + { + return ForwardingHistoryAsync(body, System.Threading.CancellationToken.None); + } + + /// * lncli: `fwdinghistory` + /// ForwardingHistory allows the caller to query the htlcswitch for a record of + /// all HTLC's forwarded within the target time range, and integer offset + /// within that time range. If no time-range is specified, then the first chunk + /// of the past 24 hrs of forwarding history are returned. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task ForwardingHistoryAsync(LnrpcForwardingHistoryRequest body, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/switch"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value)); + content_.Headers.ContentType.MediaType = "application/json"; + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcForwardingHistoryResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcForwardingHistoryResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `listchaintxns` + /// GetTransactions returns a list describing all the known transactions + /// relevant to the wallet. + /// A server side error occurred. + public System.Threading.Tasks.Task GetTransactionsAsync() + { + return GetTransactionsAsync(System.Threading.CancellationToken.None); + } + + /// * lncli: `listchaintxns` + /// GetTransactions returns a list describing all the known transactions + /// relevant to the wallet. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task GetTransactionsAsync(System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/transactions"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcTransactionDetails); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcTransactionDetails); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `sendcoins` + /// SendCoins executes a request to send coins to a particular address. Unlike + /// SendMany, this RPC call only allows creating a single output at a time. If + /// neither target_conf, or sat_per_byte are set, then the internal wallet will + /// consult its fee model to determine a fee for the default confirmation + /// target. + /// A server side error occurred. + public System.Threading.Tasks.Task SendCoinsAsync(LnrpcSendCoinsRequest body) + { + return SendCoinsAsync(body, System.Threading.CancellationToken.None); + } + + /// * lncli: `sendcoins` + /// SendCoins executes a request to send coins to a particular address. Unlike + /// SendMany, this RPC call only allows creating a single output at a time. If + /// neither target_conf, or sat_per_byte are set, then the internal wallet will + /// consult its fee model to determine a fee for the default confirmation + /// target. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task SendCoinsAsync(LnrpcSendCoinsRequest body, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/transactions"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value)); + content_.Headers.ContentType.MediaType = "application/json"; + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(LnrpcSendCoinsResponse); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(LnrpcSendCoinsResponse); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + /// * lncli: `unlock` + /// UnlockWallet is used at startup of lnd to provide a password to unlock + /// the wallet database. + /// A server side error occurred. + public System.Threading.Tasks.Task UnlockWalletAsync(LnrpcUnlockWalletRequest body) + { + return UnlockWalletAsync(body, System.Threading.CancellationToken.None); + } + + /// * lncli: `unlock` + /// UnlockWallet is used at startup of lnd to provide a password to unlock + /// the wallet database. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public async System.Threading.Tasks.Task UnlockWalletAsync(LnrpcUnlockWalletRequest body, System.Threading.CancellationToken cancellationToken) + { + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append(BaseUrl).Append("/v1/unlockwallet"); + + var client_ = new System.Net.Http.HttpClient(); + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value)); + content_.Headers.ContentType.MediaType = "application/json"; + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); + + PrepareRequest(client_, request_, urlBuilder_); + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + + ProcessResponse(client_, response_); + + var status_ = ((int)response_.StatusCode).ToString(); + if (status_ == "200") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + var result_ = default(object); + try + { + result_ = Newtonsoft.Json.JsonConvert.DeserializeObject(responseData_, _settings.Value); + return result_; + } + catch (System.Exception exception) + { + throw new SwaggerException("Could not deserialize the response body.", status_, responseData_, headers_, exception); + } + } + else + if (status_ != "200" && status_ != "204") + { + var responseData_ = await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new SwaggerException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", status_, responseData_, headers_, null); + } + + return default(object); + } + finally + { + if (response_ != null) + response_.Dispose(); + } + } + } + finally + { + if (client_ != null) + client_.Dispose(); + } + } + + } + + + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class PendingChannelsResponseClosedChannel : System.ComponentModel.INotifyPropertyChanged + { + private PendingChannelsResponsePendingChannel _channel; + private string _closing_txid; + + [Newtonsoft.Json.JsonProperty("channel", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public PendingChannelsResponsePendingChannel Channel + { + get { return _channel; } + set + { + if (_channel != value) + { + _channel = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("closing_txid", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Closing_txid + { + get { return _closing_txid; } + set + { + if (_closing_txid != value) + { + _closing_txid = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static PendingChannelsResponseClosedChannel FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class PendingChannelsResponseForceClosedChannel : System.ComponentModel.INotifyPropertyChanged + { + private PendingChannelsResponsePendingChannel _channel; + private string _closing_txid; + private string _limbo_balance; + private long? _maturity_height; + private int? _blocks_til_maturity; + private string _recovered_balance; + private System.Collections.ObjectModel.ObservableCollection _pending_htlcs; + + [Newtonsoft.Json.JsonProperty("channel", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public PendingChannelsResponsePendingChannel Channel + { + get { return _channel; } + set + { + if (_channel != value) + { + _channel = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("closing_txid", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Closing_txid + { + get { return _closing_txid; } + set + { + if (_closing_txid != value) + { + _closing_txid = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("limbo_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Limbo_balance + { + get { return _limbo_balance; } + set + { + if (_limbo_balance != value) + { + _limbo_balance = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("maturity_height", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Maturity_height + { + get { return _maturity_height; } + set + { + if (_maturity_height != value) + { + _maturity_height = value; + RaisePropertyChanged(); + } + } + } + + /// Remaining # of blocks until the commitment output can be swept. + /// Negative values indicate how many blocks have passed since becoming + /// mature. + [Newtonsoft.Json.JsonProperty("blocks_til_maturity", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Blocks_til_maturity + { + get { return _blocks_til_maturity; } + set + { + if (_blocks_til_maturity != value) + { + _blocks_til_maturity = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("recovered_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Recovered_balance + { + get { return _recovered_balance; } + set + { + if (_recovered_balance != value) + { + _recovered_balance = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("pending_htlcs", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Pending_htlcs + { + get { return _pending_htlcs; } + set + { + if (_pending_htlcs != value) + { + _pending_htlcs = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static PendingChannelsResponseForceClosedChannel FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class PendingChannelsResponsePendingChannel : System.ComponentModel.INotifyPropertyChanged + { + private string _remote_node_pub; + private string _channel_point; + private string _capacity; + private string _local_balance; + private string _remote_balance; + + [Newtonsoft.Json.JsonProperty("remote_node_pub", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Remote_node_pub + { + get { return _remote_node_pub; } + set + { + if (_remote_node_pub != value) + { + _remote_node_pub = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("channel_point", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Channel_point + { + get { return _channel_point; } + set + { + if (_channel_point != value) + { + _channel_point = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("capacity", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Capacity + { + get { return _capacity; } + set + { + if (_capacity != value) + { + _capacity = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("local_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Local_balance + { + get { return _local_balance; } + set + { + if (_local_balance != value) + { + _local_balance = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("remote_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Remote_balance + { + get { return _remote_balance; } + set + { + if (_remote_balance != value) + { + _remote_balance = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static PendingChannelsResponsePendingChannel FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class PendingChannelsResponsePendingOpenChannel : System.ComponentModel.INotifyPropertyChanged + { + private PendingChannelsResponsePendingChannel _channel; + private long? _confirmation_height; + private string _commit_fee; + private string _commit_weight; + private string _fee_per_kw; + + [Newtonsoft.Json.JsonProperty("channel", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public PendingChannelsResponsePendingChannel Channel + { + get { return _channel; } + set + { + if (_channel != value) + { + _channel = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("confirmation_height", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Confirmation_height + { + get { return _confirmation_height; } + set + { + if (_confirmation_height != value) + { + _confirmation_height = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The amount calculated to be paid in fees for the current set of + /// commitment transactions. The fee amount is persisted with the channel + /// in order to allow the fee amount to be removed and recalculated with + /// each channel state update, including updates that happen after a system + /// restart. + [Newtonsoft.Json.JsonProperty("commit_fee", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Commit_fee + { + get { return _commit_fee; } + set + { + if (_commit_fee != value) + { + _commit_fee = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("commit_weight", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Commit_weight + { + get { return _commit_weight; } + set + { + if (_commit_weight != value) + { + _commit_weight = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The required number of satoshis per kilo-weight that the requester will + /// pay at all times, for both the funding transaction and commitment + /// transaction. This value can later be updated once the channel is open. + [Newtonsoft.Json.JsonProperty("fee_per_kw", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fee_per_kw + { + get { return _fee_per_kw; } + set + { + if (_fee_per_kw != value) + { + _fee_per_kw = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static PendingChannelsResponsePendingOpenChannel FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class PendingChannelsResponseWaitingCloseChannel : System.ComponentModel.INotifyPropertyChanged + { + private PendingChannelsResponsePendingChannel _channel; + private string _limbo_balance; + + [Newtonsoft.Json.JsonProperty("channel", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public PendingChannelsResponsePendingChannel Channel + { + get { return _channel; } + set + { + if (_channel != value) + { + _channel = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("limbo_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Limbo_balance + { + get { return _limbo_balance; } + set + { + if (_limbo_balance != value) + { + _limbo_balance = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static PendingChannelsResponseWaitingCloseChannel FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcAddInvoiceResponse : System.ComponentModel.INotifyPropertyChanged + { + private byte[] _r_hash; + private string _payment_request; + + [Newtonsoft.Json.JsonProperty("r_hash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] R_hash + { + get { return _r_hash; } + set + { + if (_r_hash != value) + { + _r_hash = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// A bare-bones invoice for a payment within the Lightning Network. With the + /// details of the invoice, the sender has all the data necessary to send a + /// payment to the recipient. + [Newtonsoft.Json.JsonProperty("payment_request", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Payment_request + { + get { return _payment_request; } + set + { + if (_payment_request != value) + { + _payment_request = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcAddInvoiceResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcChannel : System.ComponentModel.INotifyPropertyChanged + { + private bool? _active; + private string _remote_pubkey; + private string _channel_point; + private string _chan_id; + private string _capacity; + private string _local_balance; + private string _remote_balance; + private string _commit_fee; + private string _commit_weight; + private string _fee_per_kw; + private string _unsettled_balance; + private string _total_satoshis_sent; + private string _total_satoshis_received; + private string _num_updates; + private System.Collections.ObjectModel.ObservableCollection _pending_htlcs; + private long? _csv_delay; + private bool? _private; + + [Newtonsoft.Json.JsonProperty("active", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Active + { + get { return _active; } + set + { + if (_active != value) + { + _active = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("remote_pubkey", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Remote_pubkey + { + get { return _remote_pubkey; } + set + { + if (_remote_pubkey != value) + { + _remote_pubkey = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The outpoint (txid:index) of the funding transaction. With this value, Bob + /// will be able to generate a signature for Alice's version of the commitment + /// transaction. + [Newtonsoft.Json.JsonProperty("channel_point", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Channel_point + { + get { return _channel_point; } + set + { + if (_channel_point != value) + { + _channel_point = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The unique channel ID for the channel. The first 3 bytes are the block + /// height, the next 3 the index within the block, and the last 2 bytes are the + /// output index for the channel. + [Newtonsoft.Json.JsonProperty("chan_id", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Chan_id + { + get { return _chan_id; } + set + { + if (_chan_id != value) + { + _chan_id = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("capacity", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Capacity + { + get { return _capacity; } + set + { + if (_capacity != value) + { + _capacity = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("local_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Local_balance + { + get { return _local_balance; } + set + { + if (_local_balance != value) + { + _local_balance = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("remote_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Remote_balance + { + get { return _remote_balance; } + set + { + if (_remote_balance != value) + { + _remote_balance = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The amount calculated to be paid in fees for the current set of commitment + /// transactions. The fee amount is persisted with the channel in order to + /// allow the fee amount to be removed and recalculated with each channel state + /// update, including updates that happen after a system restart. + [Newtonsoft.Json.JsonProperty("commit_fee", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Commit_fee + { + get { return _commit_fee; } + set + { + if (_commit_fee != value) + { + _commit_fee = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("commit_weight", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Commit_weight + { + get { return _commit_weight; } + set + { + if (_commit_weight != value) + { + _commit_weight = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The required number of satoshis per kilo-weight that the requester will pay + /// at all times, for both the funding transaction and commitment transaction. + /// This value can later be updated once the channel is open. + [Newtonsoft.Json.JsonProperty("fee_per_kw", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fee_per_kw + { + get { return _fee_per_kw; } + set + { + if (_fee_per_kw != value) + { + _fee_per_kw = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("unsettled_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Unsettled_balance + { + get { return _unsettled_balance; } + set + { + if (_unsettled_balance != value) + { + _unsettled_balance = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The total number of satoshis we've sent within this channel. + [Newtonsoft.Json.JsonProperty("total_satoshis_sent", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_satoshis_sent + { + get { return _total_satoshis_sent; } + set + { + if (_total_satoshis_sent != value) + { + _total_satoshis_sent = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The total number of satoshis we've received within this channel. + [Newtonsoft.Json.JsonProperty("total_satoshis_received", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_satoshis_received + { + get { return _total_satoshis_received; } + set + { + if (_total_satoshis_received != value) + { + _total_satoshis_received = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The total number of updates conducted within this channel. + [Newtonsoft.Json.JsonProperty("num_updates", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Num_updates + { + get { return _num_updates; } + set + { + if (_num_updates != value) + { + _num_updates = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The list of active, uncleared HTLCs currently pending within the channel. + [Newtonsoft.Json.JsonProperty("pending_htlcs", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Pending_htlcs + { + get { return _pending_htlcs; } + set + { + if (_pending_htlcs != value) + { + _pending_htlcs = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The CSV delay expressed in relative blocks. If the channel is force + /// closed, we'll need to wait for this many blocks before we can regain our + /// funds. + [Newtonsoft.Json.JsonProperty("csv_delay", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Csv_delay + { + get { return _csv_delay; } + set + { + if (_csv_delay != value) + { + _csv_delay = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("private", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Private + { + get { return _private; } + set + { + if (_private != value) + { + _private = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcChannel FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcChannelBalanceResponse : System.ComponentModel.INotifyPropertyChanged + { + private string _balance; + private string _pending_open_balance; + + [Newtonsoft.Json.JsonProperty("balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Balance + { + get { return _balance; } + set + { + if (_balance != value) + { + _balance = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("pending_open_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Pending_open_balance + { + get { return _pending_open_balance; } + set + { + if (_pending_open_balance != value) + { + _pending_open_balance = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcChannelBalanceResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcChannelCloseUpdate : System.ComponentModel.INotifyPropertyChanged + { + private byte[] _closing_txid; + private bool? _success; + + [Newtonsoft.Json.JsonProperty("closing_txid", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Closing_txid + { + get { return _closing_txid; } + set + { + if (_closing_txid != value) + { + _closing_txid = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("success", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Success + { + get { return _success; } + set + { + if (_success != value) + { + _success = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcChannelCloseUpdate FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + /// * + /// A fully authenticated channel along with all its unique attributes. + /// Once an authenticated channel announcement has been processed on the network, + /// then an instance of ChannelEdgeInfo encapsulating the channels attributes is + /// stored. The other portions relevant to routing policy of a channel are stored + /// within a ChannelEdgePolicy for each direction of the channel. + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcChannelEdge : System.ComponentModel.INotifyPropertyChanged + { + private string _channel_id; + private string _chan_point; + private long? _last_update; + private string _node1_pub; + private string _node2_pub; + private string _capacity; + private LnrpcRoutingPolicy _node1_policy; + private LnrpcRoutingPolicy _node2_policy; + + /// * + /// The unique channel ID for the channel. The first 3 bytes are the block + /// height, the next 3 the index within the block, and the last 2 bytes are the + /// output index for the channel. + [Newtonsoft.Json.JsonProperty("channel_id", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Channel_id + { + get { return _channel_id; } + set + { + if (_channel_id != value) + { + _channel_id = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("chan_point", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Chan_point + { + get { return _chan_point; } + set + { + if (_chan_point != value) + { + _chan_point = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("last_update", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Last_update + { + get { return _last_update; } + set + { + if (_last_update != value) + { + _last_update = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("node1_pub", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Node1_pub + { + get { return _node1_pub; } + set + { + if (_node1_pub != value) + { + _node1_pub = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("node2_pub", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Node2_pub + { + get { return _node2_pub; } + set + { + if (_node2_pub != value) + { + _node2_pub = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("capacity", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Capacity + { + get { return _capacity; } + set + { + if (_capacity != value) + { + _capacity = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("node1_policy", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcRoutingPolicy Node1_policy + { + get { return _node1_policy; } + set + { + if (_node1_policy != value) + { + _node1_policy = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("node2_policy", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcRoutingPolicy Node2_policy + { + get { return _node2_policy; } + set + { + if (_node2_policy != value) + { + _node2_policy = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcChannelEdge FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcChannelEdgeUpdate : System.ComponentModel.INotifyPropertyChanged + { + private string _chan_id; + private LnrpcChannelPoint _chan_point; + private string _capacity; + private LnrpcRoutingPolicy _routing_policy; + private string _advertising_node; + private string _connecting_node; + + /// * + /// The unique channel ID for the channel. The first 3 bytes are the block + /// height, the next 3 the index within the block, and the last 2 bytes are the + /// output index for the channel. + [Newtonsoft.Json.JsonProperty("chan_id", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Chan_id + { + get { return _chan_id; } + set + { + if (_chan_id != value) + { + _chan_id = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("chan_point", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcChannelPoint Chan_point + { + get { return _chan_point; } + set + { + if (_chan_point != value) + { + _chan_point = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("capacity", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Capacity + { + get { return _capacity; } + set + { + if (_capacity != value) + { + _capacity = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("routing_policy", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcRoutingPolicy Routing_policy + { + get { return _routing_policy; } + set + { + if (_routing_policy != value) + { + _routing_policy = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("advertising_node", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Advertising_node + { + get { return _advertising_node; } + set + { + if (_advertising_node != value) + { + _advertising_node = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("connecting_node", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Connecting_node + { + get { return _connecting_node; } + set + { + if (_connecting_node != value) + { + _connecting_node = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcChannelEdgeUpdate FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcChannelFeeReport : System.ComponentModel.INotifyPropertyChanged + { + private string _chan_point; + private string _base_fee_msat; + private string _fee_per_mil; + private double? _fee_rate; + + /// / The channel that this fee report belongs to. + [Newtonsoft.Json.JsonProperty("chan_point", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Chan_point + { + get { return _chan_point; } + set + { + if (_chan_point != value) + { + _chan_point = value; + RaisePropertyChanged(); + } + } + } + + /// / The base fee charged regardless of the number of milli-satoshis sent. + [Newtonsoft.Json.JsonProperty("base_fee_msat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Base_fee_msat + { + get { return _base_fee_msat; } + set + { + if (_base_fee_msat != value) + { + _base_fee_msat = value; + RaisePropertyChanged(); + } + } + } + + /// / The amount charged per milli-satoshis transferred expressed in millionths of a satoshi. + [Newtonsoft.Json.JsonProperty("fee_per_mil", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fee_per_mil + { + get { return _fee_per_mil; } + set + { + if (_fee_per_mil != value) + { + _fee_per_mil = value; + RaisePropertyChanged(); + } + } + } + + /// / The effective fee rate in milli-satoshis. Computed by dividing the fee_per_mil value by 1 million. + [Newtonsoft.Json.JsonProperty("fee_rate", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public double? Fee_rate + { + get { return _fee_rate; } + set + { + if (_fee_rate != value) + { + _fee_rate = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcChannelFeeReport FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + /// / Returns a new instance of the directed channel graph. + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcChannelGraph : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _nodes; + private System.Collections.ObjectModel.ObservableCollection _edges; + + [Newtonsoft.Json.JsonProperty("nodes", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Nodes + { + get { return _nodes; } + set + { + if (_nodes != value) + { + _nodes = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("edges", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Edges + { + get { return _edges; } + set + { + if (_edges != value) + { + _edges = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcChannelGraph FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcChannelOpenUpdate : System.ComponentModel.INotifyPropertyChanged + { + private LnrpcChannelPoint _channel_point; + + [Newtonsoft.Json.JsonProperty("channel_point", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcChannelPoint Channel_point + { + get { return _channel_point; } + set + { + if (_channel_point != value) + { + _channel_point = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcChannelOpenUpdate FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcChannelPoint : System.ComponentModel.INotifyPropertyChanged + { + private byte[] _funding_txid_bytes; + private string _funding_txid_str; + private long? _output_index; + + [Newtonsoft.Json.JsonProperty("funding_txid_bytes", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Funding_txid_bytes + { + get { return _funding_txid_bytes; } + set + { + if (_funding_txid_bytes != value) + { + _funding_txid_bytes = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("funding_txid_str", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Funding_txid_str + { + get { return _funding_txid_str; } + set + { + if (_funding_txid_str != value) + { + _funding_txid_str = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("output_index", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Output_index + { + get { return _output_index; } + set + { + if (_output_index != value) + { + _output_index = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcChannelPoint FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcCloseStatusUpdate : System.ComponentModel.INotifyPropertyChanged + { + private LnrpcPendingUpdate _close_pending; + private LnrpcConfirmationUpdate _confirmation; + private LnrpcChannelCloseUpdate _chan_close; + + [Newtonsoft.Json.JsonProperty("close_pending", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcPendingUpdate Close_pending + { + get { return _close_pending; } + set + { + if (_close_pending != value) + { + _close_pending = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("confirmation", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcConfirmationUpdate Confirmation + { + get { return _confirmation; } + set + { + if (_confirmation != value) + { + _confirmation = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("chan_close", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcChannelCloseUpdate Chan_close + { + get { return _chan_close; } + set + { + if (_chan_close != value) + { + _chan_close = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcCloseStatusUpdate FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcClosedChannelUpdate : System.ComponentModel.INotifyPropertyChanged + { + private string _chan_id; + private string _capacity; + private long? _closed_height; + private LnrpcChannelPoint _chan_point; + + /// * + /// The unique channel ID for the channel. The first 3 bytes are the block + /// height, the next 3 the index within the block, and the last 2 bytes are the + /// output index for the channel. + [Newtonsoft.Json.JsonProperty("chan_id", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Chan_id + { + get { return _chan_id; } + set + { + if (_chan_id != value) + { + _chan_id = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("capacity", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Capacity + { + get { return _capacity; } + set + { + if (_capacity != value) + { + _capacity = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("closed_height", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Closed_height + { + get { return _closed_height; } + set + { + if (_closed_height != value) + { + _closed_height = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("chan_point", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcChannelPoint Chan_point + { + get { return _chan_point; } + set + { + if (_chan_point != value) + { + _chan_point = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcClosedChannelUpdate FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcConfirmationUpdate : System.ComponentModel.INotifyPropertyChanged + { + private byte[] _block_sha; + private int? _block_height; + private long? _num_confs_left; + + [Newtonsoft.Json.JsonProperty("block_sha", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Block_sha + { + get { return _block_sha; } + set + { + if (_block_sha != value) + { + _block_sha = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("block_height", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Block_height + { + get { return _block_height; } + set + { + if (_block_height != value) + { + _block_height = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("num_confs_left", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Num_confs_left + { + get { return _num_confs_left; } + set + { + if (_num_confs_left != value) + { + _num_confs_left = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcConfirmationUpdate FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcConnectPeerRequest : System.ComponentModel.INotifyPropertyChanged + { + private LnrpcLightningAddress _addr; + private bool? _perm; + + [Newtonsoft.Json.JsonProperty("addr", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcLightningAddress Addr + { + get { return _addr; } + set + { + if (_addr != value) + { + _addr = value; + RaisePropertyChanged(); + } + } + } + + /// * If set, the daemon will attempt to persistently connect to the target + /// peer. Otherwise, the call will be synchronous. + [Newtonsoft.Json.JsonProperty("perm", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Perm + { + get { return _perm; } + set + { + if (_perm != value) + { + _perm = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcConnectPeerRequest FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcDebugLevelResponse : System.ComponentModel.INotifyPropertyChanged + { + private string _sub_systems; + + [Newtonsoft.Json.JsonProperty("sub_systems", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Sub_systems + { + get { return _sub_systems; } + set + { + if (_sub_systems != value) + { + _sub_systems = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcDebugLevelResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcFeeReportResponse : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _channel_fees; + private string _day_fee_sum; + private string _week_fee_sum; + private string _month_fee_sum; + + /// / An array of channel fee reports which describes the current fee schedule for each channel. + [Newtonsoft.Json.JsonProperty("channel_fees", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Channel_fees + { + get { return _channel_fees; } + set + { + if (_channel_fees != value) + { + _channel_fees = value; + RaisePropertyChanged(); + } + } + } + + /// / The total amount of fee revenue (in satoshis) the switch has collected over the past 24 hrs. + [Newtonsoft.Json.JsonProperty("day_fee_sum", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Day_fee_sum + { + get { return _day_fee_sum; } + set + { + if (_day_fee_sum != value) + { + _day_fee_sum = value; + RaisePropertyChanged(); + } + } + } + + /// / The total amount of fee revenue (in satoshis) the switch has collected over the past 1 week. + [Newtonsoft.Json.JsonProperty("week_fee_sum", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Week_fee_sum + { + get { return _week_fee_sum; } + set + { + if (_week_fee_sum != value) + { + _week_fee_sum = value; + RaisePropertyChanged(); + } + } + } + + /// / The total amount of fee revenue (in satoshis) the switch has collected over the past 1 month. + [Newtonsoft.Json.JsonProperty("month_fee_sum", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Month_fee_sum + { + get { return _month_fee_sum; } + set + { + if (_month_fee_sum != value) + { + _month_fee_sum = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcFeeReportResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcForwardingEvent : System.ComponentModel.INotifyPropertyChanged + { + private string _timestamp; + private string _chan_id_in; + private string _chan_id_out; + private string _amt_in; + private string _amt_out; + private string _fee; + + /// / Timestamp is the time (unix epoch offset) that this circuit was completed. + [Newtonsoft.Json.JsonProperty("timestamp", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Timestamp + { + get { return _timestamp; } + set + { + if (_timestamp != value) + { + _timestamp = value; + RaisePropertyChanged(); + } + } + } + + /// / The incoming channel ID that carried the HTLC that created the circuit. + [Newtonsoft.Json.JsonProperty("chan_id_in", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Chan_id_in + { + get { return _chan_id_in; } + set + { + if (_chan_id_in != value) + { + _chan_id_in = value; + RaisePropertyChanged(); + } + } + } + + /// / The outgoing channel ID that carried the preimage that completed the circuit. + [Newtonsoft.Json.JsonProperty("chan_id_out", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Chan_id_out + { + get { return _chan_id_out; } + set + { + if (_chan_id_out != value) + { + _chan_id_out = value; + RaisePropertyChanged(); + } + } + } + + /// / The total amount of the incoming HTLC that created half the circuit. + [Newtonsoft.Json.JsonProperty("amt_in", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Amt_in + { + get { return _amt_in; } + set + { + if (_amt_in != value) + { + _amt_in = value; + RaisePropertyChanged(); + } + } + } + + /// / The total amount of the outgoign HTLC that created the second half of the circuit. + [Newtonsoft.Json.JsonProperty("amt_out", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Amt_out + { + get { return _amt_out; } + set + { + if (_amt_out != value) + { + _amt_out = value; + RaisePropertyChanged(); + } + } + } + + /// / The total fee that this payment circuit carried. + [Newtonsoft.Json.JsonProperty("fee", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fee + { + get { return _fee; } + set + { + if (_fee != value) + { + _fee = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcForwardingEvent FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcForwardingHistoryRequest : System.ComponentModel.INotifyPropertyChanged + { + private string _start_time; + private string _end_time; + private long? _index_offset; + private long? _num_max_events; + + /// / Start time is the starting point of the forwarding history request. All records beyond this point will be included, respecting the end time, and the index offset. + [Newtonsoft.Json.JsonProperty("start_time", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Start_time + { + get { return _start_time; } + set + { + if (_start_time != value) + { + _start_time = value; + RaisePropertyChanged(); + } + } + } + + /// / End time is the end point of the forwarding history request. The response will carry at most 50k records between the start time and the end time. The index offset can be used to implement pagination. + [Newtonsoft.Json.JsonProperty("end_time", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string End_time + { + get { return _end_time; } + set + { + if (_end_time != value) + { + _end_time = value; + RaisePropertyChanged(); + } + } + } + + /// / Index offset is the offset in the time series to start at. As each response can only contain 50k records, callers can use this to skip around within a packed time series. + [Newtonsoft.Json.JsonProperty("index_offset", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Index_offset + { + get { return _index_offset; } + set + { + if (_index_offset != value) + { + _index_offset = value; + RaisePropertyChanged(); + } + } + } + + /// / The max number of events to return in the response to this query. + [Newtonsoft.Json.JsonProperty("num_max_events", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Num_max_events + { + get { return _num_max_events; } + set + { + if (_num_max_events != value) + { + _num_max_events = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcForwardingHistoryRequest FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcForwardingHistoryResponse : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _forwarding_events; + private long? _last_offset_index; + + /// / A list of forwarding events from the time slice of the time series specified in the request. + [Newtonsoft.Json.JsonProperty("forwarding_events", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Forwarding_events + { + get { return _forwarding_events; } + set + { + if (_forwarding_events != value) + { + _forwarding_events = value; + RaisePropertyChanged(); + } + } + } + + /// / The index of the last time in the set of returned forwarding events. Can be used to seek further, pagination style. + [Newtonsoft.Json.JsonProperty("last_offset_index", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Last_offset_index + { + get { return _last_offset_index; } + set + { + if (_last_offset_index != value) + { + _last_offset_index = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcForwardingHistoryResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcGenSeedResponse : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _cipher_seed_mnemonic; + private byte[] _enciphered_seed; + + /// * + /// cipher_seed_mnemonic is a 24-word mnemonic that encodes a prior aezeed + /// cipher seed obtained by the user. This field is optional, as if not + /// provided, then the daemon will generate a new cipher seed for the user. + /// Otherwise, then the daemon will attempt to recover the wallet state linked + /// to this cipher seed. + [Newtonsoft.Json.JsonProperty("cipher_seed_mnemonic", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Cipher_seed_mnemonic + { + get { return _cipher_seed_mnemonic; } + set + { + if (_cipher_seed_mnemonic != value) + { + _cipher_seed_mnemonic = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// enciphered_seed are the raw aezeed cipher seed bytes. This is the raw + /// cipher text before run through our mnemonic encoding scheme. + [Newtonsoft.Json.JsonProperty("enciphered_seed", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Enciphered_seed + { + get { return _enciphered_seed; } + set + { + if (_enciphered_seed != value) + { + _enciphered_seed = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcGenSeedResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcGetInfoResponse : System.ComponentModel.INotifyPropertyChanged + { + private string _identity_pubkey; + private string _alias; + private long? _num_pending_channels; + private long? _num_active_channels; + private long? _num_peers; + private long? _block_height; + private string _block_hash; + private bool? _synced_to_chain; + private bool? _testnet; + private System.Collections.ObjectModel.ObservableCollection _chains; + private System.Collections.ObjectModel.ObservableCollection _uris; + private string _best_header_timestamp; + private string _version; + + /// / The identity pubkey of the current node. + [Newtonsoft.Json.JsonProperty("identity_pubkey", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Identity_pubkey + { + get { return _identity_pubkey; } + set + { + if (_identity_pubkey != value) + { + _identity_pubkey = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("alias", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Alias + { + get { return _alias; } + set + { + if (_alias != value) + { + _alias = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("num_pending_channels", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Num_pending_channels + { + get { return _num_pending_channels; } + set + { + if (_num_pending_channels != value) + { + _num_pending_channels = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("num_active_channels", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Num_active_channels + { + get { return _num_active_channels; } + set + { + if (_num_active_channels != value) + { + _num_active_channels = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("num_peers", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Num_peers + { + get { return _num_peers; } + set + { + if (_num_peers != value) + { + _num_peers = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("block_height", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Block_height + { + get { return _block_height; } + set + { + if (_block_height != value) + { + _block_height = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("block_hash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Block_hash + { + get { return _block_hash; } + set + { + if (_block_hash != value) + { + _block_hash = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("synced_to_chain", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Synced_to_chain + { + get { return _synced_to_chain; } + set + { + if (_synced_to_chain != value) + { + _synced_to_chain = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("testnet", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Testnet + { + get { return _testnet; } + set + { + if (_testnet != value) + { + _testnet = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("chains", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Chains + { + get { return _chains; } + set + { + if (_chains != value) + { + _chains = value; + RaisePropertyChanged(); + } + } + } + + /// / The URIs of the current node. + [Newtonsoft.Json.JsonProperty("uris", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Uris + { + get { return _uris; } + set + { + if (_uris != value) + { + _uris = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("best_header_timestamp", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Best_header_timestamp + { + get { return _best_header_timestamp; } + set + { + if (_best_header_timestamp != value) + { + _best_header_timestamp = value; + RaisePropertyChanged(); + } + } + } + + /// / The version of the LND software that the node is running. + [Newtonsoft.Json.JsonProperty("version", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Version + { + get { return _version; } + set + { + if (_version != value) + { + _version = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcGetInfoResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcGraphTopologyUpdate : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _node_updates; + private System.Collections.ObjectModel.ObservableCollection _channel_updates; + private System.Collections.ObjectModel.ObservableCollection _closed_chans; + + [Newtonsoft.Json.JsonProperty("node_updates", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Node_updates + { + get { return _node_updates; } + set + { + if (_node_updates != value) + { + _node_updates = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("channel_updates", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Channel_updates + { + get { return _channel_updates; } + set + { + if (_channel_updates != value) + { + _channel_updates = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("closed_chans", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Closed_chans + { + get { return _closed_chans; } + set + { + if (_closed_chans != value) + { + _closed_chans = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcGraphTopologyUpdate FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcHTLC : System.ComponentModel.INotifyPropertyChanged + { + private bool? _incoming; + private string _amount; + private byte[] _hash_lock; + private long? _expiration_height; + + [Newtonsoft.Json.JsonProperty("incoming", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Incoming + { + get { return _incoming; } + set + { + if (_incoming != value) + { + _incoming = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("amount", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Amount + { + get { return _amount; } + set + { + if (_amount != value) + { + _amount = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("hash_lock", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Hash_lock + { + get { return _hash_lock; } + set + { + if (_hash_lock != value) + { + _hash_lock = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("expiration_height", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Expiration_height + { + get { return _expiration_height; } + set + { + if (_expiration_height != value) + { + _expiration_height = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcHTLC FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcHop : System.ComponentModel.INotifyPropertyChanged + { + private string _chan_id; + private string _chan_capacity; + private string _amt_to_forward; + private string _fee; + private long? _expiry; + private string _amt_to_forward_msat; + private string _fee_msat; + + /// * + /// The unique channel ID for the channel. The first 3 bytes are the block + /// height, the next 3 the index within the block, and the last 2 bytes are the + /// output index for the channel. + [Newtonsoft.Json.JsonProperty("chan_id", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Chan_id + { + get { return _chan_id; } + set + { + if (_chan_id != value) + { + _chan_id = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("chan_capacity", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Chan_capacity + { + get { return _chan_capacity; } + set + { + if (_chan_capacity != value) + { + _chan_capacity = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("amt_to_forward", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Amt_to_forward + { + get { return _amt_to_forward; } + set + { + if (_amt_to_forward != value) + { + _amt_to_forward = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("fee", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fee + { + get { return _fee; } + set + { + if (_fee != value) + { + _fee = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("expiry", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Expiry + { + get { return _expiry; } + set + { + if (_expiry != value) + { + _expiry = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("amt_to_forward_msat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Amt_to_forward_msat + { + get { return _amt_to_forward_msat; } + set + { + if (_amt_to_forward_msat != value) + { + _amt_to_forward_msat = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("fee_msat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fee_msat + { + get { return _fee_msat; } + set + { + if (_fee_msat != value) + { + _fee_msat = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcHop FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcHopHint : System.ComponentModel.INotifyPropertyChanged + { + private string _node_id; + private string _chan_id; + private long? _fee_base_msat; + private long? _fee_proportional_millionths; + private long? _cltv_expiry_delta; + + /// / The public key of the node at the start of the channel. + [Newtonsoft.Json.JsonProperty("node_id", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Node_id + { + get { return _node_id; } + set + { + if (_node_id != value) + { + _node_id = value; + RaisePropertyChanged(); + } + } + } + + /// / The unique identifier of the channel. + [Newtonsoft.Json.JsonProperty("chan_id", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Chan_id + { + get { return _chan_id; } + set + { + if (_chan_id != value) + { + _chan_id = value; + RaisePropertyChanged(); + } + } + } + + /// / The base fee of the channel denominated in millisatoshis. + [Newtonsoft.Json.JsonProperty("fee_base_msat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Fee_base_msat + { + get { return _fee_base_msat; } + set + { + if (_fee_base_msat != value) + { + _fee_base_msat = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The fee rate of the channel for sending one satoshi across it denominated in + /// millionths of a satoshi. + [Newtonsoft.Json.JsonProperty("fee_proportional_millionths", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Fee_proportional_millionths + { + get { return _fee_proportional_millionths; } + set + { + if (_fee_proportional_millionths != value) + { + _fee_proportional_millionths = value; + RaisePropertyChanged(); + } + } + } + + /// / The time-lock delta of the channel. + [Newtonsoft.Json.JsonProperty("cltv_expiry_delta", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Cltv_expiry_delta + { + get { return _cltv_expiry_delta; } + set + { + if (_cltv_expiry_delta != value) + { + _cltv_expiry_delta = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcHopHint FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcInitWalletRequest : System.ComponentModel.INotifyPropertyChanged + { + private byte[] _wallet_password; + private System.Collections.ObjectModel.ObservableCollection _cipher_seed_mnemonic; + private byte[] _aezeed_passphrase; + + /// * + /// wallet_password is the passphrase that should be used to encrypt the + /// wallet. This MUST be at least 8 chars in length. After creation, this + /// password is required to unlock the daemon. + [Newtonsoft.Json.JsonProperty("wallet_password", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Wallet_password + { + get { return _wallet_password; } + set + { + if (_wallet_password != value) + { + _wallet_password = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// cipher_seed_mnemonic is a 24-word mnemonic that encodes a prior aezeed + /// cipher seed obtained by the user. This may have been generated by the + /// GenSeed method, or be an existing seed. + [Newtonsoft.Json.JsonProperty("cipher_seed_mnemonic", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Cipher_seed_mnemonic + { + get { return _cipher_seed_mnemonic; } + set + { + if (_cipher_seed_mnemonic != value) + { + _cipher_seed_mnemonic = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// aezeed_passphrase is an optional user provided passphrase that will be used + /// to encrypt the generated aezeed cipher seed. + [Newtonsoft.Json.JsonProperty("aezeed_passphrase", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Aezeed_passphrase + { + get { return _aezeed_passphrase; } + set + { + if (_aezeed_passphrase != value) + { + _aezeed_passphrase = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcInitWalletRequest FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcInvoice : System.ComponentModel.INotifyPropertyChanged + { + private string _memo; + private byte[] _receipt; + private byte[] _r_preimage; + private byte[] _r_hash; + private string _value; + private bool? _settled; + private string _creation_date; + private string _settle_date; + private string _payment_request; + private byte[] _description_hash; + private string _expiry; + private string _fallback_addr; + private string _cltv_expiry; + private System.Collections.ObjectModel.ObservableCollection _route_hints; + private bool? _private; + + /// * + /// An optional memo to attach along with the invoice. Used for record keeping + /// purposes for the invoice's creator, and will also be set in the description + /// field of the encoded payment request if the description_hash field is not + /// being used. + [Newtonsoft.Json.JsonProperty("memo", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Memo + { + get { return _memo; } + set + { + if (_memo != value) + { + _memo = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("receipt", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Receipt + { + get { return _receipt; } + set + { + if (_receipt != value) + { + _receipt = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("r_preimage", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] R_preimage + { + get { return _r_preimage; } + set + { + if (_r_preimage != value) + { + _r_preimage = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("r_hash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] R_hash + { + get { return _r_hash; } + set + { + if (_r_hash != value) + { + _r_hash = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("value", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Value + { + get { return _value; } + set + { + if (_value != value) + { + _value = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("settled", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Settled + { + get { return _settled; } + set + { + if (_settled != value) + { + _settled = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("creation_date", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Creation_date + { + get { return _creation_date; } + set + { + if (_creation_date != value) + { + _creation_date = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("settle_date", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Settle_date + { + get { return _settle_date; } + set + { + if (_settle_date != value) + { + _settle_date = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// A bare-bones invoice for a payment within the Lightning Network. With the + /// details of the invoice, the sender has all the data necessary to send a + /// payment to the recipient. + [Newtonsoft.Json.JsonProperty("payment_request", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Payment_request + { + get { return _payment_request; } + set + { + if (_payment_request != value) + { + _payment_request = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// Hash (SHA-256) of a description of the payment. Used if the description of + /// payment (memo) is too long to naturally fit within the description field + /// of an encoded payment request. + [Newtonsoft.Json.JsonProperty("description_hash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Description_hash + { + get { return _description_hash; } + set + { + if (_description_hash != value) + { + _description_hash = value; + RaisePropertyChanged(); + } + } + } + + /// / Payment request expiry time in seconds. Default is 3600 (1 hour). + [Newtonsoft.Json.JsonProperty("expiry", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Expiry + { + get { return _expiry; } + set + { + if (_expiry != value) + { + _expiry = value; + RaisePropertyChanged(); + } + } + } + + /// / Fallback on-chain address. + [Newtonsoft.Json.JsonProperty("fallback_addr", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fallback_addr + { + get { return _fallback_addr; } + set + { + if (_fallback_addr != value) + { + _fallback_addr = value; + RaisePropertyChanged(); + } + } + } + + /// / Delta to use for the time-lock of the CLTV extended to the final hop. + [Newtonsoft.Json.JsonProperty("cltv_expiry", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Cltv_expiry + { + get { return _cltv_expiry; } + set + { + if (_cltv_expiry != value) + { + _cltv_expiry = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// Route hints that can each be individually used to assist in reaching the + /// invoice's destination. + [Newtonsoft.Json.JsonProperty("route_hints", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Route_hints + { + get { return _route_hints; } + set + { + if (_route_hints != value) + { + _route_hints = value; + RaisePropertyChanged(); + } + } + } + + /// / Whether this invoice should include routing hints for private channels. + [Newtonsoft.Json.JsonProperty("private", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Private + { + get { return _private; } + set + { + if (_private != value) + { + _private = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcInvoice FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcLightningAddress : System.ComponentModel.INotifyPropertyChanged + { + private string _pubkey; + private string _host; + + [Newtonsoft.Json.JsonProperty("pubkey", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Pubkey + { + get { return _pubkey; } + set + { + if (_pubkey != value) + { + _pubkey = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("host", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Host + { + get { return _host; } + set + { + if (_host != value) + { + _host = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcLightningAddress FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + /// * + /// An individual vertex/node within the channel graph. A node is + /// connected to other nodes by one or more channel edges emanating from it. As the + /// graph is directed, a node will also have an incoming edge attached to it for + /// each outgoing edge. + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcLightningNode : System.ComponentModel.INotifyPropertyChanged + { + private long? _last_update; + private string _pub_key; + private string _alias; + private System.Collections.ObjectModel.ObservableCollection _addresses; + private string _color; + + [Newtonsoft.Json.JsonProperty("last_update", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Last_update + { + get { return _last_update; } + set + { + if (_last_update != value) + { + _last_update = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("pub_key", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Pub_key + { + get { return _pub_key; } + set + { + if (_pub_key != value) + { + _pub_key = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("alias", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Alias + { + get { return _alias; } + set + { + if (_alias != value) + { + _alias = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("addresses", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Addresses + { + get { return _addresses; } + set + { + if (_addresses != value) + { + _addresses = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("color", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Color + { + get { return _color; } + set + { + if (_color != value) + { + _color = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcLightningNode FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcListChannelsResponse : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _channels; + + [Newtonsoft.Json.JsonProperty("channels", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Channels + { + get { return _channels; } + set + { + if (_channels != value) + { + _channels = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcListChannelsResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcListInvoiceResponse : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _invoices; + + [Newtonsoft.Json.JsonProperty("invoices", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Invoices + { + get { return _invoices; } + set + { + if (_invoices != value) + { + _invoices = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcListInvoiceResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcListPaymentsResponse : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _payments; + + [Newtonsoft.Json.JsonProperty("payments", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Payments + { + get { return _payments; } + set + { + if (_payments != value) + { + _payments = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcListPaymentsResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcListPeersResponse : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _peers; + + [Newtonsoft.Json.JsonProperty("peers", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Peers + { + get { return _peers; } + set + { + if (_peers != value) + { + _peers = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcListPeersResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcNetworkInfo : System.ComponentModel.INotifyPropertyChanged + { + private long? _graph_diameter; + private double? _avg_out_degree; + private long? _max_out_degree; + private long? _num_nodes; + private long? _num_channels; + private string _total_network_capacity; + private double? _avg_channel_size; + private string _min_channel_size; + private string _max_channel_size; + + [Newtonsoft.Json.JsonProperty("graph_diameter", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Graph_diameter + { + get { return _graph_diameter; } + set + { + if (_graph_diameter != value) + { + _graph_diameter = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("avg_out_degree", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public double? Avg_out_degree + { + get { return _avg_out_degree; } + set + { + if (_avg_out_degree != value) + { + _avg_out_degree = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("max_out_degree", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Max_out_degree + { + get { return _max_out_degree; } + set + { + if (_max_out_degree != value) + { + _max_out_degree = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("num_nodes", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Num_nodes + { + get { return _num_nodes; } + set + { + if (_num_nodes != value) + { + _num_nodes = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("num_channels", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Num_channels + { + get { return _num_channels; } + set + { + if (_num_channels != value) + { + _num_channels = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("total_network_capacity", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_network_capacity + { + get { return _total_network_capacity; } + set + { + if (_total_network_capacity != value) + { + _total_network_capacity = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("avg_channel_size", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public double? Avg_channel_size + { + get { return _avg_channel_size; } + set + { + if (_avg_channel_size != value) + { + _avg_channel_size = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("min_channel_size", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Min_channel_size + { + get { return _min_channel_size; } + set + { + if (_min_channel_size != value) + { + _min_channel_size = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("max_channel_size", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Max_channel_size + { + get { return _max_channel_size; } + set + { + if (_max_channel_size != value) + { + _max_channel_size = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcNetworkInfo FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcNewAddressResponse : System.ComponentModel.INotifyPropertyChanged + { + private string _address; + + [Newtonsoft.Json.JsonProperty("address", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Address + { + get { return _address; } + set + { + if (_address != value) + { + _address = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcNewAddressResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcNodeAddress : System.ComponentModel.INotifyPropertyChanged + { + private string _network; + private string _addr; + + [Newtonsoft.Json.JsonProperty("network", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Network + { + get { return _network; } + set + { + if (_network != value) + { + _network = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("addr", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Addr + { + get { return _addr; } + set + { + if (_addr != value) + { + _addr = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcNodeAddress FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcNodeInfo : System.ComponentModel.INotifyPropertyChanged + { + private LnrpcLightningNode _node; + private long? _num_channels; + private string _total_capacity; + + /// * + /// An individual vertex/node within the channel graph. A node is + /// connected to other nodes by one or more channel edges emanating from it. As + /// the graph is directed, a node will also have an incoming edge attached to + /// it for each outgoing edge. + [Newtonsoft.Json.JsonProperty("node", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcLightningNode Node + { + get { return _node; } + set + { + if (_node != value) + { + _node = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("num_channels", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Num_channels + { + get { return _num_channels; } + set + { + if (_num_channels != value) + { + _num_channels = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("total_capacity", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_capacity + { + get { return _total_capacity; } + set + { + if (_total_capacity != value) + { + _total_capacity = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcNodeInfo FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcNodeUpdate : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _addresses; + private string _identity_key; + private byte[] _global_features; + private string _alias; + + [Newtonsoft.Json.JsonProperty("addresses", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Addresses + { + get { return _addresses; } + set + { + if (_addresses != value) + { + _addresses = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("identity_key", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Identity_key + { + get { return _identity_key; } + set + { + if (_identity_key != value) + { + _identity_key = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("global_features", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Global_features + { + get { return _global_features; } + set + { + if (_global_features != value) + { + _global_features = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("alias", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Alias + { + get { return _alias; } + set + { + if (_alias != value) + { + _alias = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcNodeUpdate FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcOpenChannelRequest : System.ComponentModel.INotifyPropertyChanged + { + private byte[] _node_pubkey; + private string _node_pubkey_string; + private string _local_funding_amount; + private string _push_sat; + private int? _target_conf; + private string _sat_per_byte; + private bool? _private; + private string _min_htlc_msat; + private long? _remote_csv_delay; + + [Newtonsoft.Json.JsonProperty("node_pubkey", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Node_pubkey + { + get { return _node_pubkey; } + set + { + if (_node_pubkey != value) + { + _node_pubkey = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("node_pubkey_string", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Node_pubkey_string + { + get { return _node_pubkey_string; } + set + { + if (_node_pubkey_string != value) + { + _node_pubkey_string = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("local_funding_amount", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Local_funding_amount + { + get { return _local_funding_amount; } + set + { + if (_local_funding_amount != value) + { + _local_funding_amount = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("push_sat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Push_sat + { + get { return _push_sat; } + set + { + if (_push_sat != value) + { + _push_sat = value; + RaisePropertyChanged(); + } + } + } + + /// / The target number of blocks that the funding transaction should be confirmed by. + [Newtonsoft.Json.JsonProperty("target_conf", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Target_conf + { + get { return _target_conf; } + set + { + if (_target_conf != value) + { + _target_conf = value; + RaisePropertyChanged(); + } + } + } + + /// / A manual fee rate set in sat/byte that should be used when crafting the funding transaction. + [Newtonsoft.Json.JsonProperty("sat_per_byte", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Sat_per_byte + { + get { return _sat_per_byte; } + set + { + if (_sat_per_byte != value) + { + _sat_per_byte = value; + RaisePropertyChanged(); + } + } + } + + /// / Whether this channel should be private, not announced to the greater network. + [Newtonsoft.Json.JsonProperty("private", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Private + { + get { return _private; } + set + { + if (_private != value) + { + _private = value; + RaisePropertyChanged(); + } + } + } + + /// / The minimum value in millisatoshi we will require for incoming HTLCs on the channel. + [Newtonsoft.Json.JsonProperty("min_htlc_msat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Min_htlc_msat + { + get { return _min_htlc_msat; } + set + { + if (_min_htlc_msat != value) + { + _min_htlc_msat = value; + RaisePropertyChanged(); + } + } + } + + /// / The delay we require on the remote's commitment transaction. If this is not set, it will be scaled automatically with the channel size. + [Newtonsoft.Json.JsonProperty("remote_csv_delay", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Remote_csv_delay + { + get { return _remote_csv_delay; } + set + { + if (_remote_csv_delay != value) + { + _remote_csv_delay = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcOpenChannelRequest FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcOpenStatusUpdate : System.ComponentModel.INotifyPropertyChanged + { + private LnrpcPendingUpdate _chan_pending; + private LnrpcConfirmationUpdate _confirmation; + private LnrpcChannelOpenUpdate _chan_open; + + [Newtonsoft.Json.JsonProperty("chan_pending", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcPendingUpdate Chan_pending + { + get { return _chan_pending; } + set + { + if (_chan_pending != value) + { + _chan_pending = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("confirmation", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcConfirmationUpdate Confirmation + { + get { return _confirmation; } + set + { + if (_confirmation != value) + { + _confirmation = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("chan_open", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcChannelOpenUpdate Chan_open + { + get { return _chan_open; } + set + { + if (_chan_open != value) + { + _chan_open = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcOpenStatusUpdate FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcPayReq : System.ComponentModel.INotifyPropertyChanged + { + private string _destination; + private string _payment_hash; + private string _num_satoshis; + private string _timestamp; + private string _expiry; + private string _description; + private string _description_hash; + private string _fallback_addr; + private string _cltv_expiry; + private System.Collections.ObjectModel.ObservableCollection _route_hints; + + [Newtonsoft.Json.JsonProperty("destination", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Destination + { + get { return _destination; } + set + { + if (_destination != value) + { + _destination = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("payment_hash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Payment_hash + { + get { return _payment_hash; } + set + { + if (_payment_hash != value) + { + _payment_hash = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("num_satoshis", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Num_satoshis + { + get { return _num_satoshis; } + set + { + if (_num_satoshis != value) + { + _num_satoshis = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("timestamp", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Timestamp + { + get { return _timestamp; } + set + { + if (_timestamp != value) + { + _timestamp = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("expiry", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Expiry + { + get { return _expiry; } + set + { + if (_expiry != value) + { + _expiry = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("description", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Description + { + get { return _description; } + set + { + if (_description != value) + { + _description = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("description_hash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Description_hash + { + get { return _description_hash; } + set + { + if (_description_hash != value) + { + _description_hash = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("fallback_addr", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fallback_addr + { + get { return _fallback_addr; } + set + { + if (_fallback_addr != value) + { + _fallback_addr = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("cltv_expiry", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Cltv_expiry + { + get { return _cltv_expiry; } + set + { + if (_cltv_expiry != value) + { + _cltv_expiry = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("route_hints", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Route_hints + { + get { return _route_hints; } + set + { + if (_route_hints != value) + { + _route_hints = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcPayReq FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcPayment : System.ComponentModel.INotifyPropertyChanged + { + private string _payment_hash; + private string _value; + private string _creation_date; + private System.Collections.ObjectModel.ObservableCollection _path; + private string _fee; + private string _payment_preimage; + + [Newtonsoft.Json.JsonProperty("payment_hash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Payment_hash + { + get { return _payment_hash; } + set + { + if (_payment_hash != value) + { + _payment_hash = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("value", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Value + { + get { return _value; } + set + { + if (_value != value) + { + _value = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("creation_date", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Creation_date + { + get { return _creation_date; } + set + { + if (_creation_date != value) + { + _creation_date = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("path", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Path + { + get { return _path; } + set + { + if (_path != value) + { + _path = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("fee", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fee + { + get { return _fee; } + set + { + if (_fee != value) + { + _fee = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("payment_preimage", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Payment_preimage + { + get { return _payment_preimage; } + set + { + if (_payment_preimage != value) + { + _payment_preimage = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcPayment FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcPeer : System.ComponentModel.INotifyPropertyChanged + { + private string _pub_key; + private string _address; + private string _bytes_sent; + private string _bytes_recv; + private string _sat_sent; + private string _sat_recv; + private bool? _inbound; + private string _ping_time; + + [Newtonsoft.Json.JsonProperty("pub_key", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Pub_key + { + get { return _pub_key; } + set + { + if (_pub_key != value) + { + _pub_key = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("address", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Address + { + get { return _address; } + set + { + if (_address != value) + { + _address = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("bytes_sent", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Bytes_sent + { + get { return _bytes_sent; } + set + { + if (_bytes_sent != value) + { + _bytes_sent = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("bytes_recv", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Bytes_recv + { + get { return _bytes_recv; } + set + { + if (_bytes_recv != value) + { + _bytes_recv = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("sat_sent", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Sat_sent + { + get { return _sat_sent; } + set + { + if (_sat_sent != value) + { + _sat_sent = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("sat_recv", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Sat_recv + { + get { return _sat_recv; } + set + { + if (_sat_recv != value) + { + _sat_recv = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("inbound", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Inbound + { + get { return _inbound; } + set + { + if (_inbound != value) + { + _inbound = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("ping_time", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Ping_time + { + get { return _ping_time; } + set + { + if (_ping_time != value) + { + _ping_time = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcPeer FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcPendingChannelsResponse : System.ComponentModel.INotifyPropertyChanged + { + private string _total_limbo_balance; + private System.Collections.ObjectModel.ObservableCollection _pending_open_channels; + private System.Collections.ObjectModel.ObservableCollection _pending_closing_channels; + private System.Collections.ObjectModel.ObservableCollection _pending_force_closing_channels; + private System.Collections.ObjectModel.ObservableCollection _waiting_close_channels; + + [Newtonsoft.Json.JsonProperty("total_limbo_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_limbo_balance + { + get { return _total_limbo_balance; } + set + { + if (_total_limbo_balance != value) + { + _total_limbo_balance = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("pending_open_channels", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Pending_open_channels + { + get { return _pending_open_channels; } + set + { + if (_pending_open_channels != value) + { + _pending_open_channels = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("pending_closing_channels", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Pending_closing_channels + { + get { return _pending_closing_channels; } + set + { + if (_pending_closing_channels != value) + { + _pending_closing_channels = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("pending_force_closing_channels", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Pending_force_closing_channels + { + get { return _pending_force_closing_channels; } + set + { + if (_pending_force_closing_channels != value) + { + _pending_force_closing_channels = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("waiting_close_channels", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Waiting_close_channels + { + get { return _waiting_close_channels; } + set + { + if (_waiting_close_channels != value) + { + _waiting_close_channels = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcPendingChannelsResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcPendingHTLC : System.ComponentModel.INotifyPropertyChanged + { + private bool? _incoming; + private string _amount; + private string _outpoint; + private long? _maturity_height; + private int? _blocks_til_maturity; + private long? _stage; + + [Newtonsoft.Json.JsonProperty("incoming", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Incoming + { + get { return _incoming; } + set + { + if (_incoming != value) + { + _incoming = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("amount", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Amount + { + get { return _amount; } + set + { + if (_amount != value) + { + _amount = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("outpoint", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Outpoint + { + get { return _outpoint; } + set + { + if (_outpoint != value) + { + _outpoint = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("maturity_height", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Maturity_height + { + get { return _maturity_height; } + set + { + if (_maturity_height != value) + { + _maturity_height = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The number of blocks remaining until the current stage can be swept. + /// Negative values indicate how many blocks have passed since becoming + /// mature. + [Newtonsoft.Json.JsonProperty("blocks_til_maturity", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Blocks_til_maturity + { + get { return _blocks_til_maturity; } + set + { + if (_blocks_til_maturity != value) + { + _blocks_til_maturity = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("stage", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Stage + { + get { return _stage; } + set + { + if (_stage != value) + { + _stage = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcPendingHTLC FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcPendingUpdate : System.ComponentModel.INotifyPropertyChanged + { + private byte[] _txid; + private long? _output_index; + + [Newtonsoft.Json.JsonProperty("txid", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Txid + { + get { return _txid; } + set + { + if (_txid != value) + { + _txid = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("output_index", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Output_index + { + get { return _output_index; } + set + { + if (_output_index != value) + { + _output_index = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcPendingUpdate FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcPolicyUpdateRequest : System.ComponentModel.INotifyPropertyChanged + { + private bool? _global; + private LnrpcChannelPoint _chan_point; + private string _base_fee_msat; + private double? _fee_rate; + private long? _time_lock_delta; + + /// / If set, then this update applies to all currently active channels. + [Newtonsoft.Json.JsonProperty("global", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Global + { + get { return _global; } + set + { + if (_global != value) + { + _global = value; + RaisePropertyChanged(); + } + } + } + + /// / If set, this update will target a specific channel. + [Newtonsoft.Json.JsonProperty("chan_point", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcChannelPoint Chan_point + { + get { return _chan_point; } + set + { + if (_chan_point != value) + { + _chan_point = value; + RaisePropertyChanged(); + } + } + } + + /// / The base fee charged regardless of the number of milli-satoshis sent. + [Newtonsoft.Json.JsonProperty("base_fee_msat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Base_fee_msat + { + get { return _base_fee_msat; } + set + { + if (_base_fee_msat != value) + { + _base_fee_msat = value; + RaisePropertyChanged(); + } + } + } + + /// / The effective fee rate in milli-satoshis. The precision of this value goes up to 6 decimal places, so 1e-6. + [Newtonsoft.Json.JsonProperty("fee_rate", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public double? Fee_rate + { + get { return _fee_rate; } + set + { + if (_fee_rate != value) + { + _fee_rate = value; + RaisePropertyChanged(); + } + } + } + + /// / The required timelock delta for HTLCs forwarded over the channel. + [Newtonsoft.Json.JsonProperty("time_lock_delta", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Time_lock_delta + { + get { return _time_lock_delta; } + set + { + if (_time_lock_delta != value) + { + _time_lock_delta = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcPolicyUpdateRequest FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcQueryRoutesResponse : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _routes; + + [Newtonsoft.Json.JsonProperty("routes", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Routes + { + get { return _routes; } + set + { + if (_routes != value) + { + _routes = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcQueryRoutesResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + /// * + /// A path through the channel graph which runs over one or more channels in + /// succession. This struct carries all the information required to craft the + /// Sphinx onion packet, and send the payment along the first hop in the path. A + /// route is only selected as valid if all the channels have sufficient capacity to + /// carry the initial payment amount after fees are accounted for. + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcRoute : System.ComponentModel.INotifyPropertyChanged + { + private long? _total_time_lock; + private string _total_fees; + private string _total_amt; + private System.Collections.ObjectModel.ObservableCollection _hops; + private string _total_fees_msat; + private string _total_amt_msat; + + /// * + /// The cumulative (final) time lock across the entire route. This is the CLTV + /// value that should be extended to the first hop in the route. All other hops + /// will decrement the time-lock as advertised, leaving enough time for all + /// hops to wait for or present the payment preimage to complete the payment. + [Newtonsoft.Json.JsonProperty("total_time_lock", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Total_time_lock + { + get { return _total_time_lock; } + set + { + if (_total_time_lock != value) + { + _total_time_lock = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The sum of the fees paid at each hop within the final route. In the case + /// of a one-hop payment, this value will be zero as we don't need to pay a fee + /// it ourself. + [Newtonsoft.Json.JsonProperty("total_fees", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_fees + { + get { return _total_fees; } + set + { + if (_total_fees != value) + { + _total_fees = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The total amount of funds required to complete a payment over this route. + /// This value includes the cumulative fees at each hop. As a result, the HTLC + /// extended to the first-hop in the route will need to have at least this many + /// satoshis, otherwise the route will fail at an intermediate node due to an + /// insufficient amount of fees. + [Newtonsoft.Json.JsonProperty("total_amt", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_amt + { + get { return _total_amt; } + set + { + if (_total_amt != value) + { + _total_amt = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// Contains details concerning the specific forwarding details at each hop. + [Newtonsoft.Json.JsonProperty("hops", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Hops + { + get { return _hops; } + set + { + if (_hops != value) + { + _hops = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The total fees in millisatoshis. + [Newtonsoft.Json.JsonProperty("total_fees_msat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_fees_msat + { + get { return _total_fees_msat; } + set + { + if (_total_fees_msat != value) + { + _total_fees_msat = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// The total amount in millisatoshis. + [Newtonsoft.Json.JsonProperty("total_amt_msat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_amt_msat + { + get { return _total_amt_msat; } + set + { + if (_total_amt_msat != value) + { + _total_amt_msat = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcRoute FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcRouteHint : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _hop_hints; + + /// * + /// A list of hop hints that when chained together can assist in reaching a + /// specific destination. + [Newtonsoft.Json.JsonProperty("hop_hints", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Hop_hints + { + get { return _hop_hints; } + set + { + if (_hop_hints != value) + { + _hop_hints = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcRouteHint FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcRoutingPolicy : System.ComponentModel.INotifyPropertyChanged + { + private long? _time_lock_delta; + private string _min_htlc; + private string _fee_base_msat; + private string _fee_rate_milli_msat; + + [Newtonsoft.Json.JsonProperty("time_lock_delta", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long? Time_lock_delta + { + get { return _time_lock_delta; } + set + { + if (_time_lock_delta != value) + { + _time_lock_delta = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("min_htlc", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Min_htlc + { + get { return _min_htlc; } + set + { + if (_min_htlc != value) + { + _min_htlc = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("fee_base_msat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fee_base_msat + { + get { return _fee_base_msat; } + set + { + if (_fee_base_msat != value) + { + _fee_base_msat = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("fee_rate_milli_msat", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Fee_rate_milli_msat + { + get { return _fee_rate_milli_msat; } + set + { + if (_fee_rate_milli_msat != value) + { + _fee_rate_milli_msat = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcRoutingPolicy FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcSendCoinsRequest : System.ComponentModel.INotifyPropertyChanged + { + private string _addr; + private string _amount; + private int? _target_conf; + private string _sat_per_byte; + + [Newtonsoft.Json.JsonProperty("addr", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Addr + { + get { return _addr; } + set + { + if (_addr != value) + { + _addr = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("amount", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Amount + { + get { return _amount; } + set + { + if (_amount != value) + { + _amount = value; + RaisePropertyChanged(); + } + } + } + + /// / The target number of blocks that this transaction should be confirmed by. + [Newtonsoft.Json.JsonProperty("target_conf", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Target_conf + { + get { return _target_conf; } + set + { + if (_target_conf != value) + { + _target_conf = value; + RaisePropertyChanged(); + } + } + } + + /// / A manual fee rate set in sat/byte that should be used when crafting the transaction. + [Newtonsoft.Json.JsonProperty("sat_per_byte", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Sat_per_byte + { + get { return _sat_per_byte; } + set + { + if (_sat_per_byte != value) + { + _sat_per_byte = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcSendCoinsRequest FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcSendCoinsResponse : System.ComponentModel.INotifyPropertyChanged + { + private string _txid; + + [Newtonsoft.Json.JsonProperty("txid", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Txid + { + get { return _txid; } + set + { + if (_txid != value) + { + _txid = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcSendCoinsResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcSendManyResponse : System.ComponentModel.INotifyPropertyChanged + { + private string _txid; + + [Newtonsoft.Json.JsonProperty("txid", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Txid + { + get { return _txid; } + set + { + if (_txid != value) + { + _txid = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcSendManyResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcSendRequest : System.ComponentModel.INotifyPropertyChanged + { + private byte[] _dest; + private string _dest_string; + private string _amt; + private byte[] _payment_hash; + private string _payment_hash_string; + private string _payment_request; + private int? _final_cltv_delta; + + [Newtonsoft.Json.JsonProperty("dest", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Dest + { + get { return _dest; } + set + { + if (_dest != value) + { + _dest = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("dest_string", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Dest_string + { + get { return _dest_string; } + set + { + if (_dest_string != value) + { + _dest_string = value; + RaisePropertyChanged(); + } + } + } + + /// / Number of satoshis to send. + [Newtonsoft.Json.JsonProperty("amt", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Amt + { + get { return _amt; } + set + { + if (_amt != value) + { + _amt = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("payment_hash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Payment_hash + { + get { return _payment_hash; } + set + { + if (_payment_hash != value) + { + _payment_hash = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("payment_hash_string", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Payment_hash_string + { + get { return _payment_hash_string; } + set + { + if (_payment_hash_string != value) + { + _payment_hash_string = value; + RaisePropertyChanged(); + } + } + } + + /// * + /// A bare-bones invoice for a payment within the Lightning Network. With the + /// details of the invoice, the sender has all the data necessary to send a + /// payment to the recipient. + [Newtonsoft.Json.JsonProperty("payment_request", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Payment_request + { + get { return _payment_request; } + set + { + if (_payment_request != value) + { + _payment_request = value; + RaisePropertyChanged(); + } + } + } + + /// / The CLTV delta from the current height that should be used to set the timelock for the final hop. + [Newtonsoft.Json.JsonProperty("final_cltv_delta", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Final_cltv_delta + { + get { return _final_cltv_delta; } + set + { + if (_final_cltv_delta != value) + { + _final_cltv_delta = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcSendRequest FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcSendResponse : System.ComponentModel.INotifyPropertyChanged + { + private string _payment_error; + private byte[] _payment_preimage; + private LnrpcRoute _payment_route; + + [Newtonsoft.Json.JsonProperty("payment_error", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Payment_error + { + get { return _payment_error; } + set + { + if (_payment_error != value) + { + _payment_error = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("payment_preimage", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Payment_preimage + { + get { return _payment_preimage; } + set + { + if (_payment_preimage != value) + { + _payment_preimage = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("payment_route", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public LnrpcRoute Payment_route + { + get { return _payment_route; } + set + { + if (_payment_route != value) + { + _payment_route = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcSendResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcSignMessageResponse : System.ComponentModel.INotifyPropertyChanged + { + private string _signature; + + [Newtonsoft.Json.JsonProperty("signature", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Signature + { + get { return _signature; } + set + { + if (_signature != value) + { + _signature = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcSignMessageResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcTransaction : System.ComponentModel.INotifyPropertyChanged + { + private string _tx_hash; + private string _amount; + private int? _num_confirmations; + private string _block_hash; + private int? _block_height; + private string _time_stamp; + private string _total_fees; + private System.Collections.ObjectModel.ObservableCollection _dest_addresses; + + [Newtonsoft.Json.JsonProperty("tx_hash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Tx_hash + { + get { return _tx_hash; } + set + { + if (_tx_hash != value) + { + _tx_hash = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("amount", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Amount + { + get { return _amount; } + set + { + if (_amount != value) + { + _amount = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("num_confirmations", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Num_confirmations + { + get { return _num_confirmations; } + set + { + if (_num_confirmations != value) + { + _num_confirmations = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("block_hash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Block_hash + { + get { return _block_hash; } + set + { + if (_block_hash != value) + { + _block_hash = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("block_height", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Block_height + { + get { return _block_height; } + set + { + if (_block_height != value) + { + _block_height = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("time_stamp", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Time_stamp + { + get { return _time_stamp; } + set + { + if (_time_stamp != value) + { + _time_stamp = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("total_fees", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_fees + { + get { return _total_fees; } + set + { + if (_total_fees != value) + { + _total_fees = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("dest_addresses", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Dest_addresses + { + get { return _dest_addresses; } + set + { + if (_dest_addresses != value) + { + _dest_addresses = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcTransaction FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcTransactionDetails : System.ComponentModel.INotifyPropertyChanged + { + private System.Collections.ObjectModel.ObservableCollection _transactions; + + /// / The list of transactions relevant to the wallet. + [Newtonsoft.Json.JsonProperty("transactions", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.ObjectModel.ObservableCollection Transactions + { + get { return _transactions; } + set + { + if (_transactions != value) + { + _transactions = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcTransactionDetails FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcUnlockWalletRequest : System.ComponentModel.INotifyPropertyChanged + { + private byte[] _wallet_password; + + /// * + /// wallet_password should be the current valid passphrase for the daemon. This + /// will be required to decrypt on-disk material that the daemon requires to + /// function properly. + [Newtonsoft.Json.JsonProperty("wallet_password", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public byte[] Wallet_password + { + get { return _wallet_password; } + set + { + if (_wallet_password != value) + { + _wallet_password = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcUnlockWalletRequest FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcVerifyMessageResponse : System.ComponentModel.INotifyPropertyChanged + { + private bool? _valid; + private string _pubkey; + + [Newtonsoft.Json.JsonProperty("valid", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool? Valid + { + get { return _valid; } + set + { + if (_valid != value) + { + _valid = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("pubkey", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Pubkey + { + get { return _pubkey; } + set + { + if (_pubkey != value) + { + _pubkey = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcVerifyMessageResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.9.11.0 (Newtonsoft.Json v9.0.0.0)")] + public partial class LnrpcWalletBalanceResponse : System.ComponentModel.INotifyPropertyChanged + { + private string _total_balance; + private string _confirmed_balance; + private string _unconfirmed_balance; + + [Newtonsoft.Json.JsonProperty("total_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Total_balance + { + get { return _total_balance; } + set + { + if (_total_balance != value) + { + _total_balance = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("confirmed_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Confirmed_balance + { + get { return _confirmed_balance; } + set + { + if (_confirmed_balance != value) + { + _confirmed_balance = value; + RaisePropertyChanged(); + } + } + } + + [Newtonsoft.Json.JsonProperty("unconfirmed_balance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Unconfirmed_balance + { + get { return _unconfirmed_balance; } + set + { + if (_unconfirmed_balance != value) + { + _unconfirmed_balance = value; + RaisePropertyChanged(); + } + } + } + + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + + public string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this); + } + + public static LnrpcWalletBalanceResponse FromJson(string data) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(data); + } + + protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) + handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "11.11.1.0")] + public class SwaggerException : System.Exception + { + public string StatusCode { get; private set; } + + public string Response { get; private set; } + + public System.Collections.Generic.Dictionary> Headers { get; private set; } + + public SwaggerException(string message, string statusCode, string response, System.Collections.Generic.Dictionary> headers, System.Exception innerException) + : base(message, innerException) + { + StatusCode = statusCode; + Response = response; + Headers = headers; + } + + public override string ToString() + { + return string.Format("HTTP Response: \n\n{0}\n\n{1}", Response, base.ToString()); + } + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "11.11.1.0")] + public class SwaggerException : SwaggerException + { + public TResult Result { get; private set; } + + public SwaggerException(string message, string statusCode, string response, System.Collections.Generic.Dictionary> headers, TResult result, System.Exception innerException) + : base(message, statusCode, response, headers, innerException) + { + Result = result; + } + } + +} \ No newline at end of file From ad3b605148f91a8bcdfb1f6dcad11de85529e396 Mon Sep 17 00:00:00 2001 From: lepipele Date: Thu, 26 Apr 2018 21:38:57 -0500 Subject: [PATCH 02/45] Adding ZMQ settings Lnd needs --- BTCPayServer.Tests/docker-compose.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 0ea276438..1fa687767 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -80,8 +80,12 @@ services: rpcport=43782 port=39388 whitelist=0.0.0.0/0 + zmqpubrawtx=tcp://0.0.0.0:28332 + zmqpubrawtxlock=tcp://0.0.0.0:28332 + zmqpubhashblock=tcp://0.0.0.0:28332 ports: - "43782:43782" + - "28332:28332" expose: - "43782" # RPC - "39388" # P2P From 131328b42c6ef6c646954950b487be9d834223c8 Mon Sep 17 00:00:00 2001 From: lepipele Date: Fri, 27 Apr 2018 23:35:58 -0500 Subject: [PATCH 03/45] Foundation integration with Lnd --- BTCPayServer.Tests/UnitTestPeusa.cs | 21 +- BTCPayServer/BTCPayServer.csproj | 1 - .../Payments/Lightning/Lnd/LndClient.cs | 120 +++++++++++ .../{LndrpcClient.cs => LndSwaggerClient.cs} | 199 ++++++++---------- 4 files changed, 230 insertions(+), 111 deletions(-) create mode 100644 BTCPayServer/Payments/Lightning/Lnd/LndClient.cs rename BTCPayServer/Payments/Lightning/Lnd/{LndrpcClient.cs => LndSwaggerClient.cs} (98%) diff --git a/BTCPayServer.Tests/UnitTestPeusa.cs b/BTCPayServer.Tests/UnitTestPeusa.cs index cb9861d5f..48ed0f5d6 100644 --- a/BTCPayServer.Tests/UnitTestPeusa.cs +++ b/BTCPayServer.Tests/UnitTestPeusa.cs @@ -1,9 +1,16 @@ -using NBitcoin; +using BTCPayServer.Payments.Lightning.Lnd; +using NBitcoin; using NBitcoin.DataEncoders; using NBitpayClient; using System; using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; using System.Text; +using System.Threading.Tasks; using Xunit; namespace BTCPayServer.Tests @@ -48,5 +55,17 @@ namespace BTCPayServer.Tests ExtPubKey pubkey = masterPubKey.Derive(0); Console.WriteLine("PubKey " + 0 + " : " + pubkey.ToString(network)); } + + [Fact] + public async Task TestLndAsync() + { + var tls = File.ReadAllBytes(@"c:\Users\newdawn\AppData\Local\Lnd\tls.cert"); + var macroon = File.ReadAllBytes(@"c:\Users\newdawn\AppData\Local\Lnd\admin.macaroon"); + + var lnd = new LndClient(new Uri("https://localhost:8080"), Network.RegTest, tls, macroon); + var res = await lnd.GetInfo(); + + Console.WriteLine("Address: " + res.Address); + } } } diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index e070297ff..f98b986e4 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -113,7 +113,6 @@ - diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs new file mode 100644 index 000000000..2a18538d5 --- /dev/null +++ b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Security; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using NBitcoin; + +namespace BTCPayServer.Payments.Lightning.Lnd +{ + public class LndClient : ILightningInvoiceClient, ILightningListenInvoiceSession + { + public LndClient(Uri uri, Network network, byte[] tlsCertificate, byte[] grpcMacaroon) + { + _HttpClient = HttpClientFactoryForLnd.Generate(tlsCertificate, grpcMacaroon); + _Decorator = new LndSwaggerClient(uri.ToString().TrimEnd('/'), _HttpClient); + } + + private HttpClient _HttpClient; + private LndSwaggerClient _Decorator; + + public async Task CreateInvoice(LightMoney amount, string description, TimeSpan expiry, CancellationToken cancellation = default(CancellationToken)) + { + var resp = await _Decorator.AddInvoiceAsync(new LnrpcInvoice + { + Value = (long)amount.ToDecimal(LightMoneyUnit.Satoshi), + Memo = description, + Expiry = (long)expiry.TotalSeconds + }); + throw new NotImplementedException(); + } + + public async Task GetInfo(CancellationToken cancellation = default(CancellationToken)) + { + var resp = await _Decorator.GetInfoAsync(cancellation); + + var invoice = new LightningNodeInformation + { + Address = resp.Uris?.FirstOrDefault(), + BlockHeight = (int?)resp.Block_height ?? 0, + NodeId = resp.Alias, + P2PPort = 0 + }; + return invoice; + } + + public async Task GetInvoice(string invoiceId, CancellationToken cancellation = default(CancellationToken)) + { + // var resp = await _decorator.LookupInvoiceAsync(invoiceId, null, cancellation); + throw new NotImplementedException(); + } + + public Task Listen(CancellationToken cancellation = default(CancellationToken)) + { + return Task.FromResult(this); + } + + async Task ILightningListenInvoiceSession.WaitInvoice(CancellationToken cancellation) + { + //var resp = await _decorator.SubscribeInvoicesAsync(cancellation); + throw new NotImplementedException(); + } + + public void Dispose() + { + _HttpClient?.Dispose(); + } + } + + internal class HttpClientFactoryForLnd + { + internal static HttpClient Generate(byte[] tlsCertificate, byte[] grpcMacaroon) + { + var httpClient = new HttpClient(GetCertificate(tlsCertificate)); + var macaroonHex = BitConverter.ToString(grpcMacaroon).Replace("-", "", StringComparison.InvariantCulture); + httpClient.DefaultRequestHeaders.Add("Grpc-Metadata-macaroon", macaroonHex); + + return httpClient; + } + + private static HttpClientHandler GetCertificate(byte[] certFile) + { + var clientCertificate = new X509Certificate2(certFile); + + var handler = new HttpClientHandler + { + SslProtocols = SslProtocols.Tls12 + }; + + handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => + { + const SslPolicyErrors unforgivableErrors = + SslPolicyErrors.RemoteCertificateNotAvailable | + SslPolicyErrors.RemoteCertificateNameMismatch; + + if ((errors & unforgivableErrors) != 0) + { + return false; + } + + X509Certificate2 remoteRoot = chain.ChainElements[chain.ChainElements.Count - 1].Certificate; + var res = clientCertificate.RawData.SequenceEqual(remoteRoot.RawData); + + return res; + }; + + return handler; + } + } + + partial class LndSwaggerClient + { + } +} diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndrpcClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs similarity index 98% rename from BTCPayServer/Payments/Lightning/Lnd/LndrpcClient.cs rename to BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs index 37ddd82d9..75246c8d8 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndrpcClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs @@ -4,19 +4,22 @@ // //---------------------- -namespace MyNamespace +namespace BTCPayServer.Payments.Lightning.Lnd { #pragma warning disable // Disable all warnings [System.CodeDom.Compiler.GeneratedCode("NSwag", "11.11.1.0")] - public partial class Client + partial class LndSwaggerClient { private System.Lazy _settings; private string _baseUrl = ""; - public Client(string baseUrl) + private System.Net.Http.HttpClient _httpClient; + + public LndSwaggerClient(string baseUrl, System.Net.Http.HttpClient httpClient) { BaseUrl = baseUrl; + _httpClient = httpClient; _settings = new System.Lazy(() => { var settings = new Newtonsoft.Json.JsonSerializerSettings(); @@ -57,7 +60,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/balance/blockchain"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -112,8 +115,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -136,7 +137,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/balance/channels"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -191,8 +192,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -220,7 +219,7 @@ namespace MyNamespace if (private_only != null) urlBuilder_.Append("private_only=").Append(System.Uri.EscapeDataString(System.Convert.ToString(private_only.Value, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); urlBuilder_.Length--; - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -275,8 +274,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -303,7 +300,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/channels"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -361,8 +358,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -389,7 +384,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/channels/pending"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -444,8 +439,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -472,7 +465,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/channels/transactions"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -530,8 +523,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -574,7 +565,7 @@ namespace MyNamespace urlBuilder_.Replace("{channel_point.funding_txid_str}", System.Uri.EscapeDataString(System.Convert.ToString(channel_point_funding_txid_str, System.Globalization.CultureInfo.InvariantCulture))); urlBuilder_.Replace("{channel_point.output_index}", System.Uri.EscapeDataString(System.Convert.ToString(channel_point_output_index, System.Globalization.CultureInfo.InvariantCulture))); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -629,8 +620,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -653,7 +642,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/chanpolicy"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -711,8 +700,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -735,7 +722,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/fees"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -790,8 +777,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -833,7 +818,7 @@ namespace MyNamespace if (seed_entropy != null) urlBuilder_.Append("seed_entropy=").Append(System.Uri.EscapeDataString(System.Convert.ToString(seed_entropy, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); urlBuilder_.Length--; - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -888,8 +873,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -914,7 +897,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/getinfo"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -969,8 +952,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1001,7 +982,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/graph"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1056,8 +1037,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1088,7 +1067,7 @@ namespace MyNamespace urlBuilder_.Append(BaseUrl).Append("/v1/graph/edge/{chan_id}"); urlBuilder_.Replace("{chan_id}", System.Uri.EscapeDataString(System.Convert.ToString(chan_id, System.Globalization.CultureInfo.InvariantCulture))); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1143,8 +1122,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1167,7 +1144,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/graph/info"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1222,8 +1199,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1250,7 +1225,7 @@ namespace MyNamespace urlBuilder_.Append(BaseUrl).Append("/v1/graph/node/{pub_key}"); urlBuilder_.Replace("{pub_key}", System.Uri.EscapeDataString(System.Convert.ToString(pub_key, System.Globalization.CultureInfo.InvariantCulture))); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1305,8 +1280,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1347,7 +1320,7 @@ namespace MyNamespace if (num_routes != null) urlBuilder_.Append("num_routes=").Append(System.Uri.EscapeDataString(System.Convert.ToString(num_routes.Value, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); urlBuilder_.Length--; - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1402,8 +1375,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1430,7 +1401,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/initwallet"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1488,8 +1459,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1522,7 +1491,7 @@ namespace MyNamespace if (r_hash != null) urlBuilder_.Append("r_hash=").Append(System.Uri.EscapeDataString(System.Convert.ToString(r_hash, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); urlBuilder_.Length--; - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1577,8 +1546,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1605,7 +1572,7 @@ namespace MyNamespace if (pending_only != null) urlBuilder_.Append("pending_only=").Append(System.Uri.EscapeDataString(System.Convert.ToString(pending_only.Value, System.Globalization.CultureInfo.InvariantCulture))).Append("&"); urlBuilder_.Length--; - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1660,8 +1627,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1686,7 +1651,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/invoices"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1744,8 +1709,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1770,7 +1733,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/invoices/subscribe"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1825,8 +1788,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1847,7 +1808,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/newaddress"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1902,8 +1863,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -1924,7 +1883,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/payments"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -1979,8 +1938,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -2001,7 +1958,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/payments"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -2056,8 +2013,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -2086,7 +2041,7 @@ namespace MyNamespace urlBuilder_.Append(BaseUrl).Append("/v1/payreq/{pay_req}"); urlBuilder_.Replace("{pay_req}", System.Uri.EscapeDataString(System.Convert.ToString(pay_req, System.Globalization.CultureInfo.InvariantCulture))); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -2141,8 +2096,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -2163,7 +2116,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/peers"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -2218,8 +2171,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -2244,7 +2195,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/peers"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -2302,8 +2253,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -2332,7 +2281,7 @@ namespace MyNamespace urlBuilder_.Append(BaseUrl).Append("/v1/peers/{pub_key}"); urlBuilder_.Replace("{pub_key}", System.Uri.EscapeDataString(System.Convert.ToString(pub_key, System.Globalization.CultureInfo.InvariantCulture))); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -2387,8 +2336,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -2415,7 +2362,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/switch"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -2473,8 +2420,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -2497,7 +2442,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/transactions"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -2552,8 +2497,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -2582,7 +2525,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/transactions"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -2640,8 +2583,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -2664,7 +2605,7 @@ namespace MyNamespace var urlBuilder_ = new System.Text.StringBuilder(); urlBuilder_.Append(BaseUrl).Append("/v1/unlockwallet"); - var client_ = new System.Net.Http.HttpClient(); + var client_ = _httpClient; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) @@ -2722,8 +2663,6 @@ namespace MyNamespace } finally { - if (client_ != null) - client_.Dispose(); } } @@ -5532,6 +5471,7 @@ namespace MyNamespace private byte[] _wallet_password; private System.Collections.ObjectModel.ObservableCollection _cipher_seed_mnemonic; private byte[] _aezeed_passphrase; + private int? _recovery_window; /// * /// wallet_password is the passphrase that should be used to encrypt the @@ -5586,6 +5526,26 @@ namespace MyNamespace } } + /// * + /// recovery_window is an optional argument specifying the address lookahead + /// when restoring a wallet seed. The recovery window applies to each + /// invdividual branch of the BIP44 derivation paths. Supplying a recovery + /// window of zero indicates that no addresses should be recovered, such after + /// the first initialization of the wallet. + [Newtonsoft.Json.JsonProperty("recovery_window", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Recovery_window + { + get { return _recovery_window; } + set + { + if (_recovery_window != value) + { + _recovery_window = value; + RaisePropertyChanged(); + } + } + } + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; public string ToJson() @@ -5613,15 +5573,15 @@ namespace MyNamespace private byte[] _receipt; private byte[] _r_preimage; private byte[] _r_hash; - private string _value; + private long? _value; private bool? _settled; - private string _creation_date; - private string _settle_date; + private long? _creation_date; + private long? _settle_date; private string _payment_request; private byte[] _description_hash; - private string _expiry; + private long? _expiry; private string _fallback_addr; - private string _cltv_expiry; + private int? _cltv_expiry; private System.Collections.ObjectModel.ObservableCollection _route_hints; private bool? _private; @@ -5687,7 +5647,7 @@ namespace MyNamespace } [Newtonsoft.Json.JsonProperty("value", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string Value + public long? Value { get { return _value; } set @@ -5715,7 +5675,7 @@ namespace MyNamespace } [Newtonsoft.Json.JsonProperty("creation_date", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string Creation_date + public long? Creation_date { get { return _creation_date; } set @@ -5729,7 +5689,7 @@ namespace MyNamespace } [Newtonsoft.Json.JsonProperty("settle_date", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string Settle_date + public long? Settle_date { get { return _settle_date; } set @@ -5780,7 +5740,7 @@ namespace MyNamespace /// / Payment request expiry time in seconds. Default is 3600 (1 hour). [Newtonsoft.Json.JsonProperty("expiry", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string Expiry + public long? Expiry { get { return _expiry; } set @@ -5810,7 +5770,7 @@ namespace MyNamespace /// / Delta to use for the time-lock of the CLTV extended to the final hop. [Newtonsoft.Json.JsonProperty("cltv_expiry", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string Cltv_expiry + public int? Cltv_expiry { get { return _cltv_expiry; } set @@ -8540,6 +8500,7 @@ namespace MyNamespace public partial class LnrpcUnlockWalletRequest : System.ComponentModel.INotifyPropertyChanged { private byte[] _wallet_password; + private int? _recovery_window; /// * /// wallet_password should be the current valid passphrase for the daemon. This @@ -8559,6 +8520,26 @@ namespace MyNamespace } } + /// * + /// recovery_window is an optional argument specifying the address lookahead + /// when restoring a wallet seed. The recovery window applies to each + /// invdividual branch of the BIP44 derivation paths. Supplying a recovery + /// window of zero indicates that no addresses should be recovered, such after + /// the first initialization of the wallet. + [Newtonsoft.Json.JsonProperty("recovery_window", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Recovery_window + { + get { return _recovery_window; } + set + { + if (_recovery_window != value) + { + _recovery_window = value; + RaisePropertyChanged(); + } + } + } + public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; public string ToJson() From 1743919cd478a33a42e3fbafefe2de5ec170c331 Mon Sep 17 00:00:00 2001 From: lepipele Date: Sat, 28 Apr 2018 00:39:43 -0500 Subject: [PATCH 04/45] Conversion of LnrpcInvoice into LightningInvoice --- .../Payments/Lightning/Lnd/LndClient.cs | 51 +++++++++++++++++-- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs index 2a18538d5..522e01225 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; @@ -33,7 +34,16 @@ namespace BTCPayServer.Payments.Lightning.Lnd Memo = description, Expiry = (long)expiry.TotalSeconds }); - throw new NotImplementedException(); + + var invoice = new LightningInvoice + { + // TODO: Verify id corresponds to R_hash + Id = BitString(resp.R_hash), + Amount = amount, + BOLT11 = resp.Payment_request, + Status = "unpaid" + }; + return invoice; } public async Task GetInfo(CancellationToken cancellation = default(CancellationToken)) @@ -52,8 +62,8 @@ namespace BTCPayServer.Payments.Lightning.Lnd public async Task GetInvoice(string invoiceId, CancellationToken cancellation = default(CancellationToken)) { - // var resp = await _decorator.LookupInvoiceAsync(invoiceId, null, cancellation); - throw new NotImplementedException(); + var resp = await _Decorator.LookupInvoiceAsync(invoiceId, null, cancellation); + return ConvertLndInvoice(resp); } public Task Listen(CancellationToken cancellation = default(CancellationToken)) @@ -63,14 +73,45 @@ namespace BTCPayServer.Payments.Lightning.Lnd async Task ILightningListenInvoiceSession.WaitInvoice(CancellationToken cancellation) { - //var resp = await _decorator.SubscribeInvoicesAsync(cancellation); - throw new NotImplementedException(); + var resp = await _Decorator.SubscribeInvoicesAsync(cancellation); + return ConvertLndInvoice(resp); + } public void Dispose() { _HttpClient?.Dispose(); } + + private static string BitString(byte[] bytes) + { + return BitConverter.ToString(bytes) + .Replace("-", "", StringComparison.InvariantCulture) + .ToLower(CultureInfo.InvariantCulture); + } + + private static LightningInvoice ConvertLndInvoice(LnrpcInvoice resp) + { + var invoice = new LightningInvoice + { + // TODO: Verify id corresponds to R_hash + Id = BitString(resp.R_hash), + Amount = resp.Value, + BOLT11 = resp.Payment_request, + Status = "unpaid" + }; + + if (resp.Settle_date.HasValue) + { + invoice.PaidAt = DateTimeOffset.FromUnixTimeSeconds(resp.Settle_date.Value); + invoice.Status = "paid"; + } + else if (DateTimeOffset.FromUnixTimeSeconds(resp.Creation_date.Value + resp.Expiry.Value) > DateTimeOffset.UtcNow) + { + invoice.Status = "expired"; + } + return invoice; + } } internal class HttpClientFactoryForLnd From 69050f7a5624165750e017d007cc44aef0fa9f75 Mon Sep 17 00:00:00 2001 From: lepipele Date: Sat, 28 Apr 2018 12:49:56 -0500 Subject: [PATCH 05/45] Lnd sends some integers as strings, testing invoice creation --- BTCPayServer.Tests/UnitTestPeusa.cs | 12 ++++++ .../Payments/Lightning/Lnd/LndClient.cs | 41 +++++++++++++++---- .../Lightning/Lnd/LndSwaggerClient.cs | 20 ++++----- 3 files changed, 56 insertions(+), 17 deletions(-) diff --git a/BTCPayServer.Tests/UnitTestPeusa.cs b/BTCPayServer.Tests/UnitTestPeusa.cs index 48ed0f5d6..d53566fcb 100644 --- a/BTCPayServer.Tests/UnitTestPeusa.cs +++ b/BTCPayServer.Tests/UnitTestPeusa.cs @@ -67,5 +67,17 @@ namespace BTCPayServer.Tests Console.WriteLine("Address: " + res.Address); } + + [Fact] + public async Task LndCreateInvoice() + { + var tls = File.ReadAllBytes(@"c:\Users\newdawn\AppData\Local\Lnd\tls.cert"); + var macroon = File.ReadAllBytes(@"c:\Users\newdawn\AppData\Local\Lnd\admin.macaroon"); + + var lnd = new LndClient(new Uri("https://127.0.0.1:8080"), Network.RegTest, tls, macroon); + var res = await lnd.CreateInvoice(10000, "Hello world", TimeSpan.FromSeconds(3600)); + + Console.WriteLine("Result: "+ res.ToJson()); + } } } diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs index 522e01225..342f1bd73 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs @@ -26,13 +26,17 @@ namespace BTCPayServer.Payments.Lightning.Lnd private HttpClient _HttpClient; private LndSwaggerClient _Decorator; - public async Task CreateInvoice(LightMoney amount, string description, TimeSpan expiry, CancellationToken cancellation = default(CancellationToken)) + public async Task CreateInvoice(LightMoney amount, string description, TimeSpan expiry, + CancellationToken cancellation = default(CancellationToken)) { + var strAmount = ConvertInv.ToString(amount.ToUnit(LightMoneyUnit.Satoshi)); + var strExpiry = ConvertInv.ToString(expiry.TotalSeconds); + // lnd requires numbers sent as strings. don't ask var resp = await _Decorator.AddInvoiceAsync(new LnrpcInvoice { - Value = (long)amount.ToDecimal(LightMoneyUnit.Satoshi), + Value = strAmount, Memo = description, - Expiry = (long)expiry.TotalSeconds + Expiry = strExpiry }); var invoice = new LightningInvoice @@ -101,17 +105,40 @@ namespace BTCPayServer.Payments.Lightning.Lnd Status = "unpaid" }; - if (resp.Settle_date.HasValue) + if (resp.Settle_date != null) { - invoice.PaidAt = DateTimeOffset.FromUnixTimeSeconds(resp.Settle_date.Value); + invoice.PaidAt = DateTimeOffset.FromUnixTimeSeconds(ConvertInv.ToInt64(resp.Settle_date)); invoice.Status = "paid"; } - else if (DateTimeOffset.FromUnixTimeSeconds(resp.Creation_date.Value + resp.Expiry.Value) > DateTimeOffset.UtcNow) + else { - invoice.Status = "expired"; + var invoiceExpiry = ConvertInv.ToInt64(resp.Creation_date) + ConvertInv.ToInt64(resp.Expiry); + if (DateTimeOffset.FromUnixTimeSeconds(invoiceExpiry) > DateTimeOffset.UtcNow) + { + invoice.Status = "expired"; + } } return invoice; } + + // Invariant culture conversion + public static class ConvertInv + { + public static long ToInt64(string str) + { + return Convert.ToInt64(str, CultureInfo.InvariantCulture.NumberFormat); + } + + public static string ToString(decimal d) + { + return d.ToString(CultureInfo.InvariantCulture); + } + + public static string ToString(double d) + { + return d.ToString(CultureInfo.InvariantCulture); + } + } } internal class HttpClientFactoryForLnd diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs index 75246c8d8..91c3fe157 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs @@ -5573,15 +5573,15 @@ namespace BTCPayServer.Payments.Lightning.Lnd private byte[] _receipt; private byte[] _r_preimage; private byte[] _r_hash; - private long? _value; + private string _value; private bool? _settled; - private long? _creation_date; - private long? _settle_date; + private string _creation_date; + private string _settle_date; private string _payment_request; private byte[] _description_hash; - private long? _expiry; + private string _expiry; private string _fallback_addr; - private int? _cltv_expiry; + private string _cltv_expiry; private System.Collections.ObjectModel.ObservableCollection _route_hints; private bool? _private; @@ -5647,7 +5647,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd } [Newtonsoft.Json.JsonProperty("value", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public long? Value + public string Value { get { return _value; } set @@ -5675,7 +5675,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd } [Newtonsoft.Json.JsonProperty("creation_date", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public long? Creation_date + public string Creation_date { get { return _creation_date; } set @@ -5689,7 +5689,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd } [Newtonsoft.Json.JsonProperty("settle_date", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public long? Settle_date + public string Settle_date { get { return _settle_date; } set @@ -5740,7 +5740,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd /// / Payment request expiry time in seconds. Default is 3600 (1 hour). [Newtonsoft.Json.JsonProperty("expiry", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public long? Expiry + public string Expiry { get { return _expiry; } set @@ -5770,7 +5770,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd /// / Delta to use for the time-lock of the CLTV extended to the final hop. [Newtonsoft.Json.JsonProperty("cltv_expiry", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public int? Cltv_expiry + public string Cltv_expiry { get { return _cltv_expiry; } set From f9f4d9319184c41c04c74b6a21b14f072c5308a1 Mon Sep 17 00:00:00 2001 From: lepipele Date: Sun, 29 Apr 2018 02:52:33 -0500 Subject: [PATCH 06/45] Lnd Dockerfile that integrates with BtcPayServer --- BTCPayServer.Tests/docker-compose.yml | 20 +++++++ BTCPayServer.Tests/docker/lnd/Dockerfile | 25 +++++++++ BTCPayServer.Tests/docker/lnd/start-lnd.sh | 63 ++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 BTCPayServer.Tests/docker/lnd/Dockerfile create mode 100644 BTCPayServer.Tests/docker/lnd/start-lnd.sh diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 1fa687767..1f193e380 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -44,6 +44,7 @@ services: - customer_lightningd - merchant_lightningd - lightning-charged + - lnd nbxplorer: image: nicolasdorier/nbxplorer:1.0.2.2 @@ -179,8 +180,27 @@ services: expose: - "5432" + lnd: + image: testing_lnd + environment: + RPCHOST: bitcoind:43782 + RPCUSER: ceiwHEbqWI83 + RPCPASS: DwubwWsoo3 + ZMQPATH: tcp://bitcoind:28332 + NETWORK: regtest + CHAIN: bitcoin + BACKEND: bitcoind + DEBUG: debug + ports: + - "53280:8080" + volumes: + - "lnd_datadir:/root/.lnd" + links: + - bitcoind + volumes: bitcoin_datadir: customer_lightningd_datadir: merchant_lightningd_datadir: lightning_charge_datadir: + lnd_datadir: diff --git a/BTCPayServer.Tests/docker/lnd/Dockerfile b/BTCPayServer.Tests/docker/lnd/Dockerfile new file mode 100644 index 000000000..d1e31dce7 --- /dev/null +++ b/BTCPayServer.Tests/docker/lnd/Dockerfile @@ -0,0 +1,25 @@ +FROM golang:1.10 + +MAINTAINER BtcPayServer + +# Force Go to use the cgo based DNS resolver. This is required to ensure DNS +# queries required to connect to linked containers succeed. +ENV GODEBUG netdns=cgo + +# Install dep to manage vendor. +RUN go get -u github.com/golang/dep/cmd/dep + +# Grab and install the latest version of lnd and all related dependencies. +RUN git clone https://github.com/lightningnetwork/lnd $GOPATH/src/github.com/lightningnetwork/lnd + +# Make lnd folder default. +WORKDIR $GOPATH/src/github.com/lightningnetwork/lnd + +# Install dependencies and install/build lnd. +RUN dep ensure +RUN go install . ./cmd/... + +COPY "start-lnd.sh" . +RUN chmod +x start-lnd.sh + +ENTRYPOINT ["./start-lnd.sh"] diff --git a/BTCPayServer.Tests/docker/lnd/start-lnd.sh b/BTCPayServer.Tests/docker/lnd/start-lnd.sh new file mode 100644 index 000000000..711d4fed2 --- /dev/null +++ b/BTCPayServer.Tests/docker/lnd/start-lnd.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +# exit from script if error was raised. +set -e + +# error function is used within a bash function in order to send the error +# message directly to the stderr output and exit. +error() { + echo "$1" > /dev/stderr + exit 0 +} + +# return is used within bash function in order to return the value. +return() { + echo "$1" +} + +# set_default function gives the ability to move the setting of default +# env variable from docker file to the script thereby giving the ability to the +# user override it durin container start. +set_default() { + # docker initialized env variables with blank string and we can't just + # use -z flag as usually. + BLANK_STRING='""' + + VARIABLE="$1" + DEFAULT="$2" + + if [[ -z "$VARIABLE" || "$VARIABLE" == "$BLANK_STRING" ]]; then + + if [ -z "$DEFAULT" ]; then + error "You should specify default variable" + else + VARIABLE="$DEFAULT" + fi + fi + + return "$VARIABLE" +} + +# Set default variables if needed. +RPCHOST=$(set_default "$RPCHOST" "127.0.0.1:43782") +RPCUSER=$(set_default "$RPCUSER" "devuser") +RPCPASS=$(set_default "$RPCPASS" "devpass") +ZMQPATH=$(set_default "$ZMQPATH" "tcp://127.0.0.1:28332") +DEBUG=$(set_default "$DEBUG" "debug") +NETWORK=$(set_default "$NETWORK" "regtest") +CHAIN=$(set_default "$CHAIN" "bitcoin") +BACKEND=$(set_default "$BACKEND" "bitcoind") + +exec lnd \ + --noencryptwallet \ + --logdir="/data" \ + "--$CHAIN.active" \ + "--$CHAIN.$NETWORK" \ + "--$CHAIN.node"="$BACKEND" \ + "--$BACKEND.rpchost"="$RPCHOST" \ + "--$BACKEND.rpcuser"="$RPCUSER" \ + "--$BACKEND.rpcpass"="$RPCPASS" \ + "--$BACKEND.zmqpath"="$ZMQPATH" \ + "--restlisten=0.0.0.0:8080" \ + --debuglevel="$DEBUG" \ + "$@" From 75f4a39ef2a1ef38207768eef6bf1b18e3745f60 Mon Sep 17 00:00:00 2001 From: lepipele Date: Sun, 29 Apr 2018 02:57:08 -0500 Subject: [PATCH 07/45] Adding script to build lnd Docker container for testing Obviously when we publish to Docker Hub this whole folder is bye-bye --- BTCPayServer.Tests/docker/lnd/build_lnd_docker.cmd | 1 + 1 file changed, 1 insertion(+) create mode 100644 BTCPayServer.Tests/docker/lnd/build_lnd_docker.cmd diff --git a/BTCPayServer.Tests/docker/lnd/build_lnd_docker.cmd b/BTCPayServer.Tests/docker/lnd/build_lnd_docker.cmd new file mode 100644 index 000000000..2f67802fe --- /dev/null +++ b/BTCPayServer.Tests/docker/lnd/build_lnd_docker.cmd @@ -0,0 +1 @@ +docker build -t testing_lnd . From f4f9fabfd3627f08a9cdd3a8d043c8dad1932605 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Tue, 1 May 2018 19:02:57 -0500 Subject: [PATCH 08/45] Building docker compose with our custom lnd --- BTCPayServer.Tests/docker/lnd/Dockerfile | 4 ++-- BTCPayServer.Tests/docker/lnd/start-lnd.sh | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BTCPayServer.Tests/docker/lnd/Dockerfile b/BTCPayServer.Tests/docker/lnd/Dockerfile index d1e31dce7..1f95ea187 100644 --- a/BTCPayServer.Tests/docker/lnd/Dockerfile +++ b/BTCPayServer.Tests/docker/lnd/Dockerfile @@ -10,10 +10,10 @@ ENV GODEBUG netdns=cgo RUN go get -u github.com/golang/dep/cmd/dep # Grab and install the latest version of lnd and all related dependencies. -RUN git clone https://github.com/lightningnetwork/lnd $GOPATH/src/github.com/lightningnetwork/lnd +RUN git clone -b dev https://github.com/btcpayserver/lnd $GOPATH/src/github.com/btcpayserver/lnd # Make lnd folder default. -WORKDIR $GOPATH/src/github.com/lightningnetwork/lnd +WORKDIR $GOPATH/src/github.com/btcpayserver/lnd # Install dependencies and install/build lnd. RUN dep ensure diff --git a/BTCPayServer.Tests/docker/lnd/start-lnd.sh b/BTCPayServer.Tests/docker/lnd/start-lnd.sh index 711d4fed2..8ba53e4fd 100644 --- a/BTCPayServer.Tests/docker/lnd/start-lnd.sh +++ b/BTCPayServer.Tests/docker/lnd/start-lnd.sh @@ -49,6 +49,7 @@ CHAIN=$(set_default "$CHAIN" "bitcoin") BACKEND=$(set_default "$BACKEND" "bitcoind") exec lnd \ + --no-macaroons \ --noencryptwallet \ --logdir="/data" \ "--$CHAIN.active" \ From fcfba7f5e137c72d0c4045a955ba58fae1788ca7 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Tue, 1 May 2018 20:33:43 -0500 Subject: [PATCH 09/45] Refactoring connection to Lnd now there is HTTP support --- BTCPayServer.Tests/UnitTestPeusa.cs | 24 ---------- BTCPayServer.Tests/UnitTests/LndTest.cs | 46 +++++++++++++++++++ BTCPayServer.Tests/docker/lnd/Dockerfile | 2 +- .../Payments/Lightning/Lnd/LndClient.cs | 17 +++++-- 4 files changed, 59 insertions(+), 30 deletions(-) create mode 100644 BTCPayServer.Tests/UnitTests/LndTest.cs diff --git a/BTCPayServer.Tests/UnitTestPeusa.cs b/BTCPayServer.Tests/UnitTestPeusa.cs index d53566fcb..d2b99bd80 100644 --- a/BTCPayServer.Tests/UnitTestPeusa.cs +++ b/BTCPayServer.Tests/UnitTestPeusa.cs @@ -55,29 +55,5 @@ namespace BTCPayServer.Tests ExtPubKey pubkey = masterPubKey.Derive(0); Console.WriteLine("PubKey " + 0 + " : " + pubkey.ToString(network)); } - - [Fact] - public async Task TestLndAsync() - { - var tls = File.ReadAllBytes(@"c:\Users\newdawn\AppData\Local\Lnd\tls.cert"); - var macroon = File.ReadAllBytes(@"c:\Users\newdawn\AppData\Local\Lnd\admin.macaroon"); - - var lnd = new LndClient(new Uri("https://localhost:8080"), Network.RegTest, tls, macroon); - var res = await lnd.GetInfo(); - - Console.WriteLine("Address: " + res.Address); - } - - [Fact] - public async Task LndCreateInvoice() - { - var tls = File.ReadAllBytes(@"c:\Users\newdawn\AppData\Local\Lnd\tls.cert"); - var macroon = File.ReadAllBytes(@"c:\Users\newdawn\AppData\Local\Lnd\admin.macaroon"); - - var lnd = new LndClient(new Uri("https://127.0.0.1:8080"), Network.RegTest, tls, macroon); - var res = await lnd.CreateInvoice(10000, "Hello world", TimeSpan.FromSeconds(3600)); - - Console.WriteLine("Result: "+ res.ToJson()); - } } } diff --git a/BTCPayServer.Tests/UnitTests/LndTest.cs b/BTCPayServer.Tests/UnitTests/LndTest.cs new file mode 100644 index 000000000..2433c39f9 --- /dev/null +++ b/BTCPayServer.Tests/UnitTests/LndTest.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using BTCPayServer.Payments.Lightning.Lnd; +using NBitcoin; +using Xunit; +using Xunit.Abstractions; + +namespace BTCPayServer.Tests.UnitTests +{ + public class LndTest + { + private readonly ITestOutputHelper output; + + public LndTest(ITestOutputHelper output) + { + this.output = output; + } + + private LndClient Client + { + get + { + var lnd = new LndClient(new Uri("http://localhost:53280"), Network.RegTest); + return lnd; + } + } + + [Fact] + public async Task GetInfo() + { + var res = await Client.GetInfo(); + + output.WriteLine("Result: " + res.ToJson()); + } + + [Fact] + public async Task CreateInvoice() + { + var res = await Client.CreateInvoice(10000, "Hello world", TimeSpan.FromSeconds(3600)); + + output.WriteLine("Result: " + res.ToJson()); + } + } +} diff --git a/BTCPayServer.Tests/docker/lnd/Dockerfile b/BTCPayServer.Tests/docker/lnd/Dockerfile index 1f95ea187..264f5443d 100644 --- a/BTCPayServer.Tests/docker/lnd/Dockerfile +++ b/BTCPayServer.Tests/docker/lnd/Dockerfile @@ -22,4 +22,4 @@ RUN go install . ./cmd/... COPY "start-lnd.sh" . RUN chmod +x start-lnd.sh -ENTRYPOINT ["./start-lnd.sh"] +ENTRYPOINT ["./start-lnd.sh"] \ No newline at end of file diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs index 342f1bd73..0358a4007 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs @@ -17,16 +17,19 @@ namespace BTCPayServer.Payments.Lightning.Lnd { public class LndClient : ILightningInvoiceClient, ILightningListenInvoiceSession { - public LndClient(Uri uri, Network network, byte[] tlsCertificate, byte[] grpcMacaroon) + public LndClient(Uri uri, Network network, byte[] tlsCertificate = null, byte[] grpcMacaroon = null) { - _HttpClient = HttpClientFactoryForLnd.Generate(tlsCertificate, grpcMacaroon); + // for now working with custom build of lnd that has no macaroons and is on http + //_HttpClient = HttpClientFactoryForLnd.Generate(tlsCertificate, grpcMacaroon); + + _HttpClient = new HttpClient(); _Decorator = new LndSwaggerClient(uri.ToString().TrimEnd('/'), _HttpClient); } private HttpClient _HttpClient; private LndSwaggerClient _Decorator; - public async Task CreateInvoice(LightMoney amount, string description, TimeSpan expiry, + public async Task CreateInvoice(LightMoney amount, string description, TimeSpan expiry, CancellationToken cancellation = default(CancellationToken)) { var strAmount = ConvertInv.ToString(amount.ToUnit(LightMoneyUnit.Satoshi)); @@ -41,7 +44,6 @@ namespace BTCPayServer.Payments.Lightning.Lnd var invoice = new LightningInvoice { - // TODO: Verify id corresponds to R_hash Id = BitString(resp.R_hash), Amount = amount, BOLT11 = resp.Payment_request, @@ -154,7 +156,9 @@ namespace BTCPayServer.Payments.Lightning.Lnd private static HttpClientHandler GetCertificate(byte[] certFile) { - var clientCertificate = new X509Certificate2(certFile); + X509Certificate2 clientCertificate = null; + if (certFile != null) + clientCertificate = new X509Certificate2(certFile); var handler = new HttpClientHandler { @@ -172,6 +176,9 @@ namespace BTCPayServer.Payments.Lightning.Lnd return false; } + if (clientCertificate == null) + return true; + X509Certificate2 remoteRoot = chain.ChainElements[chain.ChainElements.Count - 1].Certificate; var res = clientCertificate.RawData.SequenceEqual(remoteRoot.RawData); From cfbcf0947ac23ba92a0d8ccf796bafcd58c04cc3 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Tue, 1 May 2018 21:12:04 -0500 Subject: [PATCH 10/45] Switching to using Dockerfile from Docker Hub --- BTCPayServer.Tests/docker-compose.yml | 2 +- BTCPayServer.Tests/docker/lnd/Dockerfile | 25 -------- .../docker/lnd/build_lnd_docker.cmd | 1 - BTCPayServer.Tests/docker/lnd/start-lnd.sh | 64 ------------------- 4 files changed, 1 insertion(+), 91 deletions(-) delete mode 100644 BTCPayServer.Tests/docker/lnd/Dockerfile delete mode 100644 BTCPayServer.Tests/docker/lnd/build_lnd_docker.cmd delete mode 100644 BTCPayServer.Tests/docker/lnd/start-lnd.sh diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 1f193e380..ecdce19fe 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -181,7 +181,7 @@ services: - "5432" lnd: - image: testing_lnd + image: btcpayserver/lnd:0.4.1.0 environment: RPCHOST: bitcoind:43782 RPCUSER: ceiwHEbqWI83 diff --git a/BTCPayServer.Tests/docker/lnd/Dockerfile b/BTCPayServer.Tests/docker/lnd/Dockerfile deleted file mode 100644 index 264f5443d..000000000 --- a/BTCPayServer.Tests/docker/lnd/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM golang:1.10 - -MAINTAINER BtcPayServer - -# Force Go to use the cgo based DNS resolver. This is required to ensure DNS -# queries required to connect to linked containers succeed. -ENV GODEBUG netdns=cgo - -# Install dep to manage vendor. -RUN go get -u github.com/golang/dep/cmd/dep - -# Grab and install the latest version of lnd and all related dependencies. -RUN git clone -b dev https://github.com/btcpayserver/lnd $GOPATH/src/github.com/btcpayserver/lnd - -# Make lnd folder default. -WORKDIR $GOPATH/src/github.com/btcpayserver/lnd - -# Install dependencies and install/build lnd. -RUN dep ensure -RUN go install . ./cmd/... - -COPY "start-lnd.sh" . -RUN chmod +x start-lnd.sh - -ENTRYPOINT ["./start-lnd.sh"] \ No newline at end of file diff --git a/BTCPayServer.Tests/docker/lnd/build_lnd_docker.cmd b/BTCPayServer.Tests/docker/lnd/build_lnd_docker.cmd deleted file mode 100644 index 2f67802fe..000000000 --- a/BTCPayServer.Tests/docker/lnd/build_lnd_docker.cmd +++ /dev/null @@ -1 +0,0 @@ -docker build -t testing_lnd . diff --git a/BTCPayServer.Tests/docker/lnd/start-lnd.sh b/BTCPayServer.Tests/docker/lnd/start-lnd.sh deleted file mode 100644 index 8ba53e4fd..000000000 --- a/BTCPayServer.Tests/docker/lnd/start-lnd.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env bash - -# exit from script if error was raised. -set -e - -# error function is used within a bash function in order to send the error -# message directly to the stderr output and exit. -error() { - echo "$1" > /dev/stderr - exit 0 -} - -# return is used within bash function in order to return the value. -return() { - echo "$1" -} - -# set_default function gives the ability to move the setting of default -# env variable from docker file to the script thereby giving the ability to the -# user override it durin container start. -set_default() { - # docker initialized env variables with blank string and we can't just - # use -z flag as usually. - BLANK_STRING='""' - - VARIABLE="$1" - DEFAULT="$2" - - if [[ -z "$VARIABLE" || "$VARIABLE" == "$BLANK_STRING" ]]; then - - if [ -z "$DEFAULT" ]; then - error "You should specify default variable" - else - VARIABLE="$DEFAULT" - fi - fi - - return "$VARIABLE" -} - -# Set default variables if needed. -RPCHOST=$(set_default "$RPCHOST" "127.0.0.1:43782") -RPCUSER=$(set_default "$RPCUSER" "devuser") -RPCPASS=$(set_default "$RPCPASS" "devpass") -ZMQPATH=$(set_default "$ZMQPATH" "tcp://127.0.0.1:28332") -DEBUG=$(set_default "$DEBUG" "debug") -NETWORK=$(set_default "$NETWORK" "regtest") -CHAIN=$(set_default "$CHAIN" "bitcoin") -BACKEND=$(set_default "$BACKEND" "bitcoind") - -exec lnd \ - --no-macaroons \ - --noencryptwallet \ - --logdir="/data" \ - "--$CHAIN.active" \ - "--$CHAIN.$NETWORK" \ - "--$CHAIN.node"="$BACKEND" \ - "--$BACKEND.rpchost"="$RPCHOST" \ - "--$BACKEND.rpcuser"="$RPCUSER" \ - "--$BACKEND.rpcpass"="$RPCPASS" \ - "--$BACKEND.zmqpath"="$ZMQPATH" \ - "--restlisten=0.0.0.0:8080" \ - --debuglevel="$DEBUG" \ - "$@" From b03d271f8583309d2388493a9062fc6f667961ec Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 11 May 2018 14:07:46 -0500 Subject: [PATCH 11/45] Refactoring LndClient, enabling passing of Swagger instance --- BTCPayServer.Tests/UnitTests/LndTest.cs | 91 ++++++++++++++++--- .../Payments/Lightning/Lnd/LndClient.cs | 71 +++------------ .../Lnd/LndSwaggerClientCustomHttp.cs | 83 +++++++++++++++++ 3 files changed, 173 insertions(+), 72 deletions(-) create mode 100644 BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs diff --git a/BTCPayServer.Tests/UnitTests/LndTest.cs b/BTCPayServer.Tests/UnitTests/LndTest.cs index 2433c39f9..cae4f3216 100644 --- a/BTCPayServer.Tests/UnitTests/LndTest.cs +++ b/BTCPayServer.Tests/UnitTests/LndTest.cs @@ -2,8 +2,10 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using BTCPayServer.Payments.Lightning; using BTCPayServer.Payments.Lightning.Lnd; using NBitcoin; +using NBitcoin.RPC; using Xunit; using Xunit.Abstractions; @@ -16,31 +18,96 @@ namespace BTCPayServer.Tests.UnitTests public LndTest(ITestOutputHelper output) { this.output = output; + initializeEnvironment(); + + LndRpc = LndSwaggerClientCustomHttp.Create(new Uri("http://localhost:53280"), Network.RegTest); + InvoiceClient = new LndClient(LndRpc); } - private LndClient Client - { - get - { - var lnd = new LndClient(new Uri("http://localhost:53280"), Network.RegTest); - return lnd; - } - } + private LndSwaggerClientCustomHttp LndRpc { get; set; } + private LndClient InvoiceClient { get; set; } [Fact] public async Task GetInfo() { - var res = await Client.GetInfo(); - + var res = await InvoiceClient.GetInfo(); output.WriteLine("Result: " + res.ToJson()); } [Fact] public async Task CreateInvoice() { - var res = await Client.CreateInvoice(10000, "Hello world", TimeSpan.FromSeconds(3600)); - + var res = await InvoiceClient.CreateInvoice(10000, "Hello world", TimeSpan.FromSeconds(3600)); output.WriteLine("Result: " + res.ToJson()); } + + [Fact] + public async Task GetInvoice() + { + var createInvoice = await InvoiceClient.CreateInvoice(10000, "Hello world", TimeSpan.FromSeconds(3600)); + var getInvoice = await InvoiceClient.GetInvoice(createInvoice.Id); + + Assert.Equal(createInvoice.BOLT11, getInvoice.BOLT11); + } + + + + [Fact] + public async Task SetupWalletForPayment() + { + var nodeInfo = GetInfo(); + var addressResponse = await LndRpc.NewWitnessAddressAsync(); + var address = BitcoinAddress.Create(addressResponse.Address, Network.RegTest); + await ExplorerNode.SendToAddressAsync(address, Money.Coins(0.2m)); + ExplorerNode.Generate(1); + await WaitLNSynched(); + await Task.Delay(1000); + + // We need two instances of lnd... one for merchant, one for buyer + // prepare that in next commit + //var channelReq = new LnrpcOpenChannelRequest + //{ + // Local_funding_amount = 16777215.ToString() + //}; + //var channelResp = await LndRpc.OpenChannelSyncAsync(channelReq); + + output.WriteLine("Wallet Address: " + address); + } + + private async Task WaitLNSynched() + { + while (true) + { + var merchantInfo = await InvoiceClient.GetInfo(); + var blockCount = await ExplorerNode.GetBlockCountAsync(); + if (merchantInfo.BlockHeight != blockCount) + { + await Task.Delay(1000); + } + else + { + return merchantInfo; + } + } + } + + + + + // + private void initializeEnvironment() + { + NetworkProvider = new BTCPayNetworkProvider(NetworkType.Regtest); + ExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_BTCRPCCONNECTION", "server=http://127.0.0.1:43782;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork("BTC").NBitcoinNetwork); + } + + public BTCPayNetworkProvider NetworkProvider { get; private set; } + public RPCClient ExplorerNode { get; set; } + + internal string GetEnvironment(string variable, string defaultValue) + { + var var = Environment.GetEnvironmentVariable(variable); + return String.IsNullOrEmpty(var) ? defaultValue : var; + } } } diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs index 0358a4007..0b9e6207d 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs @@ -17,18 +17,13 @@ namespace BTCPayServer.Payments.Lightning.Lnd { public class LndClient : ILightningInvoiceClient, ILightningListenInvoiceSession { - public LndClient(Uri uri, Network network, byte[] tlsCertificate = null, byte[] grpcMacaroon = null) + public LndSwaggerClient _Decorator; + + public LndClient(LndSwaggerClient decorator) { - // for now working with custom build of lnd that has no macaroons and is on http - //_HttpClient = HttpClientFactoryForLnd.Generate(tlsCertificate, grpcMacaroon); - - _HttpClient = new HttpClient(); - _Decorator = new LndSwaggerClient(uri.ToString().TrimEnd('/'), _HttpClient); + _Decorator = decorator; } - private HttpClient _HttpClient; - private LndSwaggerClient _Decorator; - public async Task CreateInvoice(LightMoney amount, string description, TimeSpan expiry, CancellationToken cancellation = default(CancellationToken)) { @@ -84,11 +79,8 @@ namespace BTCPayServer.Payments.Lightning.Lnd } - public void Dispose() - { - _HttpClient?.Dispose(); - } + // utility static methods... maybe move to separate class private static string BitString(byte[] bytes) { return BitConverter.ToString(bytes) @@ -123,6 +115,11 @@ namespace BTCPayServer.Payments.Lightning.Lnd return invoice; } + public void Dispose() + { + throw new NotImplementedException(); + } + // Invariant culture conversion public static class ConvertInv { @@ -143,53 +140,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd } } - internal class HttpClientFactoryForLnd - { - internal static HttpClient Generate(byte[] tlsCertificate, byte[] grpcMacaroon) - { - var httpClient = new HttpClient(GetCertificate(tlsCertificate)); - var macaroonHex = BitConverter.ToString(grpcMacaroon).Replace("-", "", StringComparison.InvariantCulture); - httpClient.DefaultRequestHeaders.Add("Grpc-Metadata-macaroon", macaroonHex); - - return httpClient; - } - - private static HttpClientHandler GetCertificate(byte[] certFile) - { - X509Certificate2 clientCertificate = null; - if (certFile != null) - clientCertificate = new X509Certificate2(certFile); - - var handler = new HttpClientHandler - { - SslProtocols = SslProtocols.Tls12 - }; - - handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => - { - const SslPolicyErrors unforgivableErrors = - SslPolicyErrors.RemoteCertificateNotAvailable | - SslPolicyErrors.RemoteCertificateNameMismatch; - - if ((errors & unforgivableErrors) != 0) - { - return false; - } - - if (clientCertificate == null) - return true; - - X509Certificate2 remoteRoot = chain.ChainElements[chain.ChainElements.Count - 1].Certificate; - var res = clientCertificate.RawData.SequenceEqual(remoteRoot.RawData); - - return res; - }; - - return handler; - } - } - - partial class LndSwaggerClient + public partial class LndSwaggerClient { } } diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs new file mode 100644 index 000000000..ed5cee152 --- /dev/null +++ b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Security; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; +using NBitcoin; + +namespace BTCPayServer.Payments.Lightning.Lnd +{ + public class LndSwaggerClientCustomHttp : LndSwaggerClient, IDisposable + { + public LndSwaggerClientCustomHttp(string baseUrl, HttpClient httpClient) + : base(baseUrl, httpClient) + { + _HttpClient = httpClient; + } + + private HttpClient _HttpClient; + + public void Dispose() + { + _HttpClient.Dispose(); + } + + // + public static LndSwaggerClientCustomHttp Create(Uri uri, Network network, byte[] tlsCertificate = null, byte[] grpcMacaroon = null) + { + // for now working with custom build of lnd that has no macaroons and is on http + //_HttpClient = HttpClientFactoryForLnd.Generate(tlsCertificate, grpcMacaroon); + var httpClient = new HttpClient(); + return new LndSwaggerClientCustomHttp(uri.ToString().TrimEnd('/'), httpClient); + } + } + + internal class HttpClientFactoryForLnd + { + internal static HttpClient Generate(byte[] tlsCertificate, byte[] grpcMacaroon) + { + var httpClient = new HttpClient(GetCertificate(tlsCertificate)); + var macaroonHex = BitConverter.ToString(grpcMacaroon).Replace("-", "", StringComparison.InvariantCulture); + httpClient.DefaultRequestHeaders.Add("Grpc-Metadata-macaroon", macaroonHex); + + return httpClient; + } + + private static HttpClientHandler GetCertificate(byte[] certFile) + { + X509Certificate2 clientCertificate = null; + if (certFile != null) + clientCertificate = new X509Certificate2(certFile); + + var handler = new HttpClientHandler + { + SslProtocols = SslProtocols.Tls12 + }; + + handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => + { + const SslPolicyErrors unforgivableErrors = + SslPolicyErrors.RemoteCertificateNotAvailable | + SslPolicyErrors.RemoteCertificateNameMismatch; + + if ((errors & unforgivableErrors) != 0) + { + return false; + } + + if (clientCertificate == null) + return true; + + X509Certificate2 remoteRoot = chain.ChainElements[chain.ChainElements.Count - 1].Certificate; + var res = clientCertificate.RawData.SequenceEqual(remoteRoot.RawData); + + return res; + }; + + return handler; + } + } +} From f8540dc78c1fc0f13dd7f83d69aeffe7a8312859 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 11 May 2018 16:59:24 -0500 Subject: [PATCH 12/45] Providing merchant_lnd and customer_lnd for testing --- BTCPayServer.Tests/UnitTests/LndTest.cs | 24 ++++++++-- BTCPayServer.Tests/docker-compose.yml | 48 +++++++++++++++++-- .../Payments/Lightning/Lnd/LndClient.cs | 14 ++++-- 3 files changed, 72 insertions(+), 14 deletions(-) diff --git a/BTCPayServer.Tests/UnitTests/LndTest.cs b/BTCPayServer.Tests/UnitTests/LndTest.cs index cae4f3216..a6dd231e3 100644 --- a/BTCPayServer.Tests/UnitTests/LndTest.cs +++ b/BTCPayServer.Tests/UnitTests/LndTest.cs @@ -11,6 +11,7 @@ using Xunit.Abstractions; namespace BTCPayServer.Tests.UnitTests { + // this depends for now on `docker-compose up devlnd` public class LndTest { private readonly ITestOutputHelper output; @@ -20,13 +21,17 @@ namespace BTCPayServer.Tests.UnitTests this.output = output; initializeEnvironment(); - LndRpc = LndSwaggerClientCustomHttp.Create(new Uri("http://localhost:53280"), Network.RegTest); - InvoiceClient = new LndClient(LndRpc); + MerchantLnd = LndSwaggerClientCustomHttp.Create(new Uri("http://127.0.0.1:53280"), Network.RegTest); + InvoiceClient = new LndClient(MerchantLnd); + + CustomerLnd = LndSwaggerClientCustomHttp.Create(new Uri("http://127.0.0.1:53281"), Network.RegTest); } - private LndSwaggerClientCustomHttp LndRpc { get; set; } + private LndSwaggerClientCustomHttp MerchantLnd { get; set; } private LndClient InvoiceClient { get; set; } + private LndSwaggerClientCustomHttp CustomerLnd { get; set; } + [Fact] public async Task GetInfo() { @@ -55,14 +60,23 @@ namespace BTCPayServer.Tests.UnitTests [Fact] public async Task SetupWalletForPayment() { - var nodeInfo = GetInfo(); - var addressResponse = await LndRpc.NewWitnessAddressAsync(); + var merchantNodeInfo = await InvoiceClient.GetInfo(); + var addressResponse = await CustomerLnd.NewWitnessAddressAsync(); var address = BitcoinAddress.Create(addressResponse.Address, Network.RegTest); await ExplorerNode.SendToAddressAsync(address, Money.Coins(0.2m)); ExplorerNode.Generate(1); await WaitLNSynched(); await Task.Delay(1000); + var connectResp = await CustomerLnd.ConnectPeerAsync(new LnrpcConnectPeerRequest + { + Addr = new LnrpcLightningAddress + { + Pubkey = merchantNodeInfo.NodeId, + Host = "merchant_lnd:8080" + } + }); + // We need two instances of lnd... one for merchant, one for buyer // prepare that in next commit //var channelReq = new LnrpcOpenChannelRequest diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index ecdce19fe..3971748b4 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -44,7 +44,22 @@ services: - customer_lightningd - merchant_lightningd - lightning-charged - - lnd + - customer_lnd + - merchant_lnd + + devlnd: + image: nicolasdorier/docker-bitcoin:0.16.0 + environment: + BITCOIN_EXTRA_ARGS: | + regtest=1 + connect=bitcoind:39388 + links: + - nbxplorer + - postgres + - customer_lnd + - merchant_lnd + + nbxplorer: image: nicolasdorier/nbxplorer:1.0.2.2 @@ -180,7 +195,7 @@ services: expose: - "5432" - lnd: + merchant_lnd: image: btcpayserver/lnd:0.4.1.0 environment: RPCHOST: bitcoind:43782 @@ -193,8 +208,32 @@ services: DEBUG: debug ports: - "53280:8080" + expose: + - "8080" + - "10009" volumes: - - "lnd_datadir:/root/.lnd" + - "merchant_lnd_datadir:/root/.lnd" + links: + - bitcoind + + customer_lnd: + image: btcpayserver/lnd:0.4.1.0 + environment: + RPCHOST: bitcoind:43782 + RPCUSER: ceiwHEbqWI83 + RPCPASS: DwubwWsoo3 + ZMQPATH: tcp://bitcoind:28332 + NETWORK: regtest + CHAIN: bitcoin + BACKEND: bitcoind + DEBUG: debug + ports: + - "53281:8080" + expose: + - "8080" + - "10009" + volumes: + - "customer_lnd_datadir:/root/.lnd" links: - bitcoind @@ -203,4 +242,5 @@ volumes: customer_lightningd_datadir: merchant_lightningd_datadir: lightning_charge_datadir: - lnd_datadir: + customer_lnd_datadir: + merchant_lnd_datadir: diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs index 0b9e6207d..bc141a572 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs @@ -51,14 +51,18 @@ namespace BTCPayServer.Payments.Lightning.Lnd { var resp = await _Decorator.GetInfoAsync(cancellation); - var invoice = new LightningNodeInformation + var nodeInfo = new LightningNodeInformation { - Address = resp.Uris?.FirstOrDefault(), BlockHeight = (int?)resp.Block_height ?? 0, - NodeId = resp.Alias, - P2PPort = 0 + NodeId = resp.Identity_pubkey }; - return invoice; + + // Lnd doesn't return this data as Clightning so we add it manually from data we have + var uri = new Uri(_Decorator.BaseUrl); + nodeInfo.Address = uri.Host; + nodeInfo.P2PPort = uri.Port; + + return nodeInfo; } public async Task GetInvoice(string invoiceId, CancellationToken cancellation = default(CancellationToken)) From cabd7c4e64626d7a064fcc92c53291909eff21ed Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sat, 12 May 2018 00:19:26 -0500 Subject: [PATCH 13/45] Lnd requires zmqpubrawblock setting, and port 9735 for peer connections --- BTCPayServer.Tests/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 3971748b4..00f5b94e2 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -97,6 +97,7 @@ services: port=39388 whitelist=0.0.0.0/0 zmqpubrawtx=tcp://0.0.0.0:28332 + zmqpubrawblock=tcp://0.0.0.0:28332 zmqpubrawtxlock=tcp://0.0.0.0:28332 zmqpubhashblock=tcp://0.0.0.0:28332 ports: @@ -209,8 +210,7 @@ services: ports: - "53280:8080" expose: - - "8080" - - "10009" + - "9735" volumes: - "merchant_lnd_datadir:/root/.lnd" links: From 8fc1b0c856872959ab580c9f2333cf4414a2a9ba Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sat, 12 May 2018 00:23:10 -0500 Subject: [PATCH 14/45] Ensuring lightning channel is open for testing --- BTCPayServer.Tests/UnitTests/LndTest.cs | 81 ++++++++++++++++++------- 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/BTCPayServer.Tests/UnitTests/LndTest.cs b/BTCPayServer.Tests/UnitTests/LndTest.cs index a6dd231e3..49e6c8255 100644 --- a/BTCPayServer.Tests/UnitTests/LndTest.cs +++ b/BTCPayServer.Tests/UnitTests/LndTest.cs @@ -8,6 +8,7 @@ using NBitcoin; using NBitcoin.RPC; using Xunit; using Xunit.Abstractions; +using System.Linq; namespace BTCPayServer.Tests.UnitTests { @@ -60,32 +61,70 @@ namespace BTCPayServer.Tests.UnitTests [Fact] public async Task SetupWalletForPayment() { - var merchantNodeInfo = await InvoiceClient.GetInfo(); - var addressResponse = await CustomerLnd.NewWitnessAddressAsync(); - var address = BitcoinAddress.Create(addressResponse.Address, Network.RegTest); - await ExplorerNode.SendToAddressAsync(address, Money.Coins(0.2m)); - ExplorerNode.Generate(1); - await WaitLNSynched(); - await Task.Delay(1000); + await EnsureLightningChannelAsync(); + } - var connectResp = await CustomerLnd.ConnectPeerAsync(new LnrpcConnectPeerRequest + + public async Task EnsureLightningChannelAsync() + { + var merchantInfo = await WaitLNSynched(); + var merchantAddress = new LnrpcLightningAddress { - Addr = new LnrpcLightningAddress + Pubkey = merchantInfo.NodeId, + Host = "merchant_lnd:9735" + }; + + while (true) + { + // if channel is pending generate blocks until confirmed + var pendingResponse = await CustomerLnd.PendingChannelsAsync(); + if (pendingResponse.Pending_open_channels? + .Any(a => a.Channel?.Remote_node_pub == merchantAddress.Pubkey) == true) { - Pubkey = merchantNodeInfo.NodeId, - Host = "merchant_lnd:8080" + ExplorerNode.Generate(1); + await WaitLNSynched(); + continue; } - }); - // We need two instances of lnd... one for merchant, one for buyer - // prepare that in next commit - //var channelReq = new LnrpcOpenChannelRequest - //{ - // Local_funding_amount = 16777215.ToString() - //}; - //var channelResp = await LndRpc.OpenChannelSyncAsync(channelReq); + // check if channel is established + var chanResponse = await CustomerLnd.ListChannelsAsync(null, null, null, null); + var channelToMerchant = chanResponse?.Channels + .Where(a => a.Remote_pubkey == merchantAddress.Pubkey) + .FirstOrDefault(); - output.WriteLine("Wallet Address: " + address); + if (channelToMerchant == null) + { + // create new channel + var isConnected = await CustomerLnd.ListPeersAsync(); + if (!isConnected.Peers.Any(a => a.Pub_key == merchantInfo.NodeId)) + { + var connectResp = await CustomerLnd.ConnectPeerAsync(new LnrpcConnectPeerRequest + { + Addr = merchantAddress + }); + } + + var addressResponse = await CustomerLnd.NewWitnessAddressAsync(); + var address = BitcoinAddress.Create(addressResponse.Address, Network.RegTest); + await ExplorerNode.SendToAddressAsync(address, Money.Coins(0.2m)); + ExplorerNode.Generate(1); + await WaitLNSynched(); + + var channelReq = new LnrpcOpenChannelRequest + { + Local_funding_amount = 16777215.ToString(), + Node_pubkey_string = merchantInfo.NodeId + }; + var channelResp = await CustomerLnd.OpenChannelSyncAsync(channelReq); + } + else + { + // channel exists, return it + ExplorerNode.Generate(1); + await WaitLNSynched(); + return channelToMerchant; + } + } } private async Task WaitLNSynched() @@ -96,7 +135,7 @@ namespace BTCPayServer.Tests.UnitTests var blockCount = await ExplorerNode.GetBlockCountAsync(); if (merchantInfo.BlockHeight != blockCount) { - await Task.Delay(1000); + await Task.Delay(500); } else { From f97173e9e7df17a37cd73f9a41cf55fbc4701689 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sat, 12 May 2018 00:43:13 -0500 Subject: [PATCH 15/45] Testing invoice payment with Lnd --- BTCPayServer.Tests/UnitTests/LndTest.cs | 13 ++++++++++++- BTCPayServer/Payments/Lightning/Lnd/LndClient.cs | 11 ++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/BTCPayServer.Tests/UnitTests/LndTest.cs b/BTCPayServer.Tests/UnitTests/LndTest.cs index 49e6c8255..418b73f48 100644 --- a/BTCPayServer.Tests/UnitTests/LndTest.cs +++ b/BTCPayServer.Tests/UnitTests/LndTest.cs @@ -9,6 +9,7 @@ using NBitcoin.RPC; using Xunit; using Xunit.Abstractions; using System.Linq; +using System.Threading; namespace BTCPayServer.Tests.UnitTests { @@ -59,9 +60,19 @@ namespace BTCPayServer.Tests.UnitTests [Fact] - public async Task SetupWalletForPayment() + public async Task CreateLndInvoiceAndPay() { + var merchantInvoice = await InvoiceClient.CreateInvoice(10000, "Hello world", TimeSpan.FromSeconds(3600)); + await EnsureLightningChannelAsync(); + var payResponse = await CustomerLnd.SendPaymentSyncAsync(new LnrpcSendRequest + { + Payment_request = merchantInvoice.BOLT11 + }); + + var invoice = await InvoiceClient.GetInvoice(merchantInvoice.Id); + + Assert.True(invoice.PaidAt.HasValue); } diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs index bc141a572..a97d4b51c 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs @@ -57,10 +57,10 @@ namespace BTCPayServer.Payments.Lightning.Lnd NodeId = resp.Identity_pubkey }; - // Lnd doesn't return this data as Clightning so we add it manually from data we have - var uri = new Uri(_Decorator.BaseUrl); - nodeInfo.Address = uri.Host; - nodeInfo.P2PPort = uri.Port; + // Lnd doesn't return this data as Clightning, find alternative ways to supply + // it always should be merchant_lnd:9735 because of docker + nodeInfo.Address = null; + nodeInfo.P2PPort = 9735; return nodeInfo; } @@ -71,6 +71,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd return ConvertLndInvoice(resp); } + // TODO: These two methods where you wait on invoice are still work in progress public Task Listen(CancellationToken cancellation = default(CancellationToken)) { return Task.FromResult(this); @@ -80,8 +81,8 @@ namespace BTCPayServer.Payments.Lightning.Lnd { var resp = await _Decorator.SubscribeInvoicesAsync(cancellation); return ConvertLndInvoice(resp); - } + // Eof work in progress // utility static methods... maybe move to separate class From 7c29cb62efd59010dc7911ac6402ad1d2e625a88 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Mon, 14 May 2018 15:05:03 -0500 Subject: [PATCH 16/45] Enabling dual support - clients with or without macaroons/tls --- .../Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs index ed5cee152..7f9c92eb5 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs @@ -28,9 +28,12 @@ namespace BTCPayServer.Payments.Lightning.Lnd // public static LndSwaggerClientCustomHttp Create(Uri uri, Network network, byte[] tlsCertificate = null, byte[] grpcMacaroon = null) { - // for now working with custom build of lnd that has no macaroons and is on http - //_HttpClient = HttpClientFactoryForLnd.Generate(tlsCertificate, grpcMacaroon); - var httpClient = new HttpClient(); + // for development we are working with custom build of lnd that allows no macaroons and http + var clientWithNoMacaroonsTls = tlsCertificate == null || grpcMacaroon == null; + + var httpClient = clientWithNoMacaroonsTls ? new HttpClient() : + HttpClientFactoryForLnd.Generate(tlsCertificate, grpcMacaroon); + return new LndSwaggerClientCustomHttp(uri.ToString().TrimEnd('/'), httpClient); } } From 789b9168add80e2bdd3c7dcdffafaf878e0b3ab3 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Mon, 14 May 2018 15:54:44 -0500 Subject: [PATCH 17/45] Adding Lnd to connection types and supporting parsing --- BTCPayServer.Tests/UnitTest1.cs | 7 ++ BTCPayServer.Tests/UnitTests/LndTest.cs | 8 +- .../Lightning/LightningConnectionString.cs | 81 ++++++++++--------- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 64afa1d28..b61f07339 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -328,6 +328,13 @@ namespace BTCPayServer.Tests public void CanParseLightningURL() { LightningConnectionString conn = null; + + Assert.True(LightningConnectionString.TryParse("http://127.0.0.1:53280?type=lnd", out conn)); + Assert.Equal("http://127.0.0.1:53280/", conn.ToString()); + Assert.Equal("http://127.0.0.1:53280/", conn.ToUri(true).AbsoluteUri); + Assert.Equal("http://127.0.0.1:53280/", conn.ToUri(false).AbsoluteUri); + Assert.Equal(LightningConnectionType.Lnd, conn.ConnectionType); + Assert.True(LightningConnectionString.TryParse("/test/a", out conn)); Assert.Equal("unix://test/a", conn.ToString()); Assert.Equal("unix://test/a", conn.ToUri(true).AbsoluteUri); diff --git a/BTCPayServer.Tests/UnitTests/LndTest.cs b/BTCPayServer.Tests/UnitTests/LndTest.cs index 418b73f48..4f4d0310a 100644 --- a/BTCPayServer.Tests/UnitTests/LndTest.cs +++ b/BTCPayServer.Tests/UnitTests/LndTest.cs @@ -79,7 +79,7 @@ namespace BTCPayServer.Tests.UnitTests public async Task EnsureLightningChannelAsync() { var merchantInfo = await WaitLNSynched(); - var merchantAddress = new LnrpcLightningAddress + var merchantNodeAddress = new LnrpcLightningAddress { Pubkey = merchantInfo.NodeId, Host = "merchant_lnd:9735" @@ -90,7 +90,7 @@ namespace BTCPayServer.Tests.UnitTests // if channel is pending generate blocks until confirmed var pendingResponse = await CustomerLnd.PendingChannelsAsync(); if (pendingResponse.Pending_open_channels? - .Any(a => a.Channel?.Remote_node_pub == merchantAddress.Pubkey) == true) + .Any(a => a.Channel?.Remote_node_pub == merchantNodeAddress.Pubkey) == true) { ExplorerNode.Generate(1); await WaitLNSynched(); @@ -100,7 +100,7 @@ namespace BTCPayServer.Tests.UnitTests // check if channel is established var chanResponse = await CustomerLnd.ListChannelsAsync(null, null, null, null); var channelToMerchant = chanResponse?.Channels - .Where(a => a.Remote_pubkey == merchantAddress.Pubkey) + .Where(a => a.Remote_pubkey == merchantNodeAddress.Pubkey) .FirstOrDefault(); if (channelToMerchant == null) @@ -111,7 +111,7 @@ namespace BTCPayServer.Tests.UnitTests { var connectResp = await CustomerLnd.ConnectPeerAsync(new LnrpcConnectPeerRequest { - Addr = merchantAddress + Addr = merchantNodeAddress }); } diff --git a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs index fe7fc8a6a..be9f952e2 100644 --- a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs +++ b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs @@ -8,21 +8,48 @@ namespace BTCPayServer.Payments.Lightning public enum LightningConnectionType { Charge, - CLightning + CLightning, + Lnd } public class LightningConnectionString { + public LightningConnectionString() { } + + public string Username { get; set; } + public string Password { get; set; } + public Uri BaseUri { get; set; } + + public LightningConnectionType ConnectionType { get; private set; } + + public Uri ToUri(bool withCredentials) + { + if (withCredentials) + { + return new UriBuilder(BaseUri) { UserName = Username ?? "", Password = Password ?? "" }.Uri; + } + else + { + return BaseUri; + } + } + + public override string ToString() + { + return ToUri(true).AbsoluteUri; + } + + // public static bool TryParse(string str, out LightningConnectionString connectionString) { return TryParse(str, out connectionString, out var error); } + public static bool TryParse(string str, out LightningConnectionString connectionString, out string error) { if (str == null) throw new ArgumentNullException(nameof(str)); if (str.StartsWith('/')) str = "unix:" + str; - var result = new LightningConnectionString(); connectionString = null; error = null; @@ -51,7 +78,16 @@ namespace BTCPayServer.Payments.Lightning uri = new Uri("unix://" + str, UriKind.Absolute); } - if (uri.Scheme == "http" || uri.Scheme == "https") + var result = new LightningConnectionString(); + + result.ConnectionType = uri.Scheme == "http" || uri.Scheme == "https" ? + LightningConnectionType.Charge : + LightningConnectionType.CLightning; + + if (uri.Query.Contains("type=lnd")) + result.ConnectionType = LightningConnectionType.Lnd; + + if (result.ConnectionType == LightningConnectionType.Charge) { var parts = uri.UserInfo.Split(':'); if (string.IsNullOrEmpty(uri.UserInfo) || parts.Length != 2) @@ -67,44 +103,11 @@ namespace BTCPayServer.Payments.Lightning error = "The url should not have user information"; return false; } - result.BaseUri = new UriBuilder(uri) { UserName = "", Password = "" }.Uri; + + var uriWithoutQuery = uri.AbsoluteUri.Split('?')[0]; + result.BaseUri = new UriBuilder(uriWithoutQuery) { UserName = "", Password = "" }.Uri; connectionString = result; return true; } - - public LightningConnectionString() - { - - } - - public string Username { get; set; } - public string Password { get; set; } - public Uri BaseUri { get; set; } - - public LightningConnectionType ConnectionType - { - get - { - return BaseUri.Scheme == "http" || BaseUri.Scheme == "https" ? LightningConnectionType.Charge - : LightningConnectionType.CLightning; - } - } - - public Uri ToUri(bool withCredentials) - { - if (withCredentials) - { - return new UriBuilder(BaseUri) { UserName = Username ?? "", Password = Password ?? "" }.Uri; - } - else - { - return BaseUri; - } - } - - public override string ToString() - { - return ToUri(true).AbsoluteUri; - } } } From a0243fa5694dd4d508f2e039ae6ac746a75c89fe Mon Sep 17 00:00:00 2001 From: rockstardev Date: Mon, 14 May 2018 22:18:08 -0500 Subject: [PATCH 18/45] Lnd support for passing macaroon and tls as hex --- BTCPayServer.Tests/UnitTest1.cs | 9 +++++- BTCPayServer.Tests/UnitTests/LndTest.cs | 4 +-- .../Lightning/LightningClientFactory.cs | 28 +++++++++++++++---- .../Lightning/LightningConnectionString.cs | 19 +++++++++++-- .../Payments/Lightning/Lnd/LndClient.cs | 16 +++++------ 5 files changed, 56 insertions(+), 20 deletions(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index b61f07339..da5747d80 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -328,12 +328,19 @@ namespace BTCPayServer.Tests public void CanParseLightningURL() { LightningConnectionString conn = null; + + var macaroon = "0201036c6e640247030a10b0dbbde28f009f83d330bde05075ca251201301a160a0761646472657373120472656164120577726974651a170a08696e766f6963657312047265616412057772697465000006200ae088692e67cf14e767c3d2a4a67ce489150bf810654ff980e1b7a7e263d5e8"; + var tls = "2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494942396a4343415a7967417749424167495156397a62474252724e54716b4e4b55676d72524d377a414b42676771686b6a4f50515144416a41784d5238770a485159445651514b45785a73626d5167595856306232646c626d56795958526c5a43426a5a584a304d51347744415944565151444577564754304e56557a41650a467730784f4441304d6a55794d7a517a4d6a4261467730784f5441324d6a41794d7a517a4d6a42614d444578487a416442674e5642416f54466d78755a4342680a645852765a3256755a584a686447566b49474e6c636e5178446a414d42674e5642414d5442555a50513156544d466b77457759484b6f5a497a6a3043415159490a4b6f5a497a6a304441516344516741454b7557424568564f75707965434157476130766e713262712f59396b41755a78616865646d454553482b753936436d450a397577486b4b2b4a7667547a66385141783550513741357254637155374b57595170303175364f426c5443426b6a414f42674e56485138424166384542414d430a4171517744775944565230544151482f42415577417745422f7a427642674e56485245456144426d6767564754304e565534494a6247396a5957786f62334e300a6877522f4141414268784141414141414141414141414141414141414141414268775373474f69786877514b41457342687753702f717473687754417141724c0a687753702f6d4a72687753702f754f77687753702f714e59687753702f6874436877514b70514157687753702f6c42514d416f4743437147534d343942414d430a413067414d45554349464866716d595a5043647a4a5178386b47586859473834394c31766541364c784d6f7a4f5774356d726835416945413662756e51556c710a6558553070474168776c3041654d726a4d4974394c7652736179756162565a593278343d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a"; - Assert.True(LightningConnectionString.TryParse("http://127.0.0.1:53280?type=lnd", out conn)); + var lndUri = $"http://127.0.0.1:53280?type=lnd&macaroon={macaroon}&tls={tls}"; + + Assert.True(LightningConnectionString.TryParse(lndUri, out conn)); Assert.Equal("http://127.0.0.1:53280/", conn.ToString()); Assert.Equal("http://127.0.0.1:53280/", conn.ToUri(true).AbsoluteUri); Assert.Equal("http://127.0.0.1:53280/", conn.ToUri(false).AbsoluteUri); Assert.Equal(LightningConnectionType.Lnd, conn.ConnectionType); + Assert.Equal(macaroon, conn.Macaroon); + Assert.Equal(tls, conn.Tls); Assert.True(LightningConnectionString.TryParse("/test/a", out conn)); Assert.Equal("unix://test/a", conn.ToString()); diff --git a/BTCPayServer.Tests/UnitTests/LndTest.cs b/BTCPayServer.Tests/UnitTests/LndTest.cs index 4f4d0310a..80efe432c 100644 --- a/BTCPayServer.Tests/UnitTests/LndTest.cs +++ b/BTCPayServer.Tests/UnitTests/LndTest.cs @@ -24,13 +24,13 @@ namespace BTCPayServer.Tests.UnitTests initializeEnvironment(); MerchantLnd = LndSwaggerClientCustomHttp.Create(new Uri("http://127.0.0.1:53280"), Network.RegTest); - InvoiceClient = new LndClient(MerchantLnd); + InvoiceClient = new LndInvoiceClient(MerchantLnd); CustomerLnd = LndSwaggerClientCustomHttp.Create(new Uri("http://127.0.0.1:53281"), Network.RegTest); } private LndSwaggerClientCustomHttp MerchantLnd { get; set; } - private LndClient InvoiceClient { get; set; } + private LndInvoiceClient InvoiceClient { get; set; } private LndSwaggerClientCustomHttp CustomerLnd { get; set; } diff --git a/BTCPayServer/Payments/Lightning/LightningClientFactory.cs b/BTCPayServer/Payments/Lightning/LightningClientFactory.cs index 7cb26db7e..db8d8fa2b 100644 --- a/BTCPayServer/Payments/Lightning/LightningClientFactory.cs +++ b/BTCPayServer/Payments/Lightning/LightningClientFactory.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using BTCPayServer.Payments.Lightning.Charge; using BTCPayServer.Payments.Lightning.CLightning; +using BTCPayServer.Payments.Lightning.Lnd; namespace BTCPayServer.Payments.Lightning { @@ -11,17 +12,32 @@ namespace BTCPayServer.Payments.Lightning { public ILightningInvoiceClient CreateClient(LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network) { - var uri = supportedPaymentMethod.GetLightningUrl(); - if (uri.ConnectionType == LightningConnectionType.Charge) + var connString = supportedPaymentMethod.GetLightningUrl(); + if (connString.ConnectionType == LightningConnectionType.Charge) { - return new ChargeClient(uri.ToUri(true), network.NBitcoinNetwork); + return new ChargeClient(connString.ToUri(true), network.NBitcoinNetwork); } - else if (uri.ConnectionType == LightningConnectionType.CLightning) + else if (connString.ConnectionType == LightningConnectionType.CLightning) { - return new CLightningRPCClient(uri.ToUri(false), network.NBitcoinNetwork); + return new CLightningRPCClient(connString.ToUri(false), network.NBitcoinNetwork); + } + else if (connString.ConnectionType == LightningConnectionType.Lnd) + { + var hex = new NBitcoin.DataEncoders.HexEncoder(); + + byte[] macaroon = null; + if (!String.IsNullOrEmpty(connString.Macaroon)) + macaroon = hex.DecodeData(connString.Macaroon); + + byte[] tls = null; + if (!String.IsNullOrEmpty(connString.Tls)) + tls = hex.DecodeData(connString.Tls); + + var swagger = LndSwaggerClientCustomHttp.Create(connString.ToUri(false), network.NBitcoinNetwork, tls, macaroon); + return new LndInvoiceClient(swagger); } else - throw new NotSupportedException($"Unsupported connection string for lightning server ({uri.ConnectionType})"); + throw new NotSupportedException($"Unsupported connection string for lightning server ({connString.ConnectionType})"); } } } diff --git a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs index be9f952e2..556510390 100644 --- a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs +++ b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs @@ -2,6 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.WebUtilities; +using Microsoft.Extensions.Primitives; namespace BTCPayServer.Payments.Lightning { @@ -21,6 +24,11 @@ namespace BTCPayServer.Payments.Lightning public LightningConnectionType ConnectionType { get; private set; } + // Extract this to LndConnectionString class + public string Tls { get; set; } + public string Macaroon { get; set; } + // + public Uri ToUri(bool withCredentials) { if (withCredentials) @@ -46,15 +54,13 @@ namespace BTCPayServer.Payments.Lightning public static bool TryParse(string str, out LightningConnectionString connectionString, out string error) { - if (str == null) - throw new ArgumentNullException(nameof(str)); if (str.StartsWith('/')) str = "unix:" + str; connectionString = null; error = null; Uri uri; - if (!System.Uri.TryCreate(str, UriKind.Absolute, out uri)) + if (!Uri.TryCreate(str, UriKind.Absolute, out uri)) { error = "Invalid URL"; return false; @@ -104,6 +110,13 @@ namespace BTCPayServer.Payments.Lightning return false; } + if (result.ConnectionType == LightningConnectionType.Lnd) + { + var queryString = QueryHelpers.ParseNullableQuery(uri.Query); + result.Macaroon = queryString.ContainsKey("macaroon") ? queryString["macaroon"] : StringValues.Empty; + result.Tls = queryString.ContainsKey("tls") ? queryString["tls"] : StringValues.Empty; + } + var uriWithoutQuery = uri.AbsoluteUri.Split('?')[0]; result.BaseUri = new UriBuilder(uriWithoutQuery) { UserName = "", Password = "" }.Uri; connectionString = result; diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs index a97d4b51c..9fc2be03a 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs @@ -15,13 +15,13 @@ using NBitcoin; namespace BTCPayServer.Payments.Lightning.Lnd { - public class LndClient : ILightningInvoiceClient, ILightningListenInvoiceSession + public class LndInvoiceClient : ILightningInvoiceClient, ILightningListenInvoiceSession { - public LndSwaggerClient _Decorator; + public LndSwaggerClient _rpcClient; - public LndClient(LndSwaggerClient decorator) + public LndInvoiceClient(LndSwaggerClient rpcClient) { - _Decorator = decorator; + _rpcClient = rpcClient; } public async Task CreateInvoice(LightMoney amount, string description, TimeSpan expiry, @@ -30,7 +30,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd var strAmount = ConvertInv.ToString(amount.ToUnit(LightMoneyUnit.Satoshi)); var strExpiry = ConvertInv.ToString(expiry.TotalSeconds); // lnd requires numbers sent as strings. don't ask - var resp = await _Decorator.AddInvoiceAsync(new LnrpcInvoice + var resp = await _rpcClient.AddInvoiceAsync(new LnrpcInvoice { Value = strAmount, Memo = description, @@ -49,7 +49,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd public async Task GetInfo(CancellationToken cancellation = default(CancellationToken)) { - var resp = await _Decorator.GetInfoAsync(cancellation); + var resp = await _rpcClient.GetInfoAsync(cancellation); var nodeInfo = new LightningNodeInformation { @@ -67,7 +67,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd public async Task GetInvoice(string invoiceId, CancellationToken cancellation = default(CancellationToken)) { - var resp = await _Decorator.LookupInvoiceAsync(invoiceId, null, cancellation); + var resp = await _rpcClient.LookupInvoiceAsync(invoiceId, null, cancellation); return ConvertLndInvoice(resp); } @@ -79,7 +79,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd async Task ILightningListenInvoiceSession.WaitInvoice(CancellationToken cancellation) { - var resp = await _Decorator.SubscribeInvoicesAsync(cancellation); + var resp = await _rpcClient.SubscribeInvoicesAsync(cancellation); return ConvertLndInvoice(resp); } // Eof work in progress From a063f107787aa269e55d4a7bf7717a24391becac Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sun, 20 May 2018 10:27:11 -0500 Subject: [PATCH 19/45] Checking for nulls during channel opening in tests --- BTCPayServer.Tests/UnitTests/LndTest.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/BTCPayServer.Tests/UnitTests/LndTest.cs b/BTCPayServer.Tests/UnitTests/LndTest.cs index 80efe432c..d0e8a8a39 100644 --- a/BTCPayServer.Tests/UnitTests/LndTest.cs +++ b/BTCPayServer.Tests/UnitTests/LndTest.cs @@ -69,7 +69,7 @@ namespace BTCPayServer.Tests.UnitTests { Payment_request = merchantInvoice.BOLT11 }); - + var invoice = await InvoiceClient.GetInvoice(merchantInvoice.Id); Assert.True(invoice.PaidAt.HasValue); @@ -99,15 +99,20 @@ namespace BTCPayServer.Tests.UnitTests // check if channel is established var chanResponse = await CustomerLnd.ListChannelsAsync(null, null, null, null); - var channelToMerchant = chanResponse?.Channels + LnrpcChannel channelToMerchant = null; + if (chanResponse != null && chanResponse.Channels != null) + { + channelToMerchant = chanResponse.Channels .Where(a => a.Remote_pubkey == merchantNodeAddress.Pubkey) .FirstOrDefault(); + } if (channelToMerchant == null) { // create new channel var isConnected = await CustomerLnd.ListPeersAsync(); - if (!isConnected.Peers.Any(a => a.Pub_key == merchantInfo.NodeId)) + if (isConnected.Peers == null || + !isConnected.Peers.Any(a => a.Pub_key == merchantInfo.NodeId)) { var connectResp = await CustomerLnd.ConnectPeerAsync(new LnrpcConnectPeerRequest { From cac58808f08376ae20c7644e70452727f2fb4f34 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sun, 20 May 2018 10:27:35 -0500 Subject: [PATCH 20/45] Renaming file to LndInvoiceClient and commenting Dispose --- .../Lightning/Lnd/{LndClient.cs => LndInvoiceClient.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename BTCPayServer/Payments/Lightning/Lnd/{LndClient.cs => LndInvoiceClient.cs} (99%) diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs similarity index 99% rename from BTCPayServer/Payments/Lightning/Lnd/LndClient.cs rename to BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs index 9fc2be03a..1142565c5 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs @@ -122,7 +122,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd public void Dispose() { - throw new NotImplementedException(); + // } // Invariant culture conversion From 093ae39e61cf7cb1f43f7eed15e8d349ef39f7db Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sun, 20 May 2018 10:27:49 -0500 Subject: [PATCH 21/45] Custom HTTPS certificates accepted for lnd connection --- .../Lightning/Lnd/LndSwaggerClientCustomHttp.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs index 7f9c92eb5..8f8187615 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs @@ -51,14 +51,20 @@ namespace BTCPayServer.Payments.Lightning.Lnd private static HttpClientHandler GetCertificate(byte[] certFile) { - X509Certificate2 clientCertificate = null; - if (certFile != null) - clientCertificate = new X509Certificate2(certFile); - var handler = new HttpClientHandler { SslProtocols = SslProtocols.Tls12 }; + if (certFile == null) + { + handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; + return handler; + } + + // if certificate is not null, try with custom accepting logic + X509Certificate2 clientCertificate = null; + if (certFile != null) + clientCertificate = new X509Certificate2(certFile); handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => { From ce81136c88c119729a826cb473838778382e1d0b Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 25 May 2018 10:44:59 -0500 Subject: [PATCH 22/45] Adding LndMockTester for passing end to end tests --- BTCPayServer.Tests/Lnd/LndMockTester.cs | 27 +++++++++++++++++++ .../LndTest.cs => Lnd/UnitTests.cs} | 8 +++--- BTCPayServer.Tests/ServerTester.cs | 4 +++ BTCPayServer.Tests/TestAccount.cs | 19 +++++++++---- BTCPayServer.Tests/docker-compose.yml | 1 + 5 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 BTCPayServer.Tests/Lnd/LndMockTester.cs rename BTCPayServer.Tests/{UnitTests/LndTest.cs => Lnd/UnitTests.cs} (97%) diff --git a/BTCPayServer.Tests/Lnd/LndMockTester.cs b/BTCPayServer.Tests/Lnd/LndMockTester.cs new file mode 100644 index 000000000..3ee701614 --- /dev/null +++ b/BTCPayServer.Tests/Lnd/LndMockTester.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; +using BTCPayServer.Payments.Lightning.Lnd; +using NBitcoin; + +namespace BTCPayServer.Tests.Lnd +{ + public class LndMockTester + { + private ServerTester _Parent; + + public LndMockTester(ServerTester serverTester, string environmentName, string defaultValue, string defaultHost, Network network) + { + this._Parent = serverTester; + var url = serverTester.GetEnvironment(environmentName, defaultValue); + + Swagger = LndSwaggerClientCustomHttp.Create(new Uri(url), network); + Client = new LndInvoiceClient(Swagger); + P2PHost = _Parent.GetEnvironment(environmentName + "_HOST", defaultHost); + } + + public LndSwaggerClientCustomHttp Swagger { get; set; } + public LndInvoiceClient Client { get; set; } + public string P2PHost { get; } + } +} diff --git a/BTCPayServer.Tests/UnitTests/LndTest.cs b/BTCPayServer.Tests/Lnd/UnitTests.cs similarity index 97% rename from BTCPayServer.Tests/UnitTests/LndTest.cs rename to BTCPayServer.Tests/Lnd/UnitTests.cs index d0e8a8a39..ecc0747c4 100644 --- a/BTCPayServer.Tests/UnitTests/LndTest.cs +++ b/BTCPayServer.Tests/Lnd/UnitTests.cs @@ -10,15 +10,16 @@ using Xunit; using Xunit.Abstractions; using System.Linq; using System.Threading; +using NBitpayClient; -namespace BTCPayServer.Tests.UnitTests +namespace BTCPayServer.Tests.Lnd { // this depends for now on `docker-compose up devlnd` - public class LndTest + public class UnitTests { private readonly ITestOutputHelper output; - public LndTest(ITestOutputHelper output) + public UnitTests(ITestOutputHelper output) { this.output = output; initializeEnvironment(); @@ -58,6 +59,7 @@ namespace BTCPayServer.Tests.UnitTests } + //integration tests [Fact] public async Task CreateLndInvoiceAndPay() diff --git a/BTCPayServer.Tests/ServerTester.cs b/BTCPayServer.Tests/ServerTester.cs index 957501fe4..b7fc5973a 100644 --- a/BTCPayServer.Tests/ServerTester.cs +++ b/BTCPayServer.Tests/ServerTester.cs @@ -20,6 +20,7 @@ using System.Threading; using System.Globalization; using BTCPayServer.Payments.Lightning.CLightning; using BTCPayServer.Payments.Lightning.Charge; +using BTCPayServer.Tests.Lnd; namespace BTCPayServer.Tests { @@ -52,6 +53,8 @@ namespace BTCPayServer.Tests MerchantCharge = new ChargeTester(this, "TEST_MERCHANTCHARGE", "http://api-token:foiewnccewuify@127.0.0.1:54938/", "merchant_lightningd", btc); + MerchantLnd = new LndMockTester(this, "TEST_MERCHANTLND", "http://127.0.0.1:53280/", "merchant_lnd", btc); + PayTester = new BTCPayServerTester(Path.Combine(_Directory, "pay")) { NBXplorerUri = ExplorerClient.Address, @@ -154,6 +157,7 @@ namespace BTCPayServer.Tests public CLightningRPCClient CustomerLightningD { get; set; } public CLightningRPCClient MerchantLightningD { get; private set; } public ChargeTester MerchantCharge { get; private set; } + public LndMockTester MerchantLnd { get; set; } internal string GetEnvironment(string variable, string defaultValue) { diff --git a/BTCPayServer.Tests/TestAccount.cs b/BTCPayServer.Tests/TestAccount.cs index 085d68349..8a120a7dc 100644 --- a/BTCPayServer.Tests/TestAccount.cs +++ b/BTCPayServer.Tests/TestAccount.cs @@ -117,7 +117,7 @@ namespace BTCPayServer.Tests { get; set; } - + public void RegisterLightningNode(string cryptoCode, LightningConnectionType connectionType) { RegisterLightningNodeAsync(cryptoCode, connectionType).GetAwaiter().GetResult(); @@ -126,15 +126,24 @@ namespace BTCPayServer.Tests public async Task RegisterLightningNodeAsync(string cryptoCode, LightningConnectionType connectionType) { var storeController = this.GetController(); + + string uri = null; + if (connectionType == LightningConnectionType.Charge) + uri = parent.MerchantCharge.Client.Uri.AbsoluteUri; + else if (connectionType == LightningConnectionType.CLightning) + uri = parent.MerchantLightningD.Address.AbsoluteUri; + else if (connectionType == LightningConnectionType.Lnd) + uri = parent.MerchantLnd.Swagger.BaseUrl + "?type=lnd"; + else + throw new NotSupportedException(connectionType.ToString()); + await storeController.AddLightningNode(StoreId, new LightningNodeViewModel() { - Url = connectionType == LightningConnectionType.Charge ? parent.MerchantCharge.Client.Uri.AbsoluteUri : - connectionType == LightningConnectionType.CLightning ? parent.MerchantLightningD.Address.AbsoluteUri - : throw new NotSupportedException(connectionType.ToString()), + Url = uri, SkipPortTest = true }, "save", "BTC"); if (storeController.ModelState.ErrorCount != 0) Assert.False(true, storeController.ModelState.FirstOrDefault().Value.Errors[0].ErrorMessage); } -} + } } diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index fbc4a6e58..88434efe4 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -20,6 +20,7 @@ services: TEST_MERCHANTLIGHTNINGD: "/etc/merchant_lightningd_datadir/lightning-rpc" TEST_CUSTOMERLIGHTNINGD: "/etc/customer_lightningd_datadir/lightning-rpc" TEST_MERCHANTCHARGE: http://api-token:foiewnccewuify@lightning-charged:9112/ + TEST_MERCHANTLND: http://127.0.0.1:53280/?type=lnd TESTS_INCONTAINER: "true" expose: - "80" From e634700913d6d719f173ae06d8d775ffc862851c Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 25 May 2018 12:18:47 -0500 Subject: [PATCH 23/45] Changing the way we signal that LightningConnectingString is Lnd --- BTCPayServer.Tests/ServerTester.cs | 2 +- BTCPayServer.Tests/TestAccount.cs | 2 +- BTCPayServer.Tests/UnitTest1.cs | 73 ++++++------------- BTCPayServer.Tests/docker-compose.yml | 2 +- .../Lightning/LightningConnectionString.cs | 20 ++++- 5 files changed, 40 insertions(+), 59 deletions(-) diff --git a/BTCPayServer.Tests/ServerTester.cs b/BTCPayServer.Tests/ServerTester.cs index b7fc5973a..2c0ddf526 100644 --- a/BTCPayServer.Tests/ServerTester.cs +++ b/BTCPayServer.Tests/ServerTester.cs @@ -53,7 +53,7 @@ namespace BTCPayServer.Tests MerchantCharge = new ChargeTester(this, "TEST_MERCHANTCHARGE", "http://api-token:foiewnccewuify@127.0.0.1:54938/", "merchant_lightningd", btc); - MerchantLnd = new LndMockTester(this, "TEST_MERCHANTLND", "http://127.0.0.1:53280/", "merchant_lnd", btc); + MerchantLnd = new LndMockTester(this, "TEST_MERCHANTLND", "http://lnd:lnd@127.0.0.1:53280/", "merchant_lnd", btc); PayTester = new BTCPayServerTester(Path.Combine(_Directory, "pay")) { diff --git a/BTCPayServer.Tests/TestAccount.cs b/BTCPayServer.Tests/TestAccount.cs index 8a120a7dc..e02665e79 100644 --- a/BTCPayServer.Tests/TestAccount.cs +++ b/BTCPayServer.Tests/TestAccount.cs @@ -133,7 +133,7 @@ namespace BTCPayServer.Tests else if (connectionType == LightningConnectionType.CLightning) uri = parent.MerchantLightningD.Address.AbsoluteUri; else if (connectionType == LightningConnectionType.Lnd) - uri = parent.MerchantLnd.Swagger.BaseUrl + "?type=lnd"; + uri = parent.MerchantLnd.Swagger.BaseUrl; else throw new NotSupportedException(connectionType.ToString()); diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index a21a88bda..7b5e290c0 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -431,11 +431,11 @@ namespace BTCPayServer.Tests var macaroon = "0201036c6e640247030a10b0dbbde28f009f83d330bde05075ca251201301a160a0761646472657373120472656164120577726974651a170a08696e766f6963657312047265616412057772697465000006200ae088692e67cf14e767c3d2a4a67ce489150bf810654ff980e1b7a7e263d5e8"; var tls = "2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494942396a4343415a7967417749424167495156397a62474252724e54716b4e4b55676d72524d377a414b42676771686b6a4f50515144416a41784d5238770a485159445651514b45785a73626d5167595856306232646c626d56795958526c5a43426a5a584a304d51347744415944565151444577564754304e56557a41650a467730784f4441304d6a55794d7a517a4d6a4261467730784f5441324d6a41794d7a517a4d6a42614d444578487a416442674e5642416f54466d78755a4342680a645852765a3256755a584a686447566b49474e6c636e5178446a414d42674e5642414d5442555a50513156544d466b77457759484b6f5a497a6a3043415159490a4b6f5a497a6a304441516344516741454b7557424568564f75707965434157476130766e713262712f59396b41755a78616865646d454553482b753936436d450a397577486b4b2b4a7667547a66385141783550513741357254637155374b57595170303175364f426c5443426b6a414f42674e56485138424166384542414d430a4171517744775944565230544151482f42415577417745422f7a427642674e56485245456144426d6767564754304e565534494a6247396a5957786f62334e300a6877522f4141414268784141414141414141414141414141414141414141414268775373474f69786877514b41457342687753702f717473687754417141724c0a687753702f6d4a72687753702f754f77687753702f714e59687753702f6874436877514b70514157687753702f6c42514d416f4743437147534d343942414d430a413067414d45554349464866716d595a5043647a4a5178386b47586859473834394c31766541364c784d6f7a4f5774356d726835416945413662756e51556c710a6558553070474168776c3041654d726a4d4974394c7652736179756162565a593278343d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a"; - var lndUri = $"http://127.0.0.1:53280?type=lnd&macaroon={macaroon}&tls={tls}"; + var lndUri = $"http://lnd:lnd@127.0.0.1:53280?macaroon={macaroon}&tls={tls}"; Assert.True(LightningConnectionString.TryParse(lndUri, out conn)); - Assert.Equal("http://127.0.0.1:53280/", conn.ToString()); - Assert.Equal("http://127.0.0.1:53280/", conn.ToUri(true).AbsoluteUri); + Assert.Equal("http://lnd:lnd@127.0.0.1:53280/", conn.ToString()); + Assert.Equal("http://lnd:lnd@127.0.0.1:53280/", conn.ToUri(true).AbsoluteUri); Assert.Equal("http://127.0.0.1:53280/", conn.ToUri(false).AbsoluteUri); Assert.Equal(LightningConnectionType.Lnd, conn.ConnectionType); Assert.Equal(macaroon, conn.Macaroon); @@ -479,68 +479,37 @@ namespace BTCPayServer.Tests } [Fact] - public void CanSendLightningPayment2() + public void CanSendLightningPaymentCLightning() { - using (var tester = ServerTester.Create()) - { - tester.Start(); - tester.PrepareLightning(); - var user = tester.NewAccount(); - user.GrantAccess(); - user.RegisterLightningNode("BTC", LightningConnectionType.CLightning); - user.RegisterDerivationScheme("BTC"); - - var invoice = user.BitPay.CreateInvoice(new Invoice() - { - Price = 0.01m, - Currency = "USD", - PosData = "posData", - OrderId = "orderId", - ItemDesc = "Some description" - }); - - tester.SendLightningPayment(invoice); - - Eventually(() => - { - var localInvoice = user.BitPay.GetInvoice(invoice.Id); - Assert.Equal("complete", localInvoice.Status); - Assert.Equal("False", localInvoice.ExceptionStatus.ToString()); - }); - } + ProcessLightningPayment(LightningConnectionType.CLightning); } [Fact] - public void CanSendLightningPayment() + public void CanSendLightningPaymentCharge() { + ProcessLightningPayment(LightningConnectionType.Charge); + } + // REQUIRING IMPLEMENTATION OF: + // LndInvoiceClient.Listen & LndInvoiceClient.WaitInvoice + //[Fact] + //public void CanSendLightningPaymentLnd() + //{ + // ProcessLightningPayment(LightningConnectionType.Lnd); + //} + + void ProcessLightningPayment(LightningConnectionType type) + { using (var tester = ServerTester.Create()) { tester.Start(); tester.PrepareLightning(); var user = tester.NewAccount(); user.GrantAccess(); - user.RegisterLightningNode("BTC", LightningConnectionType.Charge); + user.RegisterLightningNode("BTC", type); user.RegisterDerivationScheme("BTC"); - var invoice = user.BitPay.CreateInvoice(new Invoice() - { - Price = 0.01m, - Currency = "USD", - PosData = "posData", - OrderId = "orderId", - ItemDesc = "Some description" - }); - - tester.SendLightningPayment(invoice); - - Eventually(() => - { - var localInvoice = user.BitPay.GetInvoice(invoice.Id); - Assert.Equal("complete", localInvoice.Status); - Assert.Equal("False", localInvoice.ExceptionStatus.ToString()); - }); - + Task.WaitAll(CanSendLightningPaymentCore(tester, user)); Task.WaitAll(Enumerable.Range(0, 5) .Select(_ => CanSendLightningPaymentCore(tester, user)) @@ -550,7 +519,7 @@ namespace BTCPayServer.Tests async Task CanSendLightningPaymentCore(ServerTester tester, TestAccount user) { - await Task.Delay(TimeSpan.FromSeconds(RandomUtils.GetUInt32() % 5)); + await Task.Delay(TimeSpan.FromMilliseconds(RandomUtils.GetUInt32() % 1000)); var invoice = await user.BitPay.CreateInvoiceAsync(new Invoice() { Price = 0.01m, diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 88434efe4..82c1ee9ec 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -20,7 +20,7 @@ services: TEST_MERCHANTLIGHTNINGD: "/etc/merchant_lightningd_datadir/lightning-rpc" TEST_CUSTOMERLIGHTNINGD: "/etc/customer_lightningd_datadir/lightning-rpc" TEST_MERCHANTCHARGE: http://api-token:foiewnccewuify@lightning-charged:9112/ - TEST_MERCHANTLND: http://127.0.0.1:53280/?type=lnd + TEST_MERCHANTLND: http://lnd:lnd@127.0.0.1:53280/ TESTS_INCONTAINER: "true" expose: - "80" diff --git a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs index 556510390..334194c61 100644 --- a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs +++ b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs @@ -89,8 +89,12 @@ namespace BTCPayServer.Payments.Lightning result.ConnectionType = uri.Scheme == "http" || uri.Scheme == "https" ? LightningConnectionType.Charge : LightningConnectionType.CLightning; - - if (uri.Query.Contains("type=lnd")) + + // TODO: We need to redo the way Lightning connection strings are detected + // now that we have Lnd and we can't depend on + // http => Charge + // / => CLightning + if (uri.ToString().Contains("lnd:lnd@")) result.ConnectionType = LightningConnectionType.Lnd; if (result.ConnectionType == LightningConnectionType.Charge) @@ -104,6 +108,11 @@ namespace BTCPayServer.Payments.Lightning result.Username = parts[0]; result.Password = parts[1]; } + else if (result.ConnectionType == LightningConnectionType.Lnd) + { + result.Username = "lnd"; + result.Password = "lnd"; + } else if (!string.IsNullOrEmpty(uri.UserInfo)) { error = "The url should not have user information"; @@ -113,8 +122,11 @@ namespace BTCPayServer.Payments.Lightning if (result.ConnectionType == LightningConnectionType.Lnd) { var queryString = QueryHelpers.ParseNullableQuery(uri.Query); - result.Macaroon = queryString.ContainsKey("macaroon") ? queryString["macaroon"] : StringValues.Empty; - result.Tls = queryString.ContainsKey("tls") ? queryString["tls"] : StringValues.Empty; + if (queryString != null) + { + result.Macaroon = queryString.ContainsKey("macaroon") ? queryString["macaroon"] : StringValues.Empty; + result.Tls = queryString.ContainsKey("tls") ? queryString["tls"] : StringValues.Empty; + } } var uriWithoutQuery = uri.AbsoluteUri.Split('?')[0]; From d293bc3947d8ed36dd07273fd8f009c48a36457f Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 25 May 2018 12:19:15 -0500 Subject: [PATCH 24/45] Throwing NotImplementedException for Listen / WaitInvoice --- .../Payments/Lightning/Lnd/LndInvoiceClient.cs | 12 +++++------- .../Lightning/Lnd/LndSwaggerClientCustomHttp.cs | 4 ++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs index 1142565c5..e182b0240 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs @@ -74,13 +74,15 @@ namespace BTCPayServer.Payments.Lightning.Lnd // TODO: These two methods where you wait on invoice are still work in progress public Task Listen(CancellationToken cancellation = default(CancellationToken)) { - return Task.FromResult(this); + throw new NotImplementedException(); + //return Task.FromResult(this); } async Task ILightningListenInvoiceSession.WaitInvoice(CancellationToken cancellation) { - var resp = await _rpcClient.SubscribeInvoicesAsync(cancellation); - return ConvertLndInvoice(resp); + throw new NotImplementedException(); + //var resp = await _rpcClient.SubscribeInvoicesAsync(cancellation); + //return ConvertLndInvoice(resp); } // Eof work in progress @@ -144,8 +146,4 @@ namespace BTCPayServer.Payments.Lightning.Lnd } } } - - public partial class LndSwaggerClient - { - } } diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs index 8f8187615..8d0d02ca7 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs @@ -89,4 +89,8 @@ namespace BTCPayServer.Payments.Lightning.Lnd return handler; } } + + public partial class LndSwaggerClient + { + } } From ce9189caf8271bebc9a28b633237345272576a9f Mon Sep 17 00:00:00 2001 From: rockstardev Date: Thu, 31 May 2018 15:08:22 -0500 Subject: [PATCH 25/45] Listen / WaitInvoice for Lnd --- BTCPayServer.Tests/Lnd/UnitTests.cs | 20 ++++- .../Lightning/Lnd/LndInvoiceClient.cs | 13 ++- .../Lnd/LndSwaggerClientCustomHttp.cs | 81 ++++++++++++++++--- 3 files changed, 95 insertions(+), 19 deletions(-) diff --git a/BTCPayServer.Tests/Lnd/UnitTests.cs b/BTCPayServer.Tests/Lnd/UnitTests.cs index ecc0747c4..fd893dace 100644 --- a/BTCPayServer.Tests/Lnd/UnitTests.cs +++ b/BTCPayServer.Tests/Lnd/UnitTests.cs @@ -58,8 +58,26 @@ namespace BTCPayServer.Tests.Lnd Assert.Equal(createInvoice.BOLT11, getInvoice.BOLT11); } + // integration tests + [Fact] + public async Task TestWaitListenInvoice() + { + var merchantInvoice = await InvoiceClient.CreateInvoice(10000, "Hello world", TimeSpan.FromSeconds(3600)); - //integration tests + var waitToken = default(CancellationToken); + var listener = await InvoiceClient.Listen(waitToken); + var waitTask = listener.WaitInvoice(waitToken); + + await EnsureLightningChannelAsync(); + var payResponse = await CustomerLnd.SendPaymentSyncAsync(new LnrpcSendRequest + { + Payment_request = merchantInvoice.BOLT11 + }); + + var invoice = await waitTask; + + Assert.True(invoice.PaidAt.HasValue); + } [Fact] public async Task CreateLndInvoiceAndPay() diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs index e182b0240..8484a32a2 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs @@ -70,21 +70,18 @@ namespace BTCPayServer.Payments.Lightning.Lnd var resp = await _rpcClient.LookupInvoiceAsync(invoiceId, null, cancellation); return ConvertLndInvoice(resp); } - - // TODO: These two methods where you wait on invoice are still work in progress + public Task Listen(CancellationToken cancellation = default(CancellationToken)) { - throw new NotImplementedException(); - //return Task.FromResult(this); + Task.Run(_rpcClient.StartSubscribeInvoiceThread); + return Task.FromResult(this); } async Task ILightningListenInvoiceSession.WaitInvoice(CancellationToken cancellation) { - throw new NotImplementedException(); - //var resp = await _rpcClient.SubscribeInvoicesAsync(cancellation); - //return ConvertLndInvoice(resp); + var resp = await _rpcClient.InvoiceResponse.Task; + return ConvertLndInvoice(resp); } - // Eof work in progress // utility static methods... maybe move to separate class diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs index 8d0d02ca7..c4b6c0699 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs @@ -1,10 +1,14 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; using System.Linq; using System.Net.Http; using System.Net.Security; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading; using System.Threading.Tasks; using NBitcoin; @@ -12,7 +16,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd { public class LndSwaggerClientCustomHttp : LndSwaggerClient, IDisposable { - public LndSwaggerClientCustomHttp(string baseUrl, HttpClient httpClient) + protected LndSwaggerClientCustomHttp(string baseUrl, HttpClient httpClient) : base(baseUrl, httpClient) { _HttpClient = httpClient; @@ -28,23 +32,36 @@ namespace BTCPayServer.Payments.Lightning.Lnd // public static LndSwaggerClientCustomHttp Create(Uri uri, Network network, byte[] tlsCertificate = null, byte[] grpcMacaroon = null) { - // for development we are working with custom build of lnd that allows no macaroons and http - var clientWithNoMacaroonsTls = tlsCertificate == null || grpcMacaroon == null; + var factory = new HttpClientFactoryForLnd(tlsCertificate, grpcMacaroon); + var httpClient = factory.Generate(); - var httpClient = clientWithNoMacaroonsTls ? new HttpClient() : - HttpClientFactoryForLnd.Generate(tlsCertificate, grpcMacaroon); + var swagger = new LndSwaggerClientCustomHttp(uri.ToString().TrimEnd('/'), httpClient); + swagger.HttpClientFactory = factory; - return new LndSwaggerClientCustomHttp(uri.ToString().TrimEnd('/'), httpClient); + return swagger; } } internal class HttpClientFactoryForLnd { - internal static HttpClient Generate(byte[] tlsCertificate, byte[] grpcMacaroon) + public HttpClientFactoryForLnd(byte[] tlsCertificate = null, byte[] grpcMacaroon = null) { - var httpClient = new HttpClient(GetCertificate(tlsCertificate)); - var macaroonHex = BitConverter.ToString(grpcMacaroon).Replace("-", "", StringComparison.InvariantCulture); - httpClient.DefaultRequestHeaders.Add("Grpc-Metadata-macaroon", macaroonHex); + TlsCertificate = tlsCertificate; + GrpcMacaroon = grpcMacaroon; + } + + public byte[] TlsCertificate { get; set; } + public byte[] GrpcMacaroon { get; set; } + + public HttpClient Generate() + { + var httpClient = new HttpClient(GetCertificate(TlsCertificate)); + + if (GrpcMacaroon != null) + { + var macaroonHex = BitConverter.ToString(GrpcMacaroon).Replace("-", "", StringComparison.InvariantCulture); + httpClient.DefaultRequestHeaders.Add("Grpc-Metadata-macaroon", macaroonHex); + } return httpClient; } @@ -92,5 +109,49 @@ namespace BTCPayServer.Payments.Lightning.Lnd public partial class LndSwaggerClient { + internal HttpClientFactoryForLnd HttpClientFactory { get; set; } + + public TaskCompletionSource InvoiceResponse = new TaskCompletionSource(); + public TaskCompletionSource SubscribeLost = new TaskCompletionSource(); + + // TODO: Refactor swagger generated wrapper to include this method directly + public async Task StartSubscribeInvoiceThread() + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append(BaseUrl).Append("/v1/invoices/subscribe"); + + using (var client = HttpClientFactory.Generate()) + { + client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite); + + var request = new HttpRequestMessage(HttpMethod.Get, urlBuilder.ToString()); + + using (var response = await client.SendAsync( + request, + HttpCompletionOption.ResponseHeadersRead)) + { + using (var body = await response.Content.ReadAsStreamAsync()) + using (var reader = new StreamReader(body)) + { + try + { + while (!reader.EndOfStream) + { + string line = reader.ReadLine(); + LnrpcInvoice parsedInvoice = Newtonsoft.Json.JsonConvert.DeserializeObject(line, _settings.Value); + + InvoiceResponse?.SetResult(parsedInvoice); + } + } + catch (Exception e) + { + // TODO: check that the exception type is actually from a closed stream. + Debug.WriteLine(e.Message); + SubscribeLost?.SetResult(this); + } + } + } + } + } } } From 279de1b869b1696ea16fb6365b6c03bc87021484 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Thu, 31 May 2018 15:53:14 -0500 Subject: [PATCH 26/45] Passing CancelToken and properly parsing invoice response --- .../Lightning/Lnd/LndInvoiceClient.cs | 4 +++- .../Lnd/LndSwaggerClientCustomHttp.cs | 20 ++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs index 8484a32a2..0de32243e 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs @@ -73,7 +73,9 @@ namespace BTCPayServer.Payments.Lightning.Lnd public Task Listen(CancellationToken cancellation = default(CancellationToken)) { - Task.Run(_rpcClient.StartSubscribeInvoiceThread); +#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed + _rpcClient.StartSubscribeInvoiceThread(cancellation); +#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed return Task.FromResult(this); } diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs index c4b6c0699..b32808e5a 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClientCustomHttp.cs @@ -11,6 +11,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using NBitcoin; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace BTCPayServer.Payments.Lightning.Lnd { @@ -115,7 +117,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd public TaskCompletionSource SubscribeLost = new TaskCompletionSource(); // TODO: Refactor swagger generated wrapper to include this method directly - public async Task StartSubscribeInvoiceThread() + public async Task StartSubscribeInvoiceThread(CancellationToken token) { var urlBuilder = new StringBuilder(); urlBuilder.Append(BaseUrl).Append("/v1/invoices/subscribe"); @@ -127,8 +129,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd var request = new HttpRequestMessage(HttpMethod.Get, urlBuilder.ToString()); using (var response = await client.SendAsync( - request, - HttpCompletionOption.ResponseHeadersRead)) + request, HttpCompletionOption.ResponseHeadersRead, token)) { using (var body = await response.Content.ReadAsStreamAsync()) using (var reader = new StreamReader(body)) @@ -138,16 +139,21 @@ namespace BTCPayServer.Payments.Lightning.Lnd while (!reader.EndOfStream) { string line = reader.ReadLine(); - LnrpcInvoice parsedInvoice = Newtonsoft.Json.JsonConvert.DeserializeObject(line, _settings.Value); - - InvoiceResponse?.SetResult(parsedInvoice); + if (line != null && line.Contains("\"result\":")) + { + dynamic parsedJson = JObject.Parse(line); + var result = parsedJson.result; + var invoiceString = result.ToString(); + LnrpcInvoice parsedInvoice = JsonConvert.DeserializeObject(invoiceString, _settings.Value); + InvoiceResponse.SetResult(parsedInvoice); + } } } catch (Exception e) { // TODO: check that the exception type is actually from a closed stream. Debug.WriteLine(e.Message); - SubscribeLost?.SetResult(this); + SubscribeLost.SetResult(this); } } } From d1fb51b4123e856022e1cb8f10fc85651f70270f Mon Sep 17 00:00:00 2001 From: rockstardev Date: Thu, 31 May 2018 16:07:59 -0500 Subject: [PATCH 27/45] Reactivating LND end to end test --- BTCPayServer.Tests/UnitTest1.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 0b8872215..57ed05c96 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -490,13 +490,11 @@ namespace BTCPayServer.Tests ProcessLightningPayment(LightningConnectionType.Charge); } - // REQUIRING IMPLEMENTATION OF: - // LndInvoiceClient.Listen & LndInvoiceClient.WaitInvoice - //[Fact] - //public void CanSendLightningPaymentLnd() - //{ - // ProcessLightningPayment(LightningConnectionType.Lnd); - //} + [Fact] + public void CanSendLightningPaymentLnd() + { + ProcessLightningPayment(LightningConnectionType.Lnd); + } void ProcessLightningPayment(LightningConnectionType type) { From 2bd12386685b7b6075c1a804d0864d24e5ff8618 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Thu, 31 May 2018 16:31:00 -0500 Subject: [PATCH 28/45] Rounding TotalSeconds expiry so it doesn't break invoice creation --- BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs index 0de32243e..7a86c4b20 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs @@ -28,7 +28,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd CancellationToken cancellation = default(CancellationToken)) { var strAmount = ConvertInv.ToString(amount.ToUnit(LightMoneyUnit.Satoshi)); - var strExpiry = ConvertInv.ToString(expiry.TotalSeconds); + var strExpiry = ConvertInv.ToString(Math.Round(expiry.TotalSeconds, 0)); // lnd requires numbers sent as strings. don't ask var resp = await _rpcClient.AddInvoiceAsync(new LnrpcInvoice { From 0d1d0d57f4e5644131b02ac3910d2143d6fdf120 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Thu, 31 May 2018 16:31:19 -0500 Subject: [PATCH 29/45] Logging Swagger errors for logging and easier debugging --- BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs index 91c3fe157..c59793b8d 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndSwaggerClient.cs @@ -4,6 +4,8 @@ // //---------------------- +using System.Diagnostics; + namespace BTCPayServer.Payments.Lightning.Lnd { #pragma warning disable // Disable all warnings @@ -8698,6 +8700,8 @@ namespace BTCPayServer.Payments.Lightning.Lnd StatusCode = statusCode; Response = response; Headers = headers; + + Debug.WriteLine($"SwaggerException: {response}"); } public override string ToString() @@ -8718,4 +8722,4 @@ namespace BTCPayServer.Payments.Lightning.Lnd } } -} \ No newline at end of file +} From f8c88bd44fd37ea49a8d2b01cad25d56a846d6f2 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Thu, 31 May 2018 16:31:39 -0500 Subject: [PATCH 30/45] Providing ability to increase lightning timeout for tests/debugging --- BTCPayServer.Tests/UnitTest1.cs | 3 +++ .../Payments/Lightning/LightningLikePaymentHandler.cs | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 57ed05c96..364584a95 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -493,6 +493,9 @@ namespace BTCPayServer.Tests [Fact] public void CanSendLightningPaymentLnd() { + // For easier debugging and testing + LightningLikePaymentHandler.LIGHTNING_TIMEOUT = int.MaxValue; + ProcessLightningPayment(LightningConnectionType.Lnd); } diff --git a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs index 76fc5cb18..9b871d2ad 100644 --- a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs +++ b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs @@ -15,6 +15,8 @@ namespace BTCPayServer.Payments.Lightning { public class LightningLikePaymentHandler : PaymentMethodHandlerBase { + public static int LIGHTNING_TIMEOUT = 5000; + NBXplorerDashboard _Dashboard; LightningClientFactory _LightningClientFactory; public LightningLikePaymentHandler( @@ -41,7 +43,7 @@ namespace BTCPayServer.Payments.Lightning description = description.Replace("{StoreName}", store.StoreName ?? "", StringComparison.OrdinalIgnoreCase) .Replace("{ItemDescription}", invoice.ProductInformation.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase) .Replace("{OrderId}", invoice.OrderId ?? "", StringComparison.OrdinalIgnoreCase); - using (var cts = new CancellationTokenSource(5000)) + using (var cts = new CancellationTokenSource(LIGHTNING_TIMEOUT)) { try { @@ -70,7 +72,7 @@ namespace BTCPayServer.Payments.Lightning if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary)) throw new PaymentMethodUnavailableException($"Full node not available"); - using (var cts = new CancellationTokenSource(5000)) + using (var cts = new CancellationTokenSource(LIGHTNING_TIMEOUT)) { var client = _LightningClientFactory.CreateClient(supportedPaymentMethod, network); LightningNodeInformation info = null; From 55c9314cdd3ad40c9dc7a4aabce13e9f406fa03d Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 11:53:34 -0500 Subject: [PATCH 31/45] Reference to lnd docker image updated to point to latest Also helps with building image locally for debugging --- BTCPayServer.Tests/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 568d25c48..28f525584 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -200,7 +200,7 @@ services: - "5432" merchant_lnd: - image: btcpayserver/lnd:0.4.1.0 + image: btcpayserver/lnd:latest environment: RPCHOST: bitcoind:43782 RPCUSER: ceiwHEbqWI83 @@ -220,7 +220,7 @@ services: - bitcoind customer_lnd: - image: btcpayserver/lnd:0.4.1.0 + image: btcpayserver/lnd:latest environment: RPCHOST: bitcoind:43782 RPCUSER: ceiwHEbqWI83 From cfd083bed547611ed2459407d2ff3f6bb0f30bc8 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 11:53:53 -0500 Subject: [PATCH 32/45] Providing port for peer-to-peer connection for local tests --- BTCPayServer.Tests/docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 28f525584..8fa6b2db5 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -210,6 +210,7 @@ services: CHAIN: bitcoin BACKEND: bitcoind DEBUG: debug + EXTERNALIP: merchant_lnd:9735 ports: - "53280:8080" expose: From 9b540273fc280b808d9b2976bc8f0df004480816 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 13:57:39 -0500 Subject: [PATCH 33/45] Parsing of node info and returning it for GetInfo --- BTCPayServer.Tests/UnitTest1.cs | 6 +++--- .../Lightning/Lnd/LndInvoiceClient.cs | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 364584a95..855e43915 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -493,14 +493,14 @@ namespace BTCPayServer.Tests [Fact] public void CanSendLightningPaymentLnd() { - // For easier debugging and testing - LightningLikePaymentHandler.LIGHTNING_TIMEOUT = int.MaxValue; - ProcessLightningPayment(LightningConnectionType.Lnd); } void ProcessLightningPayment(LightningConnectionType type) { + // For easier debugging and testing + LightningLikePaymentHandler.LIGHTNING_TIMEOUT = int.MaxValue; + using (var tester = ServerTester.Create()) { tester.Start(); diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs index 7a86c4b20..896461ff8 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs @@ -57,10 +57,16 @@ namespace BTCPayServer.Payments.Lightning.Lnd NodeId = resp.Identity_pubkey }; - // Lnd doesn't return this data as Clightning, find alternative ways to supply - // it always should be merchant_lnd:9735 because of docker - nodeInfo.Address = null; - nodeInfo.P2PPort = 9735; + + var node = await _rpcClient.GetNodeInfoAsync(resp.Identity_pubkey, cancellation); + if (node.Node.Addresses == null || node.Node.Addresses.Count == 0) + throw new Exception("Lnd External IP not set, make sure you use --externalip=$EXTERNALIP parameter on lnd"); + + var firstNodeInfo = node.Node.Addresses.First(); + var externalHostPort = firstNodeInfo.Addr.Split(':'); + + nodeInfo.Address = externalHostPort[0]; + nodeInfo.P2PPort = ConvertInv.ToInt32(externalHostPort[1]); return nodeInfo; } @@ -129,6 +135,11 @@ namespace BTCPayServer.Payments.Lightning.Lnd // Invariant culture conversion public static class ConvertInv { + public static int ToInt32(string str) + { + return Convert.ToInt32(str, CultureInfo.InvariantCulture.NumberFormat); + } + public static long ToInt64(string str) { return Convert.ToInt64(str, CultureInfo.InvariantCulture.NumberFormat); From 69bd888babbd5cd3816efe56801a5bcd521683b4 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 15:02:40 -0500 Subject: [PATCH 34/45] Refactoring ServerTester so that ClightningRPCClient can use LND --- BTCPayServer.Tests/ServerTester.cs | 38 ++++++++++++++++++++---------- BTCPayServer.Tests/UnitTest1.cs | 3 ++- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/BTCPayServer.Tests/ServerTester.cs b/BTCPayServer.Tests/ServerTester.cs index a47268c48..fa16ca2d9 100644 --- a/BTCPayServer.Tests/ServerTester.cs +++ b/BTCPayServer.Tests/ServerTester.cs @@ -21,6 +21,7 @@ using System.Globalization; using BTCPayServer.Payments.Lightning.CLightning; using BTCPayServer.Payments.Lightning.Charge; using BTCPayServer.Tests.Lnd; +using BTCPayServer.Payments.Lightning; namespace BTCPayServer.Tests { @@ -81,41 +82,51 @@ namespace BTCPayServer.Tests /// /// Connect a customer LN node to the merchant LN node /// - public void PrepareLightning() + public void PrepareLightning(LightningConnectionType lndBackend) { - PrepareLightningAsync().GetAwaiter().GetResult(); + ILightningInvoiceClient client = MerchantCharge.Client; + if (lndBackend == LightningConnectionType.Lnd) + client = MerchantLnd.Client; + + PrepareLightningAsync(client).GetAwaiter().GetResult(); } + private static readonly string[] SKIPPED_STATES = + { "ONCHAIN", "CHANNELD_SHUTTING_DOWN", "CLOSINGD_SIGEXCHANGE", "CLOSINGD_COMPLETE", "FUNDING_SPEND_SEEN" }; + /// /// Connect a customer LN node to the merchant LN node /// /// - public async Task PrepareLightningAsync() + private async Task PrepareLightningAsync(ILightningInvoiceClient client) { while (true) { - var skippedStates = new[] { "ONCHAIN", "CHANNELD_SHUTTING_DOWN", "CLOSINGD_SIGEXCHANGE", "CLOSINGD_COMPLETE", "FUNDING_SPEND_SEEN" }; - var channel = (await CustomerLightningD.ListPeersAsync()) + var merchantInfo = await WaitLNSynched(client); + + var peers = await CustomerLightningD.ListPeersAsync(); + var filteringToTargetedPeers = peers.Where(a => a.Id == merchantInfo.NodeId); + var channel = filteringToTargetedPeers .SelectMany(p => p.Channels) - .Where(c => !skippedStates.Contains(c.State ?? "")) + .Where(c => !SKIPPED_STATES.Contains(c.State ?? "")) .FirstOrDefault(); + switch (channel?.State) { case null: - var merchantInfo = await WaitLNSynched(); - var clightning = new NodeInfo(merchantInfo.Id, MerchantCharge.P2PHost, merchantInfo.Port); + var clightning = new NodeInfo(merchantInfo.NodeId, merchantInfo.Address, merchantInfo.P2PPort); await CustomerLightningD.ConnectAsync(clightning); var address = await CustomerLightningD.NewAddressAsync(); await ExplorerNode.SendToAddressAsync(address, Money.Coins(0.2m)); - ExplorerNode.Generate(1); - await WaitLNSynched(); + ExplorerNode.Generate(6); + await WaitLNSynched(client); await Task.Delay(1000); await CustomerLightningD.FundChannelAsync(clightning, Money.Satoshis(16777215)); break; case "CHANNELD_AWAITING_LOCKIN": ExplorerNode.Generate(1); - await WaitLNSynched(); + await WaitLNSynched(client); break; case "CHANNELD_NORMAL": return; @@ -125,11 +136,11 @@ namespace BTCPayServer.Tests } } - private async Task WaitLNSynched() + private async Task WaitLNSynched(ILightningInvoiceClient client) { while (true) { - var merchantInfo = await MerchantCharge.Client.GetInfoAsync(); + var merchantInfo = await client.GetInfo(); var blockCount = await ExplorerNode.GetBlockCountAsync(); if (merchantInfo.BlockHeight != blockCount) { @@ -155,6 +166,7 @@ namespace BTCPayServer.Tests } public CLightningRPCClient CustomerLightningD { get; set; } + public CLightningRPCClient MerchantLightningD { get; private set; } public ChargeTester MerchantCharge { get; private set; } public LndMockTester MerchantLnd { get; set; } diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 855e43915..4e41d215a 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -504,11 +504,12 @@ namespace BTCPayServer.Tests using (var tester = ServerTester.Create()) { tester.Start(); - tester.PrepareLightning(); var user = tester.NewAccount(); user.GrantAccess(); user.RegisterLightningNode("BTC", type); user.RegisterDerivationScheme("BTC"); + + tester.PrepareLightning(type); Task.WaitAll(CanSendLightningPaymentCore(tester, user)); From a22576da0a792f94ad19df6a6d9f86666043ffda Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 15:56:02 -0500 Subject: [PATCH 35/45] Streamlining flow of interaction between test lnd customer / merchant --- BTCPayServer.Tests/ServerTester.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/BTCPayServer.Tests/ServerTester.cs b/BTCPayServer.Tests/ServerTester.cs index fa16ca2d9..9caed38fa 100644 --- a/BTCPayServer.Tests/ServerTester.cs +++ b/BTCPayServer.Tests/ServerTester.cs @@ -115,14 +115,15 @@ namespace BTCPayServer.Tests switch (channel?.State) { case null: - var clightning = new NodeInfo(merchantInfo.NodeId, merchantInfo.Address, merchantInfo.P2PPort); - await CustomerLightningD.ConnectAsync(clightning); var address = await CustomerLightningD.NewAddressAsync(); - await ExplorerNode.SendToAddressAsync(address, Money.Coins(0.2m)); - ExplorerNode.Generate(6); + await ExplorerNode.SendToAddressAsync(address, Money.Coins(0.5m)); + ExplorerNode.Generate(1); await WaitLNSynched(client); await Task.Delay(1000); - await CustomerLightningD.FundChannelAsync(clightning, Money.Satoshis(16777215)); + + var merchantNodeInfo = new NodeInfo(merchantInfo.NodeId, merchantInfo.Address, merchantInfo.P2PPort); + await CustomerLightningD.ConnectAsync(merchantNodeInfo); + await CustomerLightningD.FundChannelAsync(merchantNodeInfo, Money.Satoshis(16777215)); break; case "CHANNELD_AWAITING_LOCKIN": ExplorerNode.Generate(1); From 66ecb32538327ea2b2ecb9447d485592907e18ae Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 16:29:09 -0500 Subject: [PATCH 36/45] Need param so that funding channels can be opened between LND and CL --- BTCPayServer.Tests/docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 8fa6b2db5..4caed41ae 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -122,6 +122,7 @@ services: announce-addr=customer_lightningd log-level=debug dev-broadcast-interval=1000 + max-locktime-blocks=2016 ports: - "30992:9835" # api port expose: From 89d9658e8255da708f42582d11e26c0714c97775 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 17:12:59 -0500 Subject: [PATCH 37/45] Bugfixing amount in invoice data, we need to set Satoshis --- BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs index 896461ff8..3f1771a5b 100644 --- a/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs +++ b/BTCPayServer/Payments/Lightning/Lnd/LndInvoiceClient.cs @@ -106,7 +106,7 @@ namespace BTCPayServer.Payments.Lightning.Lnd { // TODO: Verify id corresponds to R_hash Id = BitString(resp.R_hash), - Amount = resp.Value, + Amount = new LightMoney(ConvertInv.ToInt64(resp.Value), LightMoneyUnit.Satoshi), BOLT11 = resp.Payment_request, Status = "unpaid" }; From 4ddcd7a4c8b8b25feadb07ed2aa4986de16b7142 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 17:14:20 -0500 Subject: [PATCH 38/45] Will depend on lnd bitcoin.defaultremotedelay=720 param Ref: https://github.com/lightningnetwork/lnd/pull/788 --- BTCPayServer.Tests/docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 4caed41ae..8fa6b2db5 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -122,7 +122,6 @@ services: announce-addr=customer_lightningd log-level=debug dev-broadcast-interval=1000 - max-locktime-blocks=2016 ports: - "30992:9835" # api port expose: From 2465eb7e3680015c13eb4a304309aff8b3f9d18e Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 17:20:56 -0500 Subject: [PATCH 39/45] Revering debug param --- BTCPayServer.Tests/UnitTest1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 4e41d215a..a25385eb7 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -499,7 +499,7 @@ namespace BTCPayServer.Tests void ProcessLightningPayment(LightningConnectionType type) { // For easier debugging and testing - LightningLikePaymentHandler.LIGHTNING_TIMEOUT = int.MaxValue; + // LightningLikePaymentHandler.LIGHTNING_TIMEOUT = int.MaxValue; using (var tester = ServerTester.Create()) { From 4972f0ab7b5b827d3980e80c30ad9f277163d798 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 18:27:37 -0500 Subject: [PATCH 40/45] Labeling issue with rapid testing of lightning payments --- BTCPayServer.Tests/UnitTest1.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 058edc9d5..5af1e4ca1 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -522,7 +522,10 @@ namespace BTCPayServer.Tests async Task CanSendLightningPaymentCore(ServerTester tester, TestAccount user) { - await Task.Delay(TimeSpan.FromMilliseconds(RandomUtils.GetUInt32() % 1000)); + // TODO: If this parameter is less than 1 second we start having concurrency problems + await Task.Delay(TimeSpan.FromMilliseconds(1000)); + // + var invoice = await user.BitPay.CreateInvoiceAsync(new Invoice() { Price = 0.01m, From 42475ec7b7a922eca1af413f49db4e7effd9694e Mon Sep 17 00:00:00 2001 From: rockstardev Date: Fri, 15 Jun 2018 18:28:01 -0500 Subject: [PATCH 41/45] Switching to lnd image from Docker Hub --- BTCPayServer.Tests/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 8fa6b2db5..a7a376026 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -200,7 +200,7 @@ services: - "5432" merchant_lnd: - image: btcpayserver/lnd:latest + image: btcpayserver/lnd:0.4.2.0 environment: RPCHOST: bitcoind:43782 RPCUSER: ceiwHEbqWI83 @@ -221,7 +221,7 @@ services: - bitcoind customer_lnd: - image: btcpayserver/lnd:latest + image: btcpayserver/lnd:0.4.2.0 environment: RPCHOST: bitcoind:43782 RPCUSER: ceiwHEbqWI83 From 039303bfaa6c48e176ceaf9fd8a330de07f225db Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sat, 23 Jun 2018 22:03:51 -0500 Subject: [PATCH 42/45] Fixing typos during code review --- BTCPayServer/Configuration/BTCPayServerOptions.cs | 2 +- BTCPayServer/Controllers/StoresController.LightningLike.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BTCPayServer/Configuration/BTCPayServerOptions.cs b/BTCPayServer/Configuration/BTCPayServerOptions.cs index 2ed2e665d..9c7422828 100644 --- a/BTCPayServer/Configuration/BTCPayServerOptions.cs +++ b/BTCPayServer/Configuration/BTCPayServerOptions.cs @@ -81,7 +81,7 @@ namespace BTCPayServer.Configuration { throw new ConfigException($"Invalid setting {net.CryptoCode}.lightning, you need to pass either " + $"the absolute path to the unix socket of a running CLightning instance (eg. /root/.lightning/lightning-rpc), " + - $"or the url to a charge server with crendetials (eg. https://apitoken@API_TOKEN_SECRET:charge.example.com/)"); + $"or the url to a charge server with credentials (eg. https://apitoken@API_TOKEN_SECRET:charge.example.com/)"); } InternalLightningByCryptoCode.Add(net.CryptoCode, connectionString); } diff --git a/BTCPayServer/Controllers/StoresController.LightningLike.cs b/BTCPayServer/Controllers/StoresController.LightningLike.cs index 1b51b51b4..fdfef2acb 100644 --- a/BTCPayServer/Controllers/StoresController.LightningLike.cs +++ b/BTCPayServer/Controllers/StoresController.LightningLike.cs @@ -110,6 +110,7 @@ namespace BTCPayServer.Controllers }; paymentMethod.SetLightningUrl(connectionString); } + if (command == "save") { store.SetSupportedPaymentMethod(paymentMethodId, paymentMethod); @@ -135,7 +136,7 @@ namespace BTCPayServer.Controllers await handler.TestConnection(info, cts.Token); } } - vm.StatusMessage = $"Connection to the lightning node succeed ({info})"; + vm.StatusMessage = $"Connection to the lightning node succeeded ({info})"; } catch (Exception ex) { From d34ffc0d9a8e47eb1c166f82d38643e4fa1677f1 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sat, 23 Jun 2018 22:50:50 -0500 Subject: [PATCH 43/45] Refactoring conditional method, separating into two properties --- BTCPayServer.Tests/UnitTest1.cs | 24 +++++++++---------- .../StoresController.LightningLike.cs | 13 ++++------ BTCPayServer/Controllers/StoresController.cs | 2 +- .../Lightning/LightningClientFactory.cs | 6 ++--- .../Lightning/LightningConnectionString.cs | 22 ++++++++--------- 5 files changed, 30 insertions(+), 37 deletions(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 5af1e4ca1..c2970273b 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -436,40 +436,40 @@ namespace BTCPayServer.Tests Assert.True(LightningConnectionString.TryParse(lndUri, out conn)); Assert.Equal("http://lnd:lnd@127.0.0.1:53280/", conn.ToString()); - Assert.Equal("http://lnd:lnd@127.0.0.1:53280/", conn.ToUri(true).AbsoluteUri); - Assert.Equal("http://127.0.0.1:53280/", conn.ToUri(false).AbsoluteUri); + Assert.Equal("http://lnd:lnd@127.0.0.1:53280/", conn.UriWithCreds.AbsoluteUri); + Assert.Equal("http://127.0.0.1:53280/", conn.UriPlain.AbsoluteUri); Assert.Equal(LightningConnectionType.Lnd, conn.ConnectionType); Assert.Equal(macaroon, conn.Macaroon); Assert.Equal(tls, conn.Tls); Assert.True(LightningConnectionString.TryParse("/test/a", out conn)); Assert.Equal("unix://test/a", conn.ToString()); - Assert.Equal("unix://test/a", conn.ToUri(true).AbsoluteUri); - Assert.Equal("unix://test/a", conn.ToUri(false).AbsoluteUri); + Assert.Equal("unix://test/a", conn.UriWithCreds.AbsoluteUri); + Assert.Equal("unix://test/a", conn.UriPlain.AbsoluteUri); Assert.Equal(LightningConnectionType.CLightning, conn.ConnectionType); Assert.True(LightningConnectionString.TryParse("unix://test/a", out conn)); Assert.Equal("unix://test/a", conn.ToString()); - Assert.Equal("unix://test/a", conn.ToUri(true).AbsoluteUri); - Assert.Equal("unix://test/a", conn.ToUri(false).AbsoluteUri); + Assert.Equal("unix://test/a", conn.UriWithCreds.AbsoluteUri); + Assert.Equal("unix://test/a", conn.UriPlain.AbsoluteUri); Assert.Equal(LightningConnectionType.CLightning, conn.ConnectionType); Assert.True(LightningConnectionString.TryParse("unix://test/a", out conn)); Assert.Equal("unix://test/a", conn.ToString()); - Assert.Equal("unix://test/a", conn.ToUri(true).AbsoluteUri); - Assert.Equal("unix://test/a", conn.ToUri(false).AbsoluteUri); + Assert.Equal("unix://test/a", conn.UriWithCreds.AbsoluteUri); + Assert.Equal("unix://test/a", conn.UriPlain.AbsoluteUri); Assert.Equal(LightningConnectionType.CLightning, conn.ConnectionType); Assert.True(LightningConnectionString.TryParse("tcp://test/a", out conn)); Assert.Equal("tcp://test/a", conn.ToString()); - Assert.Equal("tcp://test/a", conn.ToUri(true).AbsoluteUri); - Assert.Equal("tcp://test/a", conn.ToUri(false).AbsoluteUri); + Assert.Equal("tcp://test/a", conn.UriWithCreds.AbsoluteUri); + Assert.Equal("tcp://test/a", conn.UriPlain.AbsoluteUri); Assert.Equal(LightningConnectionType.CLightning, conn.ConnectionType); Assert.True(LightningConnectionString.TryParse("http://aaa:bbb@test/a", out conn)); Assert.Equal("http://aaa:bbb@test/a", conn.ToString()); - Assert.Equal("http://aaa:bbb@test/a", conn.ToUri(true).AbsoluteUri); - Assert.Equal("http://test/a", conn.ToUri(false).AbsoluteUri); + Assert.Equal("http://aaa:bbb@test/a", conn.UriWithCreds.AbsoluteUri); + Assert.Equal("http://test/a", conn.UriPlain.AbsoluteUri); Assert.Equal(LightningConnectionType.Charge, conn.ConnectionType); Assert.Equal("aaa", conn.Username); Assert.Equal("bbb", conn.Password); diff --git a/BTCPayServer/Controllers/StoresController.LightningLike.cs b/BTCPayServer/Controllers/StoresController.LightningLike.cs index fdfef2acb..9fdd24ec9 100644 --- a/BTCPayServer/Controllers/StoresController.LightningLike.cs +++ b/BTCPayServer/Controllers/StoresController.LightningLike.cs @@ -26,16 +26,11 @@ namespace BTCPayServer.Controllers return NotFound(); LightningNodeViewModel vm = new LightningNodeViewModel(); vm.CryptoCode = cryptoCode; - vm.InternalLightningNode = GetInternalLighningNode(cryptoCode)?.ToUri(true)?.AbsoluteUri; - SetExistingValues(store, vm); + vm.InternalLightningNode = GetInternalLighningNode(cryptoCode)?.UriWithCreds?.AbsoluteUri; + vm.Url = GetExistingLightningSupportedPaymentMethod(vm.CryptoCode, store)?.GetLightningUrl()?.UriWithCreds.AbsoluteUri; return View(vm); } - private void SetExistingValues(StoreData store, LightningNodeViewModel vm) - { - vm.Url = GetExistingLightningSupportedPaymentMethod(vm.CryptoCode, store)?.GetLightningUrl()?.ToString(); - } - private LightningSupportedPaymentMethod GetExistingLightningSupportedPaymentMethod(string cryptoCode, StoreData store) { var id = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike); @@ -65,7 +60,7 @@ namespace BTCPayServer.Controllers var network = vm.CryptoCode == null ? null : _ExplorerProvider.GetNetwork(vm.CryptoCode); var internalLightning = GetInternalLighningNode(network.CryptoCode); - vm.InternalLightningNode = internalLightning?.ToUri(true)?.AbsoluteUri; + vm.InternalLightningNode = internalLightning?.UriWithCreds?.AbsoluteUri; if (network == null) { ModelState.AddModelError(nameof(vm.CryptoCode), "Invalid network"); @@ -82,7 +77,7 @@ namespace BTCPayServer.Controllers return View(vm); } - var internalDomain = internalLightning?.ToUri(false)?.DnsSafeHost; + var internalDomain = internalLightning?.UriPlain?.DnsSafeHost; bool isLocal = (internalDomain == "127.0.0.1" || internalDomain == "localhost"); bool isInternalNode = connectionString.ConnectionType == LightningConnectionType.CLightning || diff --git a/BTCPayServer/Controllers/StoresController.cs b/BTCPayServer/Controllers/StoresController.cs index 12b7cf005..9bd1cb218 100644 --- a/BTCPayServer/Controllers/StoresController.cs +++ b/BTCPayServer/Controllers/StoresController.cs @@ -461,7 +461,7 @@ namespace BTCPayServer.Controllers vm.LightningNodes.Add(new StoreViewModel.LightningNode() { CryptoCode = network.CryptoCode, - Address = lightning?.GetLightningUrl()?.BaseUri.AbsoluteUri ?? string.Empty + Address = lightning?.GetLightningUrl()?.UriPlain.AbsoluteUri ?? string.Empty }); } } diff --git a/BTCPayServer/Payments/Lightning/LightningClientFactory.cs b/BTCPayServer/Payments/Lightning/LightningClientFactory.cs index db8d8fa2b..d6cbf3d4b 100644 --- a/BTCPayServer/Payments/Lightning/LightningClientFactory.cs +++ b/BTCPayServer/Payments/Lightning/LightningClientFactory.cs @@ -15,11 +15,11 @@ namespace BTCPayServer.Payments.Lightning var connString = supportedPaymentMethod.GetLightningUrl(); if (connString.ConnectionType == LightningConnectionType.Charge) { - return new ChargeClient(connString.ToUri(true), network.NBitcoinNetwork); + return new ChargeClient(connString.UriWithCreds, network.NBitcoinNetwork); } else if (connString.ConnectionType == LightningConnectionType.CLightning) { - return new CLightningRPCClient(connString.ToUri(false), network.NBitcoinNetwork); + return new CLightningRPCClient(connString.UriPlain, network.NBitcoinNetwork); } else if (connString.ConnectionType == LightningConnectionType.Lnd) { @@ -33,7 +33,7 @@ namespace BTCPayServer.Payments.Lightning if (!String.IsNullOrEmpty(connString.Tls)) tls = hex.DecodeData(connString.Tls); - var swagger = LndSwaggerClientCustomHttp.Create(connString.ToUri(false), network.NBitcoinNetwork, tls, macaroon); + var swagger = LndSwaggerClientCustomHttp.Create(connString.UriPlain, network.NBitcoinNetwork, tls, macaroon); return new LndInvoiceClient(swagger); } else diff --git a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs index 334194c61..13c5ac210 100644 --- a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs +++ b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs @@ -20,7 +20,7 @@ namespace BTCPayServer.Payments.Lightning public string Username { get; set; } public string Password { get; set; } - public Uri BaseUri { get; set; } + public Uri BaseUri { get; set; } // has no user and password public LightningConnectionType ConnectionType { get; private set; } @@ -29,21 +29,19 @@ namespace BTCPayServer.Payments.Lightning public string Macaroon { get; set; } // - public Uri ToUri(bool withCredentials) + public Uri UriWithCreds { - if (withCredentials) - { - return new UriBuilder(BaseUri) { UserName = Username ?? "", Password = Password ?? "" }.Uri; - } - else - { - return BaseUri; - } + get { return new UriBuilder(BaseUri) { UserName = Username ?? "", Password = Password ?? "" }.Uri; } + } + + public Uri UriPlain + { + get { return BaseUri; } } public override string ToString() { - return ToUri(true).AbsoluteUri; + return UriWithCreds.AbsoluteUri; } // @@ -89,7 +87,7 @@ namespace BTCPayServer.Payments.Lightning result.ConnectionType = uri.Scheme == "http" || uri.Scheme == "https" ? LightningConnectionType.Charge : LightningConnectionType.CLightning; - + // TODO: We need to redo the way Lightning connection strings are detected // now that we have Lnd and we can't depend on // http => Charge From 3c4c99ee4263ad23e566322e3fdb59edc60646fc Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sat, 23 Jun 2018 23:16:39 -0500 Subject: [PATCH 44/45] Saving of Macaroon and Tls for LND connection --- .../StoresController.LightningLike.cs | 2 +- BTCPayServer/Controllers/StoresController.cs | 2 +- .../Lightning/LightningConnectionString.cs | 19 ++++++++++++++- .../LightningSupportedPaymentMethod.cs | 23 ++++++++++++++----- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/BTCPayServer/Controllers/StoresController.LightningLike.cs b/BTCPayServer/Controllers/StoresController.LightningLike.cs index 9fdd24ec9..621614964 100644 --- a/BTCPayServer/Controllers/StoresController.LightningLike.cs +++ b/BTCPayServer/Controllers/StoresController.LightningLike.cs @@ -27,7 +27,7 @@ namespace BTCPayServer.Controllers LightningNodeViewModel vm = new LightningNodeViewModel(); vm.CryptoCode = cryptoCode; vm.InternalLightningNode = GetInternalLighningNode(cryptoCode)?.UriWithCreds?.AbsoluteUri; - vm.Url = GetExistingLightningSupportedPaymentMethod(vm.CryptoCode, store)?.GetLightningUrl()?.UriWithCreds.AbsoluteUri; + vm.Url = GetExistingLightningSupportedPaymentMethod(vm.CryptoCode, store)?.GetLightningUrl()?.ToFullEditString(); return View(vm); } diff --git a/BTCPayServer/Controllers/StoresController.cs b/BTCPayServer/Controllers/StoresController.cs index 9bd1cb218..12b7cf005 100644 --- a/BTCPayServer/Controllers/StoresController.cs +++ b/BTCPayServer/Controllers/StoresController.cs @@ -461,7 +461,7 @@ namespace BTCPayServer.Controllers vm.LightningNodes.Add(new StoreViewModel.LightningNode() { CryptoCode = network.CryptoCode, - Address = lightning?.GetLightningUrl()?.UriPlain.AbsoluteUri ?? string.Empty + Address = lightning?.GetLightningUrl()?.BaseUri.AbsoluteUri ?? string.Empty }); } } diff --git a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs index 13c5ac210..559ed488f 100644 --- a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs +++ b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs @@ -25,8 +25,8 @@ namespace BTCPayServer.Payments.Lightning public LightningConnectionType ConnectionType { get; private set; } // Extract this to LndConnectionString class - public string Tls { get; set; } public string Macaroon { get; set; } + public string Tls { get; set; } // public Uri UriWithCreds @@ -44,6 +44,23 @@ namespace BTCPayServer.Payments.Lightning return UriWithCreds.AbsoluteUri; } + public string ToFullEditString() + { + var dict = new Dictionary(); + if (!String.IsNullOrEmpty(Macaroon)) + dict.Add("macaroon", Macaroon); + if (!String.IsNullOrEmpty(Tls)) + dict.Add("tls", Tls); + + if (dict.Count > 0) + { + var qs = dict.Select(a => $"{a.Key}={a.Value}"); + return UriWithCreds.AbsoluteUri + "?" + String.Join("&", qs); +} + else + return UriWithCreds.AbsoluteUri; + } + // public static bool TryParse(string str, out LightningConnectionString connectionString) { diff --git a/BTCPayServer/Payments/Lightning/LightningSupportedPaymentMethod.cs b/BTCPayServer/Payments/Lightning/LightningSupportedPaymentMethod.cs index e1b100e9e..3debf76e9 100644 --- a/BTCPayServer/Payments/Lightning/LightningSupportedPaymentMethod.cs +++ b/BTCPayServer/Payments/Lightning/LightningSupportedPaymentMethod.cs @@ -8,9 +8,21 @@ namespace BTCPayServer.Payments.Lightning public class LightningSupportedPaymentMethod : ISupportedPaymentMethod { public string CryptoCode { get; set; } + public PaymentMethodId PaymentId => new PaymentMethodId(CryptoCode, PaymentTypes.LightningLike); + [Obsolete("Use Get/SetLightningUrl")] public string LightningChargeUrl { get; set; } + [Obsolete("Use Get/SetLightningUrl")] + public string Username { get; set; } + [Obsolete("Use Get/SetLightningUrl")] + public string Password { get; set; } + + [Obsolete("Use Get/SetLightningUrl")] + public string Macaroon { get; set; } + [Obsolete("Use Get/SetLightningUrl")] + public string Tls { get; set; } + public LightningConnectionString GetLightningUrl() { #pragma warning disable CS0618 // Type or member is obsolete @@ -19,6 +31,8 @@ namespace BTCPayServer.Payments.Lightning { throw new FormatException(error); } + connectionString.Macaroon = Macaroon; + connectionString.Tls = Tls; return connectionString; #pragma warning restore CS0618 // Type or member is obsolete } @@ -31,14 +45,11 @@ namespace BTCPayServer.Payments.Lightning #pragma warning disable CS0618 // Type or member is obsolete Username = connectionString.Username; Password = connectionString.Password; + Macaroon = connectionString.Macaroon; + Tls = connectionString.Tls; + LightningChargeUrl = connectionString.BaseUri.AbsoluteUri; #pragma warning restore CS0618 // Type or member is obsolete } - - [Obsolete("Use Get/SetLightningUrl")] - public string Username { get; set; } - [Obsolete("Use Get/SetLightningUrl")] - public string Password { get; set; } - public PaymentMethodId PaymentId => new PaymentMethodId(CryptoCode, PaymentTypes.LightningLike); } } From 9e698a8004bcc47c2ce784b4502495848b853a8b Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sat, 23 Jun 2018 23:37:58 -0500 Subject: [PATCH 45/45] Commenting few tricky lines of code --- BTCPayServer/Payments/Lightning/LightningConnectionString.cs | 2 +- .../Payments/Lightning/LightningSupportedPaymentMethod.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs index 559ed488f..61cb6928d 100644 --- a/BTCPayServer/Payments/Lightning/LightningConnectionString.cs +++ b/BTCPayServer/Payments/Lightning/LightningConnectionString.cs @@ -20,7 +20,7 @@ namespace BTCPayServer.Payments.Lightning public string Username { get; set; } public string Password { get; set; } - public Uri BaseUri { get; set; } // has no user and password + public Uri BaseUri { get; set; } // has no user and password or query string public LightningConnectionType ConnectionType { get; private set; } diff --git a/BTCPayServer/Payments/Lightning/LightningSupportedPaymentMethod.cs b/BTCPayServer/Payments/Lightning/LightningSupportedPaymentMethod.cs index 3debf76e9..71b90c645 100644 --- a/BTCPayServer/Payments/Lightning/LightningSupportedPaymentMethod.cs +++ b/BTCPayServer/Payments/Lightning/LightningSupportedPaymentMethod.cs @@ -8,6 +8,7 @@ namespace BTCPayServer.Payments.Lightning public class LightningSupportedPaymentMethod : ISupportedPaymentMethod { public string CryptoCode { get; set; } + // This property MUST be after CryptoCode or else JSON serialization fails public PaymentMethodId PaymentId => new PaymentMethodId(CryptoCode, PaymentTypes.LightningLike); [Obsolete("Use Get/SetLightningUrl")]