diff --git a/src/Helpers/LowerCaseJsonFormatter.cs b/src/Helpers/LowerCaseJsonFormatter.cs new file mode 100644 index 00000000..41a41fa1 --- /dev/null +++ b/src/Helpers/LowerCaseJsonFormatter.cs @@ -0,0 +1,27 @@ +using Blazorise; +using Serilog.Events; +using Serilog.Formatting; +using Serilog.Formatting.Json; + +namespace NodeGuard.Helpers; + +/// +/// Custom formatter to lowercase the JSON output +/// +public class LowerCaseJsonFormatter : ITextFormatter +{ + private readonly JsonFormatter _formatter; + + public LowerCaseJsonFormatter() + { + _formatter = new JsonFormatter(); + } + + public void Format(LogEvent logEvent, TextWriter output) + { + using var sw = new StringWriter(); + _formatter.Format(logEvent, sw); + var json = sw.ToString().ToLower(); + output.WriteLine(json); + } +} diff --git a/src/Jobs/NodeChannelSubscribeJob.cs b/src/Jobs/NodeChannelSubscribeJob.cs index 24995818..98b82ff4 100644 --- a/src/Jobs/NodeChannelSubscribeJob.cs +++ b/src/Jobs/NodeChannelSubscribeJob.cs @@ -87,11 +87,18 @@ public async Task Execute(IJobExecutionContext context) _logger.LogError(e, "Error reading and update event of node {NodeId}", nodeId); throw new JobExecutionException(e, true); } + + } + + } catch (Exception e) { _logger.LogError(e, "Error while subscribing for the channel updates of node {NodeId}", nodeId); + //Sleep to avoid massive requests + await Task.Delay(1000); + throw new JobExecutionException(e, true); } diff --git a/src/Jobs/ProcessNodeChannelAcceptorJob.cs b/src/Jobs/ProcessNodeChannelAcceptorJob.cs index 89a33a83..413bcb5c 100644 --- a/src/Jobs/ProcessNodeChannelAcceptorJob.cs +++ b/src/Jobs/ProcessNodeChannelAcceptorJob.cs @@ -241,7 +241,12 @@ await AcceptChannelOpeningRequestWithUpfrontShutdown(_nBXplorerService, catch (Exception e) { _logger.LogError(e, "Error on {JobName}", nameof(ProcessNodeChannelAcceptorJob)); + + //Sleep to avoid massive requests + await Task.Delay(1000); + throw new JobExecutionException(e, true); + } } } \ No newline at end of file diff --git a/src/Program.cs b/src/Program.cs index 58d7d7c9..61e9729f 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -55,12 +55,14 @@ public static void Main(string[] args) var builder = WebApplication.CreateBuilder(args); + var jsonFormatter = new LowerCaseJsonFormatter(); + Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) .MinimumLevel.Override("System", LogEventLevel.Warning) .Enrich.With(new DatadogLogEnricher()) - .WriteTo.Console(new JsonFormatter()) + .WriteTo.Console(jsonFormatter) .CreateLogger(); builder.Logging.ClearProviders(); diff --git a/src/Proto/nodeguard.proto b/src/Proto/nodeguard.proto index db0d3c52..83a14bf8 100644 --- a/src/Proto/nodeguard.proto +++ b/src/Proto/nodeguard.proto @@ -63,6 +63,11 @@ service NodeGuardService { Gets the status for the provided withdrawals request ids */ rpc GetWithdrawalsRequestStatus(GetWithdrawalsRequestStatusRequest) returns (GetWithdrawalsRequestStatusResponse); + + /* + Gets a channel by id + */ + rpc GetChannel(GetChannelRequest) returns (GetChannelResponse); } message GetLiquidityRulesRequest { @@ -235,7 +240,7 @@ enum CHANNEL_OPERATION_STATUS { ONCHAIN_CONFIRMATION_PENDING = 5; ONCHAIN_CONFIRMED = 6; FAILED = 7; - FINALIZINGPSBT = 8; + FINALIZING_PSBT = 8; } enum CHANNEL_OPERATION_TYPE { @@ -330,3 +335,25 @@ message WithdrawalRequest { message GetWithdrawalsRequestStatusResponse { repeated WithdrawalRequest withdrawal_requests = 1; } + +message GetChannelRequest { + // Channel ID from NGs database + int32 channel_id = 1; +} + +enum CHANNEL_STATUS { + OPEN = 0; + CLOSED = 1; +} + +message GetChannelResponse { + string funding_tx = 1; + uint32 output_index = 2; + uint64 chan_id = 3; + int64 sats_amount = 4; + optional string btc_close_address = 5; + CHANNEL_STATUS status = 6; + bool created_by_nodeguard = 7; + bool is_automated_liquidity_enabled = 8; + bool is_private = 9; +} \ No newline at end of file diff --git a/src/Rpc/NodeGuardService.cs b/src/Rpc/NodeGuardService.cs index 92a0c0cb..001d5da0 100644 --- a/src/Rpc/NodeGuardService.cs +++ b/src/Rpc/NodeGuardService.cs @@ -6,12 +6,15 @@ using NodeGuard.Jobs; using NodeGuard.Services; using Grpc.Core; +using Microsoft.EntityFrameworkCore.Infrastructure; using NBitcoin; +using NBitcoin.RPC; using NBXplorer.DerivationStrategy; using NBXplorer.Models; using Nodeguard; using Quartz; using LiquidityRule = NodeGuard.Data.Models.LiquidityRule; +using Node = Nodeguard.Node; using Wallet = NodeGuard.Data.Models.Wallet; namespace NodeGuard.Rpc; @@ -44,6 +47,8 @@ Task GetNewWalletAddress(GetNewWalletAddressRequest Task GetAvailableUtxos(GetAvailableUtxosRequest request, ServerCallContext context); Task GetWithdrawalsRequestStatus(GetWithdrawalsRequestStatusRequest request, ServerCallContext context); + + Task GetChannel(GetChannelRequest request, ServerCallContext context); } /// @@ -610,12 +615,34 @@ public override async Task GetChannelOperati throw new RpcException(new Status(StatusCode.NotFound, "Channel operation request not found")); } + var status = channelOperationRequest.Status switch + { + ChannelOperationRequestStatus.Approved => CHANNEL_OPERATION_STATUS.Approved, + ChannelOperationRequestStatus.Cancelled => CHANNEL_OPERATION_STATUS.Cancelled, + ChannelOperationRequestStatus.Rejected => CHANNEL_OPERATION_STATUS.Rejected, + ChannelOperationRequestStatus.Pending => CHANNEL_OPERATION_STATUS.Pending, + ChannelOperationRequestStatus.PSBTSignaturesPending => CHANNEL_OPERATION_STATUS.PsbtSignaturesPending, + ChannelOperationRequestStatus.OnChainConfirmationPending => CHANNEL_OPERATION_STATUS + .OnchainConfirmationPending, + ChannelOperationRequestStatus.OnChainConfirmed => CHANNEL_OPERATION_STATUS.OnchainConfirmed, + ChannelOperationRequestStatus.Failed => CHANNEL_OPERATION_STATUS.Failed, + ChannelOperationRequestStatus.FinalizingPSBT => CHANNEL_OPERATION_STATUS.FinalizingPsbt, + _ => throw new ArgumentOutOfRangeException(nameof(channelOperationRequest.Status), channelOperationRequest.Status, "Unknown status") + }; + + var type = channelOperationRequest.RequestType switch + { + OperationRequestType.Open => CHANNEL_OPERATION_TYPE.OpenChannel, + OperationRequestType.Close => CHANNEL_OPERATION_TYPE.CloseChannel, + _ => throw new ArgumentOutOfRangeException(nameof(channelOperationRequest.RequestType), channelOperationRequest.RequestType, "Unknown type") + }; + var result = new GetChannelOperationRequestResponse { SatsAmount = channelOperationRequest.SatsAmount, Description = channelOperationRequest.Description, - Status = (CHANNEL_OPERATION_STATUS)((int)channelOperationRequest.Status - 1), - Type = (CHANNEL_OPERATION_TYPE)((int)channelOperationRequest.RequestType - 1), + Status = status, + Type = type, SourceNodeId = channelOperationRequest.SourceNodeId, Private = channelOperationRequest.IsChannelPrivate, JobId = channelOperationRequest.JobId @@ -859,4 +886,36 @@ public override async Task GetWithdrawalsRe } }; } + + public override async Task GetChannel(GetChannelRequest request, ServerCallContext context) + { + var channel = await _channelRepository.GetById(request.ChannelId); + if (channel == null) + { + throw new RpcException(new Status(StatusCode.NotFound, "Channel not found")); + } + + var status = channel.Status switch + { + Channel.ChannelStatus.Open => CHANNEL_STATUS.Open, + Channel.ChannelStatus.Closed => CHANNEL_STATUS.Closed, + _ => throw new ArgumentOutOfRangeException(nameof(channel.Status), channel.Status, "Unknown status") + }; + + var result = new GetChannelResponse() + { + FundingTx = channel.FundingTx, + OutputIndex = channel.FundingTxOutputIndex, + ChanId = channel.ChanId, + SatsAmount = channel.SatsAmount, + Status = status, + CreatedByNodeguard = channel.CreatedByNodeGuard, + IsAutomatedLiquidityEnabled = channel.IsAutomatedLiquidityEnabled, + IsPrivate = channel.IsPrivate, + }; + + result.BtcCloseAddress = channel.BtcCloseAddress != null ? channel.BtcCloseAddress : String.Empty; + + return result; + } } \ No newline at end of file