diff --git a/application/src/integrationTest/java/de/cotto/lndmanagej/controller/NodeControllerIT.java b/application/src/integrationTest/java/de/cotto/lndmanagej/controller/NodeControllerIT.java index 9766fff4..3c89a1ed 100644 --- a/application/src/integrationTest/java/de/cotto/lndmanagej/controller/NodeControllerIT.java +++ b/application/src/integrationTest/java/de/cotto/lndmanagej/controller/NodeControllerIT.java @@ -16,6 +16,8 @@ import java.util.Set; 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.CoopClosedChannelFixtures.CLOSED_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; @@ -55,11 +57,14 @@ class NodeControllerIT { 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)); List channelIds = List.of(CHANNEL_ID.toString(), CHANNEL_ID_2.toString()); + List closedChannelIds = List.of(CHANNEL_ID.toString(), CHANNEL_ID_3.toString()); mockMvc.perform(get(NODE_PREFIX + "/details")) .andExpect(jsonPath("$.node", is(PUBKEY_2.toString()))) .andExpect(jsonPath("$.alias", is(ALIAS_2))) .andExpect(jsonPath("$.channels", is(channelIds))) + .andExpect(jsonPath("$.closedChannels", is(closedChannelIds))) .andExpect(jsonPath("$.online", is(true))); } diff --git a/application/src/main/java/de/cotto/lndmanagej/controller/NodeController.java b/application/src/main/java/de/cotto/lndmanagej/controller/NodeController.java index f9a99144..23865b39 100644 --- a/application/src/main/java/de/cotto/lndmanagej/controller/NodeController.java +++ b/application/src/main/java/de/cotto/lndmanagej/controller/NodeController.java @@ -44,7 +44,13 @@ public class NodeController { public NodeDetailsDto getDetails(@PathVariable Pubkey pubkey) { mark("getDetails"); Node node = nodeService.getNode(pubkey); - return new NodeDetailsDto(pubkey, node.alias(), getChannelIdsForPubkey(pubkey), node.online()); + return new NodeDetailsDto( + pubkey, + node.alias(), + getChannelIdsForPubkey(pubkey), + getClosedChannelIdsForPubkey(pubkey), + node.online() + ); } @GetMapping("/open-channels") @@ -61,6 +67,13 @@ public class NodeController { .collect(Collectors.toList()); } + private List getClosedChannelIdsForPubkey(Pubkey pubkey) { + return channelService.getClosedChannelsWith(pubkey).stream() + .map(Channel::getId) + .sorted() + .collect(Collectors.toList()); + } + private void mark(String getDetails) { metrics.mark(MetricRegistry.name(getClass(), getDetails)); } diff --git a/application/src/main/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDto.java b/application/src/main/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDto.java index d1970db8..034f66f1 100644 --- a/application/src/main/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDto.java +++ b/application/src/main/java/de/cotto/lndmanagej/controller/dto/NodeDetailsDto.java @@ -11,6 +11,7 @@ public record NodeDetailsDto( @JsonSerialize(using = ToStringSerializer.class) Pubkey node, String alias, List channels, + List closedChannels, boolean online ) { } diff --git a/application/src/main/java/de/cotto/lndmanagej/service/ChannelService.java b/application/src/main/java/de/cotto/lndmanagej/service/ChannelService.java index 76cc1768..325550c0 100644 --- a/application/src/main/java/de/cotto/lndmanagej/service/ChannelService.java +++ b/application/src/main/java/de/cotto/lndmanagej/service/ChannelService.java @@ -95,6 +95,12 @@ public class ChannelService { .collect(Collectors.toSet()); } + public Set getClosedChannelsWith(Pubkey peer) { + return getClosedChannels().stream() + .filter(c -> peer.equals(c.getRemotePubkey())) + .collect(Collectors.toSet()); + } + public Set getAllChannelsWith(Pubkey peer) { return getAllLocalChannels() .filter(c -> peer.equals(c.getRemotePubkey())) diff --git a/application/src/test/java/de/cotto/lndmanagej/controller/NodeControllerTest.java b/application/src/test/java/de/cotto/lndmanagej/controller/NodeControllerTest.java index ad016e9b..3c6081c4 100644 --- a/application/src/test/java/de/cotto/lndmanagej/controller/NodeControllerTest.java +++ b/application/src/test/java/de/cotto/lndmanagej/controller/NodeControllerTest.java @@ -18,6 +18,8 @@ import java.util.Set; 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_2; +import static de.cotto.lndmanagej.model.CoopClosedChannelFixtures.CLOSED_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; @@ -53,7 +55,7 @@ class NodeControllerTest { @Test void getNodeDetails_no_channels() { - NodeDetailsDto expectedDetails = new NodeDetailsDto(PUBKEY_2, ALIAS_2, List.of(), true); + NodeDetailsDto expectedDetails = new NodeDetailsDto(PUBKEY_2, ALIAS_2, List.of(), List.of(), true); when(nodeService.getNode(PUBKEY_2)).thenReturn(new Node(PUBKEY_2, ALIAS_2, 0, true)); assertThat(nodeController.getDetails(PUBKEY_2)).isEqualTo(expectedDetails); @@ -64,10 +66,12 @@ class NodeControllerTest { 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, LOCAL_OPEN_CHANNEL_3)); + when(channelService.getClosedChannelsWith(PUBKEY_2)).thenReturn(Set.of(CLOSED_CHANNEL_2, CLOSED_CHANNEL_3)); NodeDetailsDto expectedDetails = new NodeDetailsDto( PUBKEY_2, ALIAS_2, List.of(CHANNEL_ID, CHANNEL_ID_3), + List.of(CHANNEL_ID_2, CHANNEL_ID_3), false ); diff --git a/application/src/test/java/de/cotto/lndmanagej/service/ChannelServiceTest.java b/application/src/test/java/de/cotto/lndmanagej/service/ChannelServiceTest.java index 7f717484..820ad767 100644 --- a/application/src/test/java/de/cotto/lndmanagej/service/ChannelServiceTest.java +++ b/application/src/test/java/de/cotto/lndmanagej/service/ChannelServiceTest.java @@ -129,6 +129,22 @@ class ChannelServiceTest { .containsExactlyInAnyOrder(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_3); } + @Test + void getClosedChannelsWith_by_pubkey() { + when(grpcClosedChannels.getClosedChannels()).thenReturn(Set.of(CLOSED_CHANNEL, CLOSED_CHANNEL_2)); + assertThat(channelService.getClosedChannelsWith(PUBKEY_2)) + .containsExactlyInAnyOrder(CLOSED_CHANNEL, CLOSED_CHANNEL_2); + } + + @Test + void getClosedChannelsWith_ignores_channel_to_other_node() { + when(grpcClosedChannels.getClosedChannels()).thenReturn( + Set.of(CLOSED_CHANNEL, CLOSED_CHANNEL_2, CLOSED_CHANNEL_TO_NODE_3) + ); + assertThat(channelService.getClosedChannelsWith(PUBKEY_2)) + .containsExactlyInAnyOrder(CLOSED_CHANNEL, CLOSED_CHANNEL_2); + } + @Test void getOpenChannels() { when(grpcChannels.getChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_2));