From 9539a593843c9f8bfa919f0d5de0b35e90bc4e0a Mon Sep 17 00:00:00 2001 From: Carsten Otto Date: Sat, 18 Dec 2021 01:10:31 +0100 Subject: [PATCH] add NodeDetailsService --- .../service/NodeDetailsService.java | 65 ++++++++++++++ .../lndmanagej/service/FeeServiceTest.java | 4 +- .../service/NodeDetailsServiceTest.java | 76 +++++++++++++++++ .../de/cotto/lndmanagej/model/FeeReport.java | 1 + .../cotto/lndmanagej/model/NodeDetails.java | 18 ++++ .../cotto/lndmanagej/model/FeeReportTest.java | 5 ++ .../lndmanagej/model/NodeDetailsTest.java | 73 ++++++++++++++++ .../model/ForceClosingChannelFixtures.java | 8 +- .../lndmanagej/model/NodeDetailsFixtures.java | 43 ++++++++++ .../controller/NodeControllerIT.java | 59 +++++-------- .../lndmanagej/controller/NodeController.java | 34 ++------ .../controller/dto/NodeDetailsDto.java | 44 ++++------ .../controller/NodeControllerTest.java | 84 ++----------------- .../controller/dto/NodeDetailsDtoTest.java | 38 +++++++++ 14 files changed, 374 insertions(+), 178 deletions(-) create mode 100644 backend/src/main/java/de/cotto/lndmanagej/service/NodeDetailsService.java create mode 100644 backend/src/test/java/de/cotto/lndmanagej/service/NodeDetailsServiceTest.java create mode 100644 model/src/main/java/de/cotto/lndmanagej/model/NodeDetails.java create mode 100644 model/src/test/java/de/cotto/lndmanagej/model/NodeDetailsTest.java create mode 100644 model/src/testFixtures/java/de/cotto/lndmanagej/model/NodeDetailsFixtures.java create mode 100644 web/src/test/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDtoTest.java diff --git a/backend/src/main/java/de/cotto/lndmanagej/service/NodeDetailsService.java b/backend/src/main/java/de/cotto/lndmanagej/service/NodeDetailsService.java new file mode 100644 index 00000000..f1dcf9d9 --- /dev/null +++ b/backend/src/main/java/de/cotto/lndmanagej/service/NodeDetailsService.java @@ -0,0 +1,65 @@ +package de.cotto.lndmanagej.service; + +import de.cotto.lndmanagej.model.BalanceInformation; +import de.cotto.lndmanagej.model.Channel; +import de.cotto.lndmanagej.model.ChannelId; +import de.cotto.lndmanagej.model.Node; +import de.cotto.lndmanagej.model.NodeDetails; +import de.cotto.lndmanagej.model.OnChainCosts; +import de.cotto.lndmanagej.model.Pubkey; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Set; + +@Component +public class NodeDetailsService { + private final ChannelService channelService; + private final NodeService nodeService; + private final OnChainCostService onChainCostService; + private final BalanceService balanceService; + private final FeeService feeService; + private final RebalanceService rebalanceService; + + public NodeDetailsService( + ChannelService channelService, + NodeService nodeService, + OnChainCostService onChainCostService, + BalanceService balanceService, + FeeService feeService, + RebalanceService rebalanceService + ) { + this.channelService = channelService; + this.nodeService = nodeService; + this.onChainCostService = onChainCostService; + this.balanceService = balanceService; + this.feeService = feeService; + this.rebalanceService = rebalanceService; + } + + public NodeDetails getDetails(Pubkey pubkey) { + Node node = nodeService.getNode(pubkey); + OnChainCosts onChainCosts = onChainCostService.getOnChainCostsForPeer(pubkey); + BalanceInformation balanceInformation = balanceService.getBalanceInformationForPeer(pubkey); + return new NodeDetails( + pubkey, + node.alias(), + getSortedChannelIds(channelService.getOpenChannelsWith(pubkey)), + getSortedChannelIds(channelService.getClosedChannelsWith(pubkey)), + getSortedChannelIds(channelService.getWaitingCloseChannelsWith(pubkey)), + getSortedChannelIds(channelService.getForceClosingChannelsWith(pubkey)), + onChainCosts, + balanceInformation, + node.online(), + feeService.getFeeReportForPeer(pubkey), + rebalanceService.getReportForPeer(pubkey) + ); + } + + private List getSortedChannelIds(Set channels) { + return channels.stream() + .map(Channel::getId) + .sorted() + .toList(); + } +} diff --git a/backend/src/test/java/de/cotto/lndmanagej/service/FeeServiceTest.java b/backend/src/test/java/de/cotto/lndmanagej/service/FeeServiceTest.java index b43020b9..5d0ee728 100644 --- a/backend/src/test/java/de/cotto/lndmanagej/service/FeeServiceTest.java +++ b/backend/src/test/java/de/cotto/lndmanagej/service/FeeServiceTest.java @@ -71,7 +71,7 @@ class FeeServiceTest { void getFeeReportForChannel_no_forward() { when(dao.getEventsWithOutgoingChannel(CHANNEL_ID)).thenReturn(List.of()); when(dao.getEventsWithIncomingChannel(CHANNEL_ID)).thenReturn(List.of()); - assertThat(feeService.getFeeReportForChannel(CHANNEL_ID)).isEqualTo(new FeeReport(Coins.NONE, Coins.NONE)); + assertThat(feeService.getFeeReportForChannel(CHANNEL_ID)).isEqualTo(FeeReport.EMPTY); } @Test @@ -93,6 +93,6 @@ class FeeServiceTest { @Test void getFeeReportForPeer_no_channel() { - assertThat(feeService.getFeeReportForPeer(PUBKEY)).isEqualTo(new FeeReport(Coins.NONE, Coins.NONE)); + assertThat(feeService.getFeeReportForPeer(PUBKEY)).isEqualTo(FeeReport.EMPTY); } } \ No newline at end of file diff --git a/backend/src/test/java/de/cotto/lndmanagej/service/NodeDetailsServiceTest.java b/backend/src/test/java/de/cotto/lndmanagej/service/NodeDetailsServiceTest.java new file mode 100644 index 00000000..a171a3ef --- /dev/null +++ b/backend/src/test/java/de/cotto/lndmanagej/service/NodeDetailsServiceTest.java @@ -0,0 +1,76 @@ +package de.cotto.lndmanagej.service; + +import de.cotto.lndmanagej.model.BalanceInformation; +import de.cotto.lndmanagej.model.FeeReport; +import de.cotto.lndmanagej.model.NodeDetailsFixtures; +import de.cotto.lndmanagej.model.OnChainCosts; +import de.cotto.lndmanagej.model.RebalanceReport; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Set; + +import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION_2; +import static de.cotto.lndmanagej.model.CoopClosedChannelFixtures.CLOSED_CHANNEL_2; +import static de.cotto.lndmanagej.model.FeeReportFixtures.FEE_REPORT; +import static de.cotto.lndmanagej.model.ForceClosingChannelFixtures.FORCE_CLOSING_CHANNEL_4; +import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; +import static de.cotto.lndmanagej.model.NodeFixtures.NODE; +import static de.cotto.lndmanagej.model.NodeFixtures.NODE_PEER; +import static de.cotto.lndmanagej.model.OnChainCostsFixtures.ON_CHAIN_COSTS; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; +import static de.cotto.lndmanagej.model.RebalanceReportFixtures.REBALANCE_REPORT; +import static de.cotto.lndmanagej.model.WaitingCloseChannelFixtures.WAITING_CLOSE_CHANNEL_TO_NODE_3; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class NodeDetailsServiceTest { + @InjectMocks + private NodeDetailsService nodeDetailsService; + + @Mock + private NodeService nodeService; + + @Mock + private OnChainCostService onChainCostService; + + @Mock + private BalanceService balanceService; + + @Mock + private ChannelService channelService; + + @Mock + private FeeService feeService; + + @Mock + private RebalanceService rebalanceService; + + @Test + void getDetails_no_channel() { + when(nodeService.getNode(PUBKEY)).thenReturn(NODE); + when(balanceService.getBalanceInformationForPeer(PUBKEY)).thenReturn(BalanceInformation.EMPTY); + when(onChainCostService.getOnChainCostsForPeer(PUBKEY)).thenReturn(OnChainCosts.NONE); + when(feeService.getFeeReportForPeer(PUBKEY)).thenReturn(FeeReport.EMPTY); + when(rebalanceService.getReportForPeer(PUBKEY)).thenReturn(RebalanceReport.EMPTY); + assertThat(nodeDetailsService.getDetails(PUBKEY)).isEqualTo(NodeDetailsFixtures.NODE_DETAILS_EMPTY); + } + + @Test + void getDetails() { + when(nodeService.getNode(PUBKEY)).thenReturn(NODE_PEER); + when(onChainCostService.getOnChainCostsForPeer(PUBKEY)).thenReturn(ON_CHAIN_COSTS); + when(balanceService.getBalanceInformationForPeer(PUBKEY)).thenReturn(BALANCE_INFORMATION_2); + when(channelService.getOpenChannelsWith(PUBKEY)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL)); + when(channelService.getClosedChannelsWith(PUBKEY)).thenReturn(Set.of(CLOSED_CHANNEL_2)); + when(channelService.getWaitingCloseChannelsWith(PUBKEY)).thenReturn(Set.of(WAITING_CLOSE_CHANNEL_TO_NODE_3)); + when(channelService.getForceClosingChannelsWith(PUBKEY)).thenReturn(Set.of(FORCE_CLOSING_CHANNEL_4)); + when(feeService.getFeeReportForPeer(PUBKEY)).thenReturn(FEE_REPORT); + when(rebalanceService.getReportForPeer(PUBKEY)).thenReturn(REBALANCE_REPORT); + assertThat(nodeDetailsService.getDetails(PUBKEY)).isEqualTo(NodeDetailsFixtures.NODE_DETAILS); + } +} \ No newline at end of file diff --git a/model/src/main/java/de/cotto/lndmanagej/model/FeeReport.java b/model/src/main/java/de/cotto/lndmanagej/model/FeeReport.java index 79d351b3..af20ca18 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/FeeReport.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/FeeReport.java @@ -1,4 +1,5 @@ package de.cotto.lndmanagej.model; public record FeeReport(Coins earned, Coins sourced) { + public static final FeeReport EMPTY = new FeeReport(Coins.NONE, Coins.NONE); } diff --git a/model/src/main/java/de/cotto/lndmanagej/model/NodeDetails.java b/model/src/main/java/de/cotto/lndmanagej/model/NodeDetails.java new file mode 100644 index 00000000..3407ca32 --- /dev/null +++ b/model/src/main/java/de/cotto/lndmanagej/model/NodeDetails.java @@ -0,0 +1,18 @@ +package de.cotto.lndmanagej.model; + +import java.util.List; + +public record NodeDetails( + Pubkey pubkey, + String alias, + List channels, + List closedChannels, + List waitingCloseChannels, + List pendingForceClosingChannels, + OnChainCosts onChainCosts, + BalanceInformation balanceInformation, + boolean online, + FeeReport feeReport, + RebalanceReport rebalanceReport +) { +} diff --git a/model/src/test/java/de/cotto/lndmanagej/model/FeeReportTest.java b/model/src/test/java/de/cotto/lndmanagej/model/FeeReportTest.java index c667c0a0..5d601e97 100644 --- a/model/src/test/java/de/cotto/lndmanagej/model/FeeReportTest.java +++ b/model/src/test/java/de/cotto/lndmanagej/model/FeeReportTest.java @@ -15,4 +15,9 @@ class FeeReportTest { void sourced() { assertThat(FEE_REPORT.sourced()).isEqualTo(Coins.ofMilliSatoshis(567)); } + + @Test + void empty() { + assertThat(FeeReport.EMPTY).isEqualTo(new FeeReport(Coins.NONE, Coins.NONE)); + } } \ No newline at end of file diff --git a/model/src/test/java/de/cotto/lndmanagej/model/NodeDetailsTest.java b/model/src/test/java/de/cotto/lndmanagej/model/NodeDetailsTest.java new file mode 100644 index 00000000..9ceef462 --- /dev/null +++ b/model/src/test/java/de/cotto/lndmanagej/model/NodeDetailsTest.java @@ -0,0 +1,73 @@ +package de.cotto.lndmanagej.model; + +import org.junit.jupiter.api.Test; + +import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION_2; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_4; +import static de.cotto.lndmanagej.model.FeeReportFixtures.FEE_REPORT; +import static de.cotto.lndmanagej.model.NodeDetailsFixtures.NODE_DETAILS; +import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS; +import static de.cotto.lndmanagej.model.OnChainCostsFixtures.ON_CHAIN_COSTS; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; +import static de.cotto.lndmanagej.model.RebalanceReportFixtures.REBALANCE_REPORT; +import static org.assertj.core.api.Assertions.assertThat; + +class NodeDetailsTest { + @Test + void pubkey() { + assertThat(NODE_DETAILS.pubkey()).isEqualTo(PUBKEY); + } + + @Test + void alias() { + assertThat(NODE_DETAILS.alias()).isEqualTo(ALIAS); + } + + @Test + void channels() { + assertThat(NODE_DETAILS.channels()).containsExactly(CHANNEL_ID); + } + + @Test + void closedChannels() { + assertThat(NODE_DETAILS.closedChannels()).containsExactly(CHANNEL_ID_2); + } + + @Test + void waitingCloseChannels() { + assertThat(NODE_DETAILS.waitingCloseChannels()).containsExactly(CHANNEL_ID_3); + } + + @Test + void pendingForceClosingChannels() { + assertThat(NODE_DETAILS.pendingForceClosingChannels()).containsExactly(CHANNEL_ID_4); + } + + @Test + void onChainCosts() { + assertThat(NODE_DETAILS.onChainCosts()).isEqualTo(ON_CHAIN_COSTS); + } + + @Test + void balanceInformation() { + assertThat(NODE_DETAILS.balanceInformation()).isEqualTo(BALANCE_INFORMATION_2); + } + + @Test + void online() { + assertThat(NODE_DETAILS.online()).isTrue(); + } + + @Test + void feeReport() { + assertThat(NODE_DETAILS.feeReport()).isEqualTo(FEE_REPORT); + } + + @Test + void rebalanceReport() { + assertThat(NODE_DETAILS.rebalanceReport()).isEqualTo(REBALANCE_REPORT); + } +} \ No newline at end of file diff --git a/model/src/testFixtures/java/de/cotto/lndmanagej/model/ForceClosingChannelFixtures.java b/model/src/testFixtures/java/de/cotto/lndmanagej/model/ForceClosingChannelFixtures.java index 1cd65f7d..60368bfa 100644 --- a/model/src/testFixtures/java/de/cotto/lndmanagej/model/ForceClosingChannelFixtures.java +++ b/model/src/testFixtures/java/de/cotto/lndmanagej/model/ForceClosingChannelFixtures.java @@ -6,9 +6,11 @@ import static de.cotto.lndmanagej.model.ChannelFixtures.CAPACITY; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_4; import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT; import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT_2; import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT_3; +import static de.cotto.lndmanagej.model.ChannelPointFixtures.TRANSACTION_HASH_2; import static de.cotto.lndmanagej.model.ChannelPointFixtures.TRANSACTION_HASH_3; import static de.cotto.lndmanagej.model.OpenInitiator.LOCAL; import static de.cotto.lndmanagej.model.OpenInitiator.REMOTE; @@ -36,11 +38,11 @@ public class ForceClosingChannelFixtures { HTLC_OUTPOINTS, REMOTE ); - public static final ForceClosingChannel FORCE_CLOSING_CHANNEL_3 = new ForceClosingChannel( - new ChannelCoreInformation(CHANNEL_ID_3, CHANNEL_POINT, CAPACITY), + public static final ForceClosingChannel FORCE_CLOSING_CHANNEL_4 = new ForceClosingChannel( + new ChannelCoreInformation(CHANNEL_ID_4, CHANNEL_POINT, CAPACITY), PUBKEY, PUBKEY_2, - TRANSACTION_HASH_3, + TRANSACTION_HASH_2, HTLC_OUTPOINTS, UNKNOWN ); diff --git a/model/src/testFixtures/java/de/cotto/lndmanagej/model/NodeDetailsFixtures.java b/model/src/testFixtures/java/de/cotto/lndmanagej/model/NodeDetailsFixtures.java new file mode 100644 index 00000000..961db7f4 --- /dev/null +++ b/model/src/testFixtures/java/de/cotto/lndmanagej/model/NodeDetailsFixtures.java @@ -0,0 +1,43 @@ +package de.cotto.lndmanagej.model; + +import java.util.List; + +import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION_2; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_4; +import static de.cotto.lndmanagej.model.FeeReportFixtures.FEE_REPORT; +import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS; +import static de.cotto.lndmanagej.model.OnChainCostsFixtures.ON_CHAIN_COSTS; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; +import static de.cotto.lndmanagej.model.RebalanceReportFixtures.REBALANCE_REPORT; + +public class NodeDetailsFixtures { + public static final NodeDetails NODE_DETAILS = new NodeDetails( + PUBKEY, + ALIAS, + List.of(CHANNEL_ID), + List.of(CHANNEL_ID_2), + List.of(CHANNEL_ID_3), + List.of(CHANNEL_ID_4), + ON_CHAIN_COSTS, + BALANCE_INFORMATION_2, + true, + FEE_REPORT, + REBALANCE_REPORT + ); + public static final NodeDetails NODE_DETAILS_EMPTY = new NodeDetails( + PUBKEY, + ALIAS, + List.of(), + List.of(), + List.of(), + List.of(), + OnChainCosts.NONE, + BalanceInformation.EMPTY, + false, + FeeReport.EMPTY, + RebalanceReport.EMPTY + ); +} diff --git a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/NodeControllerIT.java b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/NodeControllerIT.java index 32e3c55a..6ef0e661 100644 --- a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/NodeControllerIT.java +++ b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/NodeControllerIT.java @@ -3,13 +3,11 @@ package de.cotto.lndmanagej.controller; import de.cotto.lndmanagej.model.ChannelIdResolver; import de.cotto.lndmanagej.model.Coins; import de.cotto.lndmanagej.model.FeeReport; -import de.cotto.lndmanagej.model.Node; import de.cotto.lndmanagej.service.BalanceService; import de.cotto.lndmanagej.service.ChannelService; import de.cotto.lndmanagej.service.FeeService; +import de.cotto.lndmanagej.service.NodeDetailsService; import de.cotto.lndmanagej.service.NodeService; -import de.cotto.lndmanagej.service.OnChainCostService; -import de.cotto.lndmanagej.service.RebalanceService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -20,21 +18,17 @@ import java.util.List; import java.util.Set; import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION; -import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION_2; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; -import static de.cotto.lndmanagej.model.CoopClosedChannelFixtures.CLOSED_CHANNEL; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_4; import static de.cotto.lndmanagej.model.CoopClosedChannelFixtures.CLOSED_CHANNEL_3; -import static de.cotto.lndmanagej.model.ForceClosingChannelFixtures.FORCE_CLOSING_CHANNEL_2; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; -import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_2; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_3; +import static de.cotto.lndmanagej.model.NodeDetailsFixtures.NODE_DETAILS; +import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS; import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS_2; -import static de.cotto.lndmanagej.model.OnChainCostsFixtures.ON_CHAIN_COSTS; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; -import static de.cotto.lndmanagej.model.RebalanceReportFixtures.REBALANCE_REPORT; -import static de.cotto.lndmanagej.model.WaitingCloseChannelFixtures.WAITING_CLOSE_CHANNEL; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; import static org.hamcrest.core.Is.is; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -43,7 +37,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @WebMvcTest(controllers = NodeController.class) class NodeControllerIT { - private static final String NODE_PREFIX = "/api/node/" + PUBKEY_2; + private static final String NODE_PREFIX = "/api/node/" + PUBKEY; private static final FeeReport FEE_REPORT = new FeeReport(Coins.ofMilliSatoshis(1_234), Coins.ofMilliSatoshis(567)); @Autowired @@ -55,9 +49,6 @@ class NodeControllerIT { @MockBean private ChannelService channelService; - @MockBean - private OnChainCostService onChainCostService; - @MockBean @SuppressWarnings("unused") private ChannelIdResolver channelIdResolver; @@ -69,33 +60,25 @@ class NodeControllerIT { private FeeService feeService; @MockBean - private RebalanceService rebalanceService; + private NodeDetailsService nodeDetailsService; @Test void getAlias() throws Exception { - when(nodeService.getAlias(PUBKEY_2)).thenReturn(ALIAS_2); + when(nodeService.getAlias(PUBKEY)).thenReturn(ALIAS_2); mockMvc.perform(get(NODE_PREFIX + "/alias")) .andExpect(content().string(ALIAS_2)); } @Test void getDetails() throws Exception { - when(nodeService.getNode(PUBKEY_2)).thenReturn(new Node(PUBKEY_2, ALIAS_2, 0, true)); - when(channelService.getOpenChannelsWith(PUBKEY_2)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_2)); - when(channelService.getClosedChannelsWith(PUBKEY_2)).thenReturn(Set.of(CLOSED_CHANNEL, CLOSED_CHANNEL_3)); - when(channelService.getWaitingCloseChannelsWith(PUBKEY_2)).thenReturn(Set.of(WAITING_CLOSE_CHANNEL)); - when(channelService.getForceClosingChannelsWith(PUBKEY_2)).thenReturn(Set.of(FORCE_CLOSING_CHANNEL_2)); - when(onChainCostService.getOnChainCostsForPeer(PUBKEY_2)).thenReturn(ON_CHAIN_COSTS); - when(balanceService.getBalanceInformationForPeer(PUBKEY_2)).thenReturn(BALANCE_INFORMATION_2); - when(feeService.getFeeReportForPeer(PUBKEY_2)).thenReturn(FEE_REPORT); - when(rebalanceService.getReportForPeer(PUBKEY_2)).thenReturn(REBALANCE_REPORT); - List channelIds = List.of(CHANNEL_ID.toString(), CHANNEL_ID_2.toString()); - List closedChannelIds = List.of(CHANNEL_ID.toString(), CHANNEL_ID_3.toString()); - List waitingCloseChannelIds = List.of(CHANNEL_ID.toString()); - List forceClosingChannelIds = List.of(CHANNEL_ID_2.toString()); + when(nodeDetailsService.getDetails(PUBKEY)).thenReturn(NODE_DETAILS); + List channelIds = List.of(CHANNEL_ID.toString()); + List closedChannelIds = List.of(CHANNEL_ID_2.toString()); + List waitingCloseChannelIds = List.of(CHANNEL_ID_3.toString()); + List forceClosingChannelIds = List.of(CHANNEL_ID_4.toString()); mockMvc.perform(get(NODE_PREFIX + "/details")) - .andExpect(jsonPath("$.node", is(PUBKEY_2.toString()))) - .andExpect(jsonPath("$.alias", is(ALIAS_2))) + .andExpect(jsonPath("$.node", is(PUBKEY.toString()))) + .andExpect(jsonPath("$.alias", is(ALIAS))) .andExpect(jsonPath("$.channels", is(channelIds))) .andExpect(jsonPath("$.closedChannels", is(closedChannelIds))) .andExpect(jsonPath("$.waitingCloseChannels", is(waitingCloseChannelIds))) @@ -120,25 +103,25 @@ class NodeControllerIT { @Test void getOpenChannelIds() throws Exception { - when(channelService.getOpenChannelsWith(PUBKEY_2)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_3)); + when(channelService.getOpenChannelsWith(PUBKEY)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_3)); List channelIds = List.of(CHANNEL_ID.toString(), CHANNEL_ID_3.toString()); mockMvc.perform(get(NODE_PREFIX + "/open-channels")) - .andExpect(jsonPath("$.node", is(PUBKEY_2.toString()))) + .andExpect(jsonPath("$.node", is(PUBKEY.toString()))) .andExpect(jsonPath("$.channels", is(channelIds))); } @Test void getAllChannelIds() throws Exception { - when(channelService.getAllChannelsWith(PUBKEY_2)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, CLOSED_CHANNEL_3)); + when(channelService.getAllChannelsWith(PUBKEY)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, CLOSED_CHANNEL_3)); List channelIds = List.of(CHANNEL_ID.toString(), CHANNEL_ID_3.toString()); mockMvc.perform(get(NODE_PREFIX + "/all-channels")) - .andExpect(jsonPath("$.node", is(PUBKEY_2.toString()))) + .andExpect(jsonPath("$.node", is(PUBKEY.toString()))) .andExpect(jsonPath("$.channels", is(channelIds))); } @Test void getBalance() throws Exception { - when(balanceService.getBalanceInformationForPeer(PUBKEY_2)).thenReturn(BALANCE_INFORMATION); + when(balanceService.getBalanceInformationForPeer(PUBKEY)).thenReturn(BALANCE_INFORMATION); mockMvc.perform(get(NODE_PREFIX + "/balance")) .andExpect(jsonPath("$.localBalance", is("1000"))) .andExpect(jsonPath("$.localReserve", is("100"))) @@ -150,7 +133,7 @@ class NodeControllerIT { @Test void getFeeReport() throws Exception { - when(feeService.getFeeReportForPeer(PUBKEY_2)).thenReturn(FEE_REPORT); + when(feeService.getFeeReportForPeer(PUBKEY)).thenReturn(FEE_REPORT); mockMvc.perform(get(NODE_PREFIX + "/fee-report")) .andExpect(jsonPath("$.earned", is("1234"))) .andExpect(jsonPath("$.sourced", is("567"))); diff --git a/web/src/main/java/de/cotto/lndmanagej/controller/NodeController.java b/web/src/main/java/de/cotto/lndmanagej/controller/NodeController.java index df77da3d..b6c82747 100644 --- a/web/src/main/java/de/cotto/lndmanagej/controller/NodeController.java +++ b/web/src/main/java/de/cotto/lndmanagej/controller/NodeController.java @@ -6,18 +6,15 @@ import de.cotto.lndmanagej.controller.dto.ChannelsForNodeDto; import de.cotto.lndmanagej.controller.dto.FeeReportDto; import de.cotto.lndmanagej.controller.dto.NodeDetailsDto; import de.cotto.lndmanagej.controller.dto.ObjectMapperConfiguration; -import de.cotto.lndmanagej.model.BalanceInformation; import de.cotto.lndmanagej.model.Channel; import de.cotto.lndmanagej.model.ChannelId; -import de.cotto.lndmanagej.model.Node; -import de.cotto.lndmanagej.model.OnChainCosts; +import de.cotto.lndmanagej.model.NodeDetails; import de.cotto.lndmanagej.model.Pubkey; import de.cotto.lndmanagej.service.BalanceService; import de.cotto.lndmanagej.service.ChannelService; import de.cotto.lndmanagej.service.FeeService; +import de.cotto.lndmanagej.service.NodeDetailsService; import de.cotto.lndmanagej.service.NodeService; -import de.cotto.lndmanagej.service.OnChainCostService; -import de.cotto.lndmanagej.service.RebalanceService; import org.springframework.context.annotation.Import; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -33,25 +30,22 @@ import java.util.Set; public class NodeController { private final NodeService nodeService; private final ChannelService channelService; - private final OnChainCostService onChainCostService; private final BalanceService balanceService; private final FeeService feeService; - private final RebalanceService rebalanceService; + private final NodeDetailsService nodeDetailsService; public NodeController( NodeService nodeService, ChannelService channelService, - OnChainCostService onChainCostService, BalanceService balanceService, FeeService feeService, - RebalanceService rebalanceService + NodeDetailsService nodeDetailsService ) { this.nodeService = nodeService; this.channelService = channelService; - this.onChainCostService = onChainCostService; this.balanceService = balanceService; this.feeService = feeService; - this.rebalanceService = rebalanceService; + this.nodeDetailsService = nodeDetailsService; } @Timed @@ -63,22 +57,8 @@ public class NodeController { @Timed @GetMapping("/details") public NodeDetailsDto getDetails(@PathVariable Pubkey pubkey) { - Node node = nodeService.getNode(pubkey); - OnChainCosts onChainCosts = onChainCostService.getOnChainCostsForPeer(pubkey); - BalanceInformation balanceInformation = balanceService.getBalanceInformationForPeer(pubkey); - return new NodeDetailsDto( - pubkey, - node.alias(), - toSortedList(channelService.getOpenChannelsWith(pubkey)), - toSortedList(channelService.getClosedChannelsWith(pubkey)), - toSortedList(channelService.getWaitingCloseChannelsWith(pubkey)), - toSortedList(channelService.getForceClosingChannelsWith(pubkey)), - onChainCosts, - balanceInformation, - node.online(), - feeService.getFeeReportForPeer(pubkey), - rebalanceService.getReportForPeer(pubkey) - ); + NodeDetails nodeDetails = nodeDetailsService.getDetails(pubkey); + return NodeDetailsDto.createFromModel(nodeDetails); } @Timed diff --git a/web/src/main/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDto.java b/web/src/main/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDto.java index 99d3816a..58fc246c 100644 --- a/web/src/main/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDto.java +++ b/web/src/main/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDto.java @@ -2,12 +2,9 @@ package de.cotto.lndmanagej.controller.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; -import de.cotto.lndmanagej.model.BalanceInformation; import de.cotto.lndmanagej.model.ChannelId; -import de.cotto.lndmanagej.model.FeeReport; -import de.cotto.lndmanagej.model.OnChainCosts; +import de.cotto.lndmanagej.model.NodeDetails; import de.cotto.lndmanagej.model.Pubkey; -import de.cotto.lndmanagej.model.RebalanceReport; import java.util.List; @@ -24,32 +21,19 @@ public record NodeDetailsDto( FeeReportDto feeReport, RebalanceReportDto rebalanceReport ) { - @SuppressWarnings("PMD.ExcessiveParameterList") - public NodeDetailsDto( - Pubkey pubkey, - String alias, - List channels, - List closedChannels, - List waitingCloseChannels, - List pendingForceClosingChannels, - OnChainCosts onChainCosts, - BalanceInformation balanceInformation, - boolean online, - FeeReport feeReport, - RebalanceReport rebalanceReport - ) { - this( - pubkey, - alias, - channels, - closedChannels, - waitingCloseChannels, - pendingForceClosingChannels, - OnChainCostsDto.createFromModel(onChainCosts), - BalanceInformationDto.createFromModel(balanceInformation), - online, - FeeReportDto.createFromModel(feeReport), - RebalanceReportDto.createFromModel(rebalanceReport) + public static NodeDetailsDto createFromModel(NodeDetails nodeDetails) { + return new NodeDetailsDto( + nodeDetails.pubkey(), + nodeDetails.alias(), + nodeDetails.channels(), + nodeDetails.closedChannels(), + nodeDetails.waitingCloseChannels(), + nodeDetails.pendingForceClosingChannels(), + OnChainCostsDto.createFromModel(nodeDetails.onChainCosts()), + BalanceInformationDto.createFromModel(nodeDetails.balanceInformation()), + nodeDetails.online(), + FeeReportDto.createFromModel(nodeDetails.feeReport()), + RebalanceReportDto.createFromModel(nodeDetails.rebalanceReport()) ); } } diff --git a/web/src/test/java/de/cotto/lndmanagej/controller/NodeControllerTest.java b/web/src/test/java/de/cotto/lndmanagej/controller/NodeControllerTest.java index 10bd1618..43a5c9b3 100644 --- a/web/src/test/java/de/cotto/lndmanagej/controller/NodeControllerTest.java +++ b/web/src/test/java/de/cotto/lndmanagej/controller/NodeControllerTest.java @@ -4,21 +4,13 @@ import de.cotto.lndmanagej.controller.dto.BalanceInformationDto; import de.cotto.lndmanagej.controller.dto.ChannelsForNodeDto; import de.cotto.lndmanagej.controller.dto.FeeReportDto; import de.cotto.lndmanagej.controller.dto.NodeDetailsDto; -import de.cotto.lndmanagej.controller.dto.OnChainCostsDto; -import de.cotto.lndmanagej.controller.dto.RebalanceReportDto; -import de.cotto.lndmanagej.model.BalanceInformation; import de.cotto.lndmanagej.model.Coins; import de.cotto.lndmanagej.model.FeeReport; -import de.cotto.lndmanagej.model.Node; -import de.cotto.lndmanagej.model.OnChainCosts; -import de.cotto.lndmanagej.model.Pubkey; -import de.cotto.lndmanagej.model.RebalanceReport; import de.cotto.lndmanagej.service.BalanceService; import de.cotto.lndmanagej.service.ChannelService; import de.cotto.lndmanagej.service.FeeService; +import de.cotto.lndmanagej.service.NodeDetailsService; import de.cotto.lndmanagej.service.NodeService; -import de.cotto.lndmanagej.service.OnChainCostService; -import de.cotto.lndmanagej.service.RebalanceService; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -34,20 +26,14 @@ import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; import static de.cotto.lndmanagej.model.CoopClosedChannelFixtures.CLOSED_CHANNEL_2; import static de.cotto.lndmanagej.model.CoopClosedChannelFixtures.CLOSED_CHANNEL_3; -import static de.cotto.lndmanagej.model.ForceClosingChannelFixtures.FORCE_CLOSING_CHANNEL; -import static de.cotto.lndmanagej.model.ForceClosingChannelFixtures.FORCE_CLOSING_CHANNEL_2; -import static de.cotto.lndmanagej.model.ForceClosingChannelFixtures.FORCE_CLOSING_CHANNEL_3; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_2; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_3; +import static de.cotto.lndmanagej.model.NodeDetailsFixtures.NODE_DETAILS; import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS_2; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; -import static de.cotto.lndmanagej.model.RebalanceReportFixtures.REBALANCE_REPORT; -import static de.cotto.lndmanagej.model.WaitingCloseChannelFixtures.WAITING_CLOSE_CHANNEL; -import static de.cotto.lndmanagej.model.WaitingCloseChannelFixtures.WAITING_CLOSE_CHANNEL_2; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -63,9 +49,6 @@ class NodeControllerTest { @Mock private ChannelService channelService; - @Mock - private OnChainCostService onChainCostService; - @Mock private BalanceService balanceService; @@ -73,7 +56,7 @@ class NodeControllerTest { private FeeService feeService; @Mock - private RebalanceService rebalanceService; + private NodeDetailsService nodeDetailsService; @Test void getAlias() { @@ -83,64 +66,9 @@ class NodeControllerTest { } @Test - void getNodeDetails_no_channels() { - when(onChainCostService.getOnChainCostsForPeer(any())).thenReturn(OnChainCosts.NONE); - when(balanceService.getBalanceInformationForPeer(any(Pubkey.class))).thenReturn(BalanceInformation.EMPTY); - when(feeService.getFeeReportForPeer(any())).thenReturn(new FeeReport(Coins.NONE, Coins.NONE)); - when(rebalanceService.getReportForPeer(PUBKEY_2)).thenReturn(RebalanceReport.EMPTY); - NodeDetailsDto expectedDetails = new NodeDetailsDto( - PUBKEY_2, - ALIAS_2, - List.of(), - List.of(), - List.of(), - List.of(), - OnChainCostsDto.createFromModel(OnChainCosts.NONE), - BalanceInformationDto.createFromModel(BalanceInformation.EMPTY), - true, - new FeeReportDto("0", "0"), - RebalanceReportDto.createFromModel(RebalanceReport.EMPTY) - ); - when(nodeService.getNode(PUBKEY_2)).thenReturn(new Node(PUBKEY_2, ALIAS_2, 0, true)); - - assertThat(nodeController.getDetails(PUBKEY_2)).isEqualTo(expectedDetails); - } - - @Test - void getNodeDetails_with_channels() { - when(nodeService.getNode(PUBKEY_2)).thenReturn(new Node(PUBKEY_2, ALIAS_2, 0, false)); - when(channelService.getOpenChannelsWith(PUBKEY_2)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL_3, LOCAL_OPEN_CHANNEL)); - when(channelService.getClosedChannelsWith(PUBKEY_2)).thenReturn(Set.of(CLOSED_CHANNEL_2, CLOSED_CHANNEL_3)); - when(channelService.getWaitingCloseChannelsWith(PUBKEY_2)).thenReturn( - Set.of(WAITING_CLOSE_CHANNEL, WAITING_CLOSE_CHANNEL_2) - ); - when(channelService.getForceClosingChannelsWith(PUBKEY_2)).thenReturn( - Set.of(FORCE_CLOSING_CHANNEL, FORCE_CLOSING_CHANNEL_2, FORCE_CLOSING_CHANNEL_3) - ); - OnChainCosts onChainCosts = new OnChainCosts( - Coins.ofSatoshis(123), - Coins.ofSatoshis(456), - Coins.ofSatoshis(789) - ); - when(onChainCostService.getOnChainCostsForPeer(PUBKEY_2)).thenReturn(onChainCosts); - when(balanceService.getBalanceInformationForPeer(PUBKEY_2)).thenReturn(BALANCE_INFORMATION); - when(rebalanceService.getReportForPeer(PUBKEY_2)).thenReturn(REBALANCE_REPORT); - when(feeService.getFeeReportForPeer(PUBKEY_2)).thenReturn(FEE_REPORT); - NodeDetailsDto expectedDetails = new NodeDetailsDto( - PUBKEY_2, - ALIAS_2, - List.of(CHANNEL_ID, CHANNEL_ID_3), - List.of(CHANNEL_ID_2, CHANNEL_ID_3), - List.of(CHANNEL_ID, CHANNEL_ID_2), - List.of(CHANNEL_ID, CHANNEL_ID_2, CHANNEL_ID_3), - OnChainCostsDto.createFromModel(onChainCosts), - BalanceInformationDto.createFromModel(BALANCE_INFORMATION), - false, - FeeReportDto.createFromModel(FEE_REPORT), - RebalanceReportDto.createFromModel(REBALANCE_REPORT) - ); - - assertThat(nodeController.getDetails(PUBKEY_2)).isEqualTo(expectedDetails); + void getNodeDetails() { + when(nodeDetailsService.getDetails(PUBKEY_2)).thenReturn(NODE_DETAILS); + assertThat(nodeController.getDetails(PUBKEY_2)).isEqualTo(NodeDetailsDto.createFromModel(NODE_DETAILS)); } @Test diff --git a/web/src/test/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDtoTest.java b/web/src/test/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDtoTest.java new file mode 100644 index 00000000..79281c01 --- /dev/null +++ b/web/src/test/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDtoTest.java @@ -0,0 +1,38 @@ +package de.cotto.lndmanagej.controller.dto; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION_2; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_3; +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_4; +import static de.cotto.lndmanagej.model.FeeReportFixtures.FEE_REPORT; +import static de.cotto.lndmanagej.model.NodeDetailsFixtures.NODE_DETAILS; +import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS; +import static de.cotto.lndmanagej.model.OnChainCostsFixtures.ON_CHAIN_COSTS; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; +import static de.cotto.lndmanagej.model.RebalanceReportFixtures.REBALANCE_REPORT; +import static org.assertj.core.api.Assertions.assertThat; + +class NodeDetailsDtoTest { + @Test + void createFromModel() { + NodeDetailsDto expected = new NodeDetailsDto( + PUBKEY, + ALIAS, + List.of(CHANNEL_ID), + List.of(CHANNEL_ID_2), + List.of(CHANNEL_ID_3), + List.of(CHANNEL_ID_4), + OnChainCostsDto.createFromModel(ON_CHAIN_COSTS), + BalanceInformationDto.createFromModel(BALANCE_INFORMATION_2), + true, + FeeReportDto.createFromModel(FEE_REPORT), + RebalanceReportDto.createFromModel(REBALANCE_REPORT) + ); + assertThat(NodeDetailsDto.createFromModel(NODE_DETAILS)).isEqualTo(expected); + } +} \ No newline at end of file