Compare commits

...

2 Commits

Author SHA1 Message Date
Dennis Reimann
be1c922f90
Fix build 2022-10-17 13:49:32 +02:00
Kukks
878cbed0d3
Better Channel Management APIs 2022-10-17 13:49:32 +02:00
9 changed files with 63 additions and 27 deletions

View File

@ -119,7 +119,7 @@ namespace BTCPayServer.Lightning.CLightning
return peers;
}
public Task FundChannelAsync(OpenChannelRequest openChannelRequest, CancellationToken cancellation)
public Task<FundChannelResponse> FundChannelAsync(OpenChannelRequest openChannelRequest, CancellationToken cancellation)
{
OpenChannelRequest.AssertIsSane(openChannelRequest);
List<object> parameters = new List<object>();
@ -127,7 +127,31 @@ namespace BTCPayServer.Lightning.CLightning
parameters.Add(openChannelRequest.ChannelAmount.Satoshi);
if (openChannelRequest.FeeRate != null)
parameters.Add($"{openChannelRequest.FeeRate.FeePerK.Satoshi * 4}perkw");
return SendCommandAsync<object>("fundchannel", parameters.ToArray(), true, cancellation: cancellation);
else
{
parameters.Add("normal");
}
if (openChannelRequest.Private != null)
{
parameters.Add(openChannelRequest.Private.ToString().ToLowerInvariant());
}
return SendCommandAsync<FundChannelResponse>("fundchannel", parameters.ToArray(), true, cancellation: cancellation);
}
public class FundChannelResponse
{
[JsonProperty("tx")]
public string Transaction { get; set; }
[JsonProperty("txid")]
public string TransactionId { get; set; }
[JsonProperty("outnum")]
public string FundingOutputIndex { get; set; }
[JsonProperty("channel_id")]
public string ChannelId { get; set; }
[JsonProperty("close_to")]
public string CloseToScriptPubKey { get; set; }
}
public Task ConnectAsync(NodeInfo nodeInfo, CancellationToken cancellation = default)
@ -398,6 +422,7 @@ namespace BTCPayServer.Lightning.CLightning
{
channels.Add(new LightningChannel()
{
Id = channel.ShortChannelId.ToString(),
RemoteNode = new PubKey(peer.Id),
IsPublic = !channel.Private,
LocalBalance = channel.ToUs,
@ -486,10 +511,11 @@ namespace BTCPayServer.Lightning.CLightning
async Task<OpenChannelResponse> ILightningClient.OpenChannel(OpenChannelRequest openChannelRequest, CancellationToken cancellation)
{
retry:
try
{
await FundChannelAsync(openChannelRequest, cancellation);
}
FundChannelResponse response;
try
{
response = await FundChannelAsync(openChannelRequest, cancellation);
}
catch (LightningRPCException ex) when (ex.Code == CLightningErrorCode.STILL_SYNCING_BITCOIN)
{
await Task.Delay(1000, cancellation);
@ -522,7 +548,10 @@ retry:
{
return new OpenChannelResponse(OpenChannelResult.AlreadyExists);
}
return new OpenChannelResponse(OpenChannelResult.Ok);
return new OpenChannelResponse(OpenChannelResult.Ok)
{
ChannelId = response.ChannelId
};
}
async Task<BitcoinAddress> ILightningClient.GetDepositAddress(CancellationToken cancellation)

View File

@ -4,6 +4,7 @@ namespace BTCPayServer.Lightning
{
public class LightningChannel
{
public string Id { get; set; }
public PubKey RemoteNode { get; set; }
public bool IsPublic { get; set; }
public bool IsActive { get; set; }

View File

@ -19,6 +19,8 @@ namespace BTCPayServer.Lightning
{
get; set;
}
public bool? Private { get; set; }
public static void AssertIsSane(OpenChannelRequest openChannelRequest)
{
if (openChannelRequest == null)

View File

@ -19,5 +19,7 @@ namespace BTCPayServer.Lightning
{
get; set;
}
public string ChannelId { get; set; }
}
}

View File

@ -73,17 +73,19 @@ namespace BTCPayServer.Lightning.Eclair
}, cts);
}
public async Task<string> Open(PubKey nodeId, long fundingSatoshis, int? pushMsat = null,
long? fundingFeerateSatByte = null, ChannelFlags? channelFlags = null,
public async Task<string> Open(PubKey nodeId, long fundingSatoshis, string channelType = null,int? pushMsat = null,
long? fundingFeerateSatByte = null, bool? announceChannel = null, int? openTimeoutSeconds = null,
CancellationToken cts = default)
{
return await SendCommandAsync<OpenRequest, string>("open", new OpenRequest()
{
NodeId = nodeId.ToString(),
FundingSatoshis = fundingSatoshis,
ChannelFlags = channelFlags,
AnnounceChannel = announceChannel,
ChannelType = channelType,
PushMsat = pushMsat,
FundingFeerateSatByte = fundingFeerateSatByte
FundingFeerateSatByte = fundingFeerateSatByte,
OpenTimeoutSeconds = openTimeoutSeconds
}, cts);
}

View File

@ -330,13 +330,15 @@ namespace BTCPayServer.Lightning.Eclair
try
{
var result = await _eclairClient.Open(openChannelRequest.NodeInfo.NodeId,
openChannelRequest.ChannelAmount.Satoshi
, null,
Convert.ToInt64(openChannelRequest.FeeRate.SatoshiPerByte), null, cancellation);
openChannelRequest.ChannelAmount.Satoshi, null, null,
(openChannelRequest.FeeRate is null
? (long?)null
: Convert.ToInt64(openChannelRequest.FeeRate.SatoshiPerByte)), openChannelRequest.Private, null,
cancellation);
if (result.Contains("created channel", StringComparison.OrdinalIgnoreCase))
{
var channelId = result.Replace("created channel", "").Trim();
string channelId = result.Replace("created channel", "").Trim();
var channel = await _eclairClient.Channel(channelId, cancellation);
switch (channel.State)
{
@ -346,7 +348,10 @@ namespace BTCPayServer.Lightning.Eclair
case "WAIT_FOR_FUNDING_SIGNED":
case "WAIT_FOR_FUNDING_LOCKED":
case "WAIT_FOR_FUNDING_CONFIRMED":
return new OpenChannelResponse(OpenChannelResult.NeedMoreConf);
return new OpenChannelResponse(OpenChannelResult.NeedMoreConf)
{
ChannelId = channelId
};
}
}

View File

@ -1,8 +0,0 @@
namespace BTCPayServer.Lightning.Eclair.Models
{
public enum ChannelFlags
{
Private = 0,
Public = 1
}
}

View File

@ -6,6 +6,8 @@ namespace BTCPayServer.Lightning.Eclair.Models
public long FundingSatoshis { get; set; }
public long? PushMsat { get; set; }
public long? FundingFeerateSatByte { get; set; }
public ChannelFlags? ChannelFlags { get; set; }
public string ChannelType { get; set; }
public bool? AnnounceChannel { get; set; }
public int? OpenTimeoutSeconds { get; set; }
}
}

View File

@ -681,12 +681,13 @@ retry:
{
Local_funding_amount = openChannelRequest.ChannelAmount.Satoshi.ToString(CultureInfo.InvariantCulture),
Node_pubkey_string = openChannelRequest.NodeInfo.NodeId.ToString(),
Private = openChannelRequest.Private
};
if (openChannelRequest.FeeRate != null)
{
req.Sat_per_byte = ((int)openChannelRequest.FeeRate.SatoshiPerByte).ToString();
}
var result = await this.SwaggerClient.OpenChannelSyncAsync(req, cancellation);
await SwaggerClient.OpenChannelSyncAsync(req, cancellation);
return new OpenChannelResponse(OpenChannelResult.Ok);
}
catch (SwaggerException ex) when