From 721c8bffe02dd2a8651b7a4315add22231ac42a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20A=2EP?=
<53834183+Jossec101@users.noreply.github.com>
Date: Wed, 26 Jul 2023 20:17:26 +0200
Subject: [PATCH 1/4] refactor(Channels.razor): remove unused import Polly
style(Channels.razor): change variable case from _IsUserNodeManager to
_isUserNodeManager for consistency refactor(Channels.razor): change
ChannelsColumnName enum values to uppercase for better readability
refactor(Channels.razor): remove unnecessary type casting in SelectedValue
attributes refactor(Channels.razor): change nullable types to non-nullable
and vice versa according to their usage
refactor(Channels.razor): apply null safety checks and improve variable naming for readability
1. refactor: rename variables to follow underscore prefix naming convention for private fields
2. refactor: add null safety checks before accessing nullable properties or methods
3. refactor: change variable names to uppercase for constants to follow naming conventions
4. refactor: remove unused exception variable in catch block
5. refactor: add explicit type to remoteBalance variable for clarity
6. refactor: add null checks before accessing nullable properties or methods
7. refactor: add null check before accessing _currentLiquidityRule in validation methods
8. refactor: change method parameters to nullable types in filter methods
9. refactor: improve logic in CheckDisableCloseChannelButton method for readability
---
src/Pages/Channels.razor | 142 +++++++++++++++++++++------------------
1 file changed, 77 insertions(+), 65 deletions(-)
diff --git a/src/Pages/Channels.razor b/src/Pages/Channels.razor
index a735a86a..9c66159b 100644
--- a/src/Pages/Channels.razor
+++ b/src/Pages/Channels.razor
@@ -2,7 +2,6 @@
@using System.Security.Claims
@using Humanizer
@using NBitcoin
-@using Polly
@using Channel = FundsManager.Data.Models.Channel
@attribute [Authorize(Roles = "NodeManager")]
Active Channels
@@ -34,7 +33,7 @@
- @if (_IsUserNodeManager)
+ @if (_isUserNodeManager)
{
Manage
Close
@@ -46,9 +45,9 @@
-
+
-
-
+
-
+
All
@foreach (var node in _nodes)
{
@@ -84,7 +83,7 @@
-
+
All
@@ -96,7 +95,7 @@
@context.Status.ToString("G")
-
+
All
@@ -117,7 +116,7 @@
}
-
+
@StringHelper.TruncateHeadAndTail(context.FundingTx, 5):@context.FundingTxOutputIndex
-
+
@{
var btcAmount = new Money(context.SatsAmount, MoneyUnit.Satoshi).ToUnit(MoneyUnit.BTC);
@@ -134,8 +133,8 @@
}
-
-
+
+
@if (!string.IsNullOrEmpty(context.BtcCloseAddress))
@@ -148,7 +147,7 @@
-
+
@{
var balance = Task.Run(() => GetPercentageBalance(context)).Result;
@@ -170,9 +169,9 @@
-
-
-
+
+
+
@context.ChanId
@@ -181,7 +180,7 @@
-
+
@@ -340,15 +339,15 @@
private List? _channels = new List();
private Channel? _selectedChannel;
private bool _modalVisible;
- private bool _IsUserNodeManager = false;
- private DataGrid _channelsDataGridRef;
+ private bool _isUserNodeManager;
+ private DataGrid? _channelsDataGridRef;
private Modal? _channelLiquidityModal;
private List _availableWallets = new List();
private LiquidityRule? _currentLiquidityRule = new LiquidityRule();
- private Validations _channelManagementValidationsRef;
+ private Validations? _channelManagementValidationsRef;
private string _statusFilter = "Open";
- private int _sourceNodeIdFilter = 0;
- private int _destinationNodeIdFilter = 0;
+ private int _sourceNodeIdFilter;
+ private int _destinationNodeIdFilter;
private List _nodes = new List();
private List _wallets = new List();
private int _filterWalletId;
@@ -361,27 +360,27 @@
private decimal _btcPrice;
- private ColumnLayout ChannelsColumnLayout;
- private Dictionary ChannelsColumns = new();
- private bool columnsLoaded;
+ private ColumnLayout? _channelsColumnLayout;
+ private Dictionary _channelsColumns = new();
+ private bool _columnsLoaded;
// This dictionary is used to store the balance of each channel, key is the channel id, value is a tuple with the node id as local in the pair, local balance, remote balance
private Dictionary _channelsBalance = new();
private DateTimeOffset _lastBalanceUpdate = DateTimeOffset.Now;
public abstract class ChannelsColumnName
{
- public static readonly ColumnDefault SourceNode = new("Source Node");
- public static readonly ColumnDefault DestinationNode = new("Destination Node");
- public static readonly ColumnDefault Status = new("Status");
- public static readonly ColumnDefault OpenedWith = new("Opened With");
- public static readonly ColumnDefault Outpoint = new("Outpoint");
- public static readonly ColumnDefault Capacity = new("Capacity (BTC)");
- public static readonly ColumnDefault Private = new("Private");
- public static readonly ColumnDefault CloseAddress = new("Close Address");
- public static readonly ColumnDefault ChannelBalance = new("Channel Balance");
- public static readonly ColumnDefault CreationDate = new("Creation Date");
- public static readonly ColumnDefault UpdateDate = new("Update Date");
- public static readonly ColumnDefault ChannelId = new("Channel Id");
+ public static readonly ColumnDefault SOURCE_NODE = new("Source Node");
+ public static readonly ColumnDefault DESTINATION_NODE = new("Destination Node");
+ public static readonly ColumnDefault STATUS = new("Status");
+ public static readonly ColumnDefault OPENED_WITH = new("Opened With");
+ public static readonly ColumnDefault OUTPOINT = new("Outpoint");
+ public static readonly ColumnDefault CAPACITY = new("Capacity (BTC)");
+ public static readonly ColumnDefault PRIVATE = new("Private");
+ public static readonly ColumnDefault CLOSE_ADDRESS = new("Close Address");
+ public static readonly ColumnDefault CHANNEL_BALANCE = new("Channel Balance");
+ public static readonly ColumnDefault CREATION_DATE = new("Creation Date");
+ public static readonly ColumnDefault UPDATE_DATE = new("Update Date");
+ public static readonly ColumnDefault CHANNEL_ID = new("Channel Id");
}
protected override async Task OnInitializedAsync()
@@ -396,7 +395,7 @@
await FetchData();
if (ClaimsPrincipal != null && ClaimsPrincipal.IsInRole(ApplicationUserRole.NodeManager.ToString()))
{
- _IsUserNodeManager = true;
+ _isUserNodeManager = true;
}
}
}
@@ -404,16 +403,19 @@
private async Task FetchData()
{
_availableWallets = await WalletRepository.GetAvailableWallets();
- _channels = await ChannelRepository.GetAllManagedByUserNodes(LoggedUser.Id);
+ if (LoggedUser?.Id != null)
+ {
+ _channels = await ChannelRepository.GetAllManagedByUserNodes(LoggedUser.Id);
+ }
_nodes = await NodeRepository.GetAll();
_wallets = await WalletRepository.GetAll();
- _channelsDataGridRef.FilterData();
+ _channelsDataGridRef?.FilterData();
_channelsBalance = await LightningService.GetChannelsBalance();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
- if (!firstRender && !columnsLoaded)
+ if (!firstRender && !_columnsLoaded)
{
await LoadColumnLayout();
}
@@ -421,19 +423,19 @@
private async Task LoadColumnLayout()
{
- ChannelsColumns = await LocalStorageService.LoadStorage(nameof(ChannelsColumnName), ColumnHelpers.GetColumnsDictionary());
- columnsLoaded = true;
+ _channelsColumns = await LocalStorageService.LoadStorage(nameof(ChannelsColumnName), ColumnHelpers.GetColumnsDictionary());
+ _columnsLoaded = true;
StateHasChanged();
}
- private async Task ShowConfirmedClose(Channel channel, bool forceClose = false)
+ private async Task ShowConfirmedClose(Channel? channel, bool forceClose = false)
{
if (await MessageService.Confirm($"Are you sure you want to {(forceClose ? "force " : string.Empty)}close this channel?", "Confirmation"))
{
if (channel != null)
{
- channel.DestinationNode = await NodeRepository.GetById(channel.DestinationNodeId);
- channel.SourceNode = await NodeRepository.GetById(channel.SourceNodeId);
+ channel.DestinationNode = await NodeRepository.GetById(channel.DestinationNodeId) ?? throw new InvalidOperationException();
+ channel.SourceNode = await NodeRepository.GetById(channel.SourceNodeId) ?? throw new InvalidOperationException();
var result = await ChannelRepository.SafeRemove(channel, forceClose);
if (!result.Item1)
@@ -492,7 +494,7 @@
var capacity = values.Item2 + values.Item3;
// Initialize the remote balance
- var remoteBalance = 0L;
+ long remoteBalance;
// Check if the source node ID of the channel is the same as the managed node ID
// or if the source node is not managed
@@ -517,7 +519,7 @@
return Convert.ToInt32(result);
}
- catch (Exception e)
+ catch (Exception)
{
ToastService.ShowError($"Channel balance for channel id:{channel.Id} could not be retrieved");
return -1;
@@ -526,29 +528,32 @@
private async Task OnSelectedWalletChanged(int arg)
{
- _currentLiquidityRule.WalletId = arg;
+ if (_currentLiquidityRule != null) _currentLiquidityRule.WalletId = arg;
}
private async Task CloseChannelManagementModal()
{
- await _channelLiquidityModal?.Close(CloseReason.UserClosing);
+ if (_channelLiquidityModal != null) await _channelLiquidityModal.Close(CloseReason.UserClosing);
await ClearManagementModal();
await FetchData();
}
private async Task SaveAndCloseChannelManagementModal()
{
- if (await _channelManagementValidationsRef.ValidateAll())
+ if (_channelManagementValidationsRef != null && await _channelManagementValidationsRef.ValidateAll())
{
//Save the channel
- var updateResult = ChannelRepository.Update(_selectedChannel);
- if (!updateResult.Item1)
- {
- ToastService.ShowError("Something went wrong");
- }
- else
+ if (_selectedChannel != null)
{
- ToastService.ShowSuccess("Channel updated successfully");
+ var updateResult = ChannelRepository.Update(_selectedChannel);
+ if (!updateResult.Item1)
+ {
+ ToastService.ShowError("Something went wrong");
+ }
+ else
+ {
+ ToastService.ShowSuccess("Channel updated successfully");
+ }
}
//Save the liquidity rule if the liquidity rule id is below or equal zero
@@ -614,7 +619,7 @@
NodeId = node.Id
};
- await _channelLiquidityModal?.Show();
+ if (_channelLiquidityModal != null) await _channelLiquidityModal.Show();
}
private async Task OnEnableLiquidityMgnmtChanged(bool enabledLiquidityMgnmt)
@@ -647,6 +652,7 @@
private void ValidateTargetBalance(ValidatorEventArgs arg1)
{
+ if(_currentLiquidityRule == null) return;
//Default validation status
arg1.Status = ValidationStatus.Success;
@@ -674,6 +680,7 @@
private void ValidateRemoteBalance(ValidatorEventArgs arg1)
{
+ if(_currentLiquidityRule == null) return;
//Default validation status
arg1.Status = ValidationStatus.Success;
@@ -710,6 +717,7 @@
private void ValidateLocalBalance(ValidatorEventArgs arg1)
{
+ if (_currentLiquidityRule == null) return;
//Default validation status
arg1.Status = ValidationStatus.Success;
//If the minimum remote balance is 0 this cannot be 0
@@ -743,7 +751,7 @@
}
}
- private bool OnStatusFilter(object itemValue, object searchValue)
+ private bool OnStatusFilter(object? itemValue, object? searchValue)
{
//If searchValue is null, we set it to the filter initial value in the field
searchValue ??= _statusFilter;
@@ -763,7 +771,7 @@
return searchValue == null || (int) searchValue == 0 || (int) itemValue == (int) searchValue;
}
- private bool OnSourceNodeIdFilter(object itemValue, object searchValue)
+ private bool OnSourceNodeIdFilter(object? itemValue, object? searchValue)
{
//If searchValue is null, we set it to the filter initial value in the field
searchValue ??= _sourceNodeIdFilter;
@@ -775,7 +783,7 @@
return true;
}
- private bool OnDestinationNodeIdFilter(object itemValue, object searchValue)
+ private bool OnDestinationNodeIdFilter(object? itemValue, object? searchValue)
{
//If searchValue is null, we set it to the filter initial value in the field
searchValue ??= _destinationNodeIdFilter;
@@ -807,7 +815,11 @@
private bool CheckDisableCloseChannelButton(Channel channel)
{
var lastRequest = channel.ChannelOperationRequests.LastOrDefault();
- if (lastRequest == null && channel.CreatedByNodeGuard == false) return false;
+
+ // If the channel is not created by the node guard, we dont disable the button
+ if (lastRequest == null || channel.CreatedByNodeGuard == false) return false;
+
+ // If the channel is created by the node guard, we disable the button if the channel is closed or if the last request is a close request and is confirmed or is pending confirmation
return channel.Status == Channel.ChannelStatus.Closed || (lastRequest.RequestType == OperationRequestType.Close
&& lastRequest.Status == ChannelOperationRequestStatus.OnChainConfirmed
|| lastRequest.Status == ChannelOperationRequestStatus.OnChainConfirmationPending);
@@ -820,11 +832,11 @@
private bool IsColumnVisible(ColumnDefault column)
{
- if (ChannelsColumnLayout == null)
+ if (_channelsColumnLayout == null)
{
return true;
}
- return ChannelsColumnLayout.IsColumnVisible(column);
+ return _channelsColumnLayout.IsColumnVisible(column);
}
}
\ No newline at end of file
From e960dd0d359fe608e20bb0aa2a6bf3c8bd740347 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20A=2EP?=
<53834183+Jossec101@users.noreply.github.com>
Date: Wed, 26 Jul 2023 20:35:38 +0200
Subject: [PATCH 2/4] feat(Channels.razor): add default LiquidityRule when none
exists for selected channel
This change ensures that a default LiquidityRule is created when none exists for the selected channel. This is done to prevent potential null reference exceptions and to provide a sensible default for the channel's liquidity management.
---
src/Pages/Channels.razor | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/Pages/Channels.razor b/src/Pages/Channels.razor
index 9c66159b..f0ff1765 100644
--- a/src/Pages/Channels.razor
+++ b/src/Pages/Channels.razor
@@ -610,14 +610,14 @@
var node = string.IsNullOrEmpty(sourceNode.ChannelAdminMacaroon) ? destinationNode : sourceNode;
//If there is a liquidity rule for this channel, we load it, the first one
- _currentLiquidityRule = _selectedChannel?.LiquidityRules.FirstOrDefault() ?? new LiquidityRule
+ _currentLiquidityRule = _selectedChannel?.LiquidityRules.FirstOrDefault()?? new LiquidityRule
{
MinimumLocalBalance = 20,
MinimumRemoteBalance = 80,
RebalanceTarget = 50,
ChannelId = channel.Id,
NodeId = node.Id
- };
+ };;
if (_channelLiquidityModal != null) await _channelLiquidityModal.Show();
}
@@ -634,7 +634,15 @@
}
else
{
- _currentLiquidityRule = _selectedChannel.LiquidityRules.FirstOrDefault();
+ var node = string.IsNullOrEmpty(_selectedChannel.SourceNode.ChannelAdminMacaroon) ? _selectedChannel.DestinationNode : _selectedChannel.SourceNode;
+ _currentLiquidityRule = _selectedChannel.LiquidityRules.FirstOrDefault() ?? new LiquidityRule
+ {
+ MinimumLocalBalance = 20,
+ MinimumRemoteBalance = 80,
+ RebalanceTarget = 50,
+ ChannelId = _selectedChannel.Id,
+ NodeId = node.Id
+ };
}
var updateResult = ChannelRepository.Update(_selectedChannel);
From 7742494d0647ae9dfc9ef6b4a56ae065abcf7216 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20A=2EP?=
<53834183+Jossec101@users.noreply.github.com>
Date: Thu, 27 Jul 2023 12:24:19 +0200
Subject: [PATCH 3/4] Update src/Pages/Channels.razor
Co-authored-by: Rodrigo <39995243+RodriFS@users.noreply.github.com>
---
src/Pages/Channels.razor | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Pages/Channels.razor b/src/Pages/Channels.razor
index f0ff1765..9088d840 100644
--- a/src/Pages/Channels.razor
+++ b/src/Pages/Channels.razor
@@ -617,7 +617,7 @@
RebalanceTarget = 50,
ChannelId = channel.Id,
NodeId = node.Id
- };;
+ };
if (_channelLiquidityModal != null) await _channelLiquidityModal.Show();
}
From 05e434b7c5509ce2ed45c2ce5dca67f7cc3d05cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20A=2EP?=
<53834183+Jossec101@users.noreply.github.com>
Date: Thu, 27 Jul 2023 12:24:27 +0200
Subject: [PATCH 4/4] Update src/Pages/Channels.razor
Co-authored-by: Rodrigo <39995243+RodriFS@users.noreply.github.com>
---
src/Pages/Channels.razor | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Pages/Channels.razor b/src/Pages/Channels.razor
index 9088d840..a15f578c 100644
--- a/src/Pages/Channels.razor
+++ b/src/Pages/Channels.razor
@@ -610,7 +610,7 @@
var node = string.IsNullOrEmpty(sourceNode.ChannelAdminMacaroon) ? destinationNode : sourceNode;
//If there is a liquidity rule for this channel, we load it, the first one
- _currentLiquidityRule = _selectedChannel?.LiquidityRules.FirstOrDefault()?? new LiquidityRule
+ _currentLiquidityRule = _selectedChannel?.LiquidityRules.FirstOrDefault() ?? new LiquidityRule
{
MinimumLocalBalance = 20,
MinimumRemoteBalance = 80,