diff --git a/application/src/integrationTest/java/de/cotto/lndmanagej/controller/LegacyControllerIT.java b/application/src/integrationTest/java/de/cotto/lndmanagej/controller/LegacyControllerIT.java index 7dd999a4..ca5f7b1a 100644 --- a/application/src/integrationTest/java/de/cotto/lndmanagej/controller/LegacyControllerIT.java +++ b/application/src/integrationTest/java/de/cotto/lndmanagej/controller/LegacyControllerIT.java @@ -80,6 +80,13 @@ class LegacyControllerIT { .andExpect(content().string(CHANNEL_ID + "\n" + CHANNEL_ID_3)); } + @Test + void getAllChannelIds_for_peer() throws Exception { + when(channelService.getAllChannelsWith(PUBKEY)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, CLOSED_CHANNEL_3)); + mockMvc.perform(get(PUBKEY_BASE + "/all-channels")) + .andExpect(content().string(CHANNEL_ID + "\n" + CHANNEL_ID_3)); + } + @Test void getOpenChannelIds() throws Exception { when(channelService.getOpenChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_3)); diff --git a/application/src/main/java/de/cotto/lndmanagej/controller/LegacyController.java b/application/src/main/java/de/cotto/lndmanagej/controller/LegacyController.java index 22ac3640..03505cbd 100644 --- a/application/src/main/java/de/cotto/lndmanagej/controller/LegacyController.java +++ b/application/src/main/java/de/cotto/lndmanagej/controller/LegacyController.java @@ -63,6 +63,16 @@ public class LegacyController { .collect(Collectors.joining(NEWLINE)); } + @GetMapping("/node/{pubkey}/all-channels") + public String getAllChannelIdsForPubkey(@PathVariable Pubkey pubkey) { + mark("getAllChannelIdsForPubkey"); + return channelService.getAllChannelsWith(pubkey).stream() + .map(Channel::getId) + .sorted() + .map(ChannelId::toString) + .collect(Collectors.joining(NEWLINE)); + } + @GetMapping("/open-channels") public String getOpenChannelIds() { mark("getOpenChannelIds"); 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 99822288..4b0e6c87 100644 --- a/application/src/main/java/de/cotto/lndmanagej/service/ChannelService.java +++ b/application/src/main/java/de/cotto/lndmanagej/service/ChannelService.java @@ -4,6 +4,7 @@ import com.google.common.cache.LoadingCache; import de.cotto.lndmanagej.caching.CacheBuilder; import de.cotto.lndmanagej.grpc.GrpcChannels; import de.cotto.lndmanagej.model.ClosedChannel; +import de.cotto.lndmanagej.model.LocalChannel; import de.cotto.lndmanagej.model.LocalOpenChannel; import de.cotto.lndmanagej.model.Pubkey; import de.cotto.lndmanagej.model.UnresolvedClosedChannel; @@ -12,6 +13,7 @@ import org.springframework.stereotype.Component; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; @Component public class ChannelService { @@ -61,4 +63,12 @@ public class ChannelService { .filter(c -> peer.equals(c.getRemotePubkey())) .collect(Collectors.toSet()); } + + public Set getAllChannelsWith(Pubkey pubkey) { + Stream openChannels = getOpenChannelsWith(pubkey).stream(); + Stream closedChannels = getClosedChannels().stream() + .filter(c -> c.getRemotePubkey().equals(pubkey)); + return Stream.concat(openChannels, closedChannels) + .collect(Collectors.toSet()); + } } diff --git a/application/src/test/java/de/cotto/lndmanagej/controller/LegacyControllerTest.java b/application/src/test/java/de/cotto/lndmanagej/controller/LegacyControllerTest.java index baa1fc03..9cd5e515 100644 --- a/application/src/test/java/de/cotto/lndmanagej/controller/LegacyControllerTest.java +++ b/application/src/test/java/de/cotto/lndmanagej/controller/LegacyControllerTest.java @@ -91,6 +91,23 @@ class LegacyControllerTest { ); } + @Test + void getAllChannelIds_for_peer() { + when(channelService.getAllChannelsWith(PUBKEY)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, CLOSED_CHANNEL_3)); + assertThat(legacyController.getAllChannelIdsForPubkey(PUBKEY)).isEqualTo( + CHANNEL_ID + "\n" + CHANNEL_ID_3 + ); + verify(metrics).mark(argThat(name -> name.endsWith(".getAllChannelIdsForPubkey"))); + } + + @Test + void getAllChannelIds_for_peer_ordered() { + when(channelService.getAllChannelsWith(PUBKEY)).thenReturn(Set.of(CLOSED_CHANNEL_3, LOCAL_OPEN_CHANNEL)); + assertThat(legacyController.getAllChannelIdsForPubkey(PUBKEY)).isEqualTo( + CHANNEL_ID + "\n" + CHANNEL_ID_3 + ); + } + @Test void getOpenChannelIds() { when(channelService.getOpenChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_3)); 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 417a8de7..1afa4e2f 100644 --- a/application/src/test/java/de/cotto/lndmanagej/service/ChannelServiceTest.java +++ b/application/src/test/java/de/cotto/lndmanagej/service/ChannelServiceTest.java @@ -19,15 +19,19 @@ import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2; import static de.cotto.lndmanagej.model.ChannelPointFixtures.CHANNEL_POINT; import static de.cotto.lndmanagej.model.ClosedChannelFixtures.CLOSED_CHANNEL; import static de.cotto.lndmanagej.model.ClosedChannelFixtures.CLOSED_CHANNEL_2; +import static de.cotto.lndmanagej.model.ClosedChannelFixtures.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; +import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_TO_NODE_3; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3; import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.CLOSED_CHANNEL_UNRESOLVED_ID; import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL; import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL_2; +import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL_3; +import static de.cotto.lndmanagej.model.UnresolvedClosedChannelFixtures.UNRESOLVED_CLOSED_CHANNEL_TO_NODE_3; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; @@ -91,4 +95,13 @@ class ChannelServiceTest { .thenReturn(Set.of(UNRESOLVED_CLOSED_CHANNEL_2, CLOSED_CHANNEL_UNRESOLVED_ID)); assertThat(channelService.getClosedChannels()).containsExactlyInAnyOrder(CLOSED_CHANNEL_2); } + + @Test + void getAllChannels_by_pubkey() { + when(grpcChannels.getChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_TO_NODE_3)); + when(grpcChannels.getUnresolvedClosedChannels()) + .thenReturn(Set.of(UNRESOLVED_CLOSED_CHANNEL_3, UNRESOLVED_CLOSED_CHANNEL_TO_NODE_3)); + assertThat(channelService.getAllChannelsWith(PUBKEY_2)) + .containsExactlyInAnyOrder(LOCAL_OPEN_CHANNEL, CLOSED_CHANNEL_3); + } } \ No newline at end of file diff --git a/model/src/main/java/de/cotto/lndmanagej/model/ClosedChannel.java b/model/src/main/java/de/cotto/lndmanagej/model/ClosedChannel.java index 660ba8ba..4878e68e 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/ClosedChannel.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/ClosedChannel.java @@ -1,8 +1,8 @@ package de.cotto.lndmanagej.model; public final class ClosedChannel extends LocalChannel { - private ClosedChannel(LocalChannel localChannel) { - super(localChannel, localChannel.getRemotePubkey()); + private ClosedChannel(LocalChannel localChannel, Pubkey ownPubkey) { + super(localChannel, ownPubkey); } public static ClosedChannel create(UnresolvedClosedChannel unresolvedClosedChannel) { @@ -13,6 +13,6 @@ public final class ClosedChannel extends LocalChannel { if (channelId.isUnresolved()) { throw new IllegalArgumentException("Channel ID must be resolved"); } - return new ClosedChannel(unresolvedClosedChannel.getWithId(channelId)); + return new ClosedChannel(unresolvedClosedChannel.getWithId(channelId), unresolvedClosedChannel.getOwnPubkey()); } } diff --git a/model/src/main/java/de/cotto/lndmanagej/model/UnresolvedClosedChannel.java b/model/src/main/java/de/cotto/lndmanagej/model/UnresolvedClosedChannel.java index 5f67d963..475eca3f 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/UnresolvedClosedChannel.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/UnresolvedClosedChannel.java @@ -12,4 +12,8 @@ public class UnresolvedClosedChannel extends LocalChannel { public LocalChannel getWithId(ChannelId channelId) { return new UnresolvedClosedChannel(super.getWithId(channelId), ownPubkey); } + + public Pubkey getOwnPubkey() { + return ownPubkey; + } } diff --git a/model/src/test/java/de/cotto/lndmanagej/model/ClosedChannelTest.java b/model/src/test/java/de/cotto/lndmanagej/model/ClosedChannelTest.java index d6f80405..09be21cf 100644 --- a/model/src/test/java/de/cotto/lndmanagej/model/ClosedChannelTest.java +++ b/model/src/test/java/de/cotto/lndmanagej/model/ClosedChannelTest.java @@ -32,6 +32,12 @@ class ClosedChannelTest { assertThat(ClosedChannel.create(CLOSED_CHANNEL_UNRESOLVED_ID, CHANNEL_ID)).isEqualTo(CLOSED_CHANNEL); } + @Test + void create_with_explicit_channel_id_retains_remote_pubkey() { + ClosedChannel closedChannel = ClosedChannel.create(CLOSED_CHANNEL_UNRESOLVED_ID, CHANNEL_ID); + assertThat(closedChannel.getRemotePubkey()).isEqualTo(CLOSED_CHANNEL_UNRESOLVED_ID.getRemotePubkey()); + } + @Test void create_with_explicit_unresolved_channel_id() { assertThatIllegalArgumentException() @@ -46,7 +52,7 @@ class ClosedChannelTest { @Test void getRemotePubkey() { - assertThat(CLOSED_CHANNEL.getRemotePubkey()).isEqualTo(PUBKEY); + assertThat(CLOSED_CHANNEL.getRemotePubkey()).isEqualTo(PUBKEY_2); } @Test diff --git a/model/src/test/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelTest.java b/model/src/test/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelTest.java index 1072c10a..f1eb18e3 100644 --- a/model/src/test/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelTest.java +++ b/model/src/test/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelTest.java @@ -40,4 +40,12 @@ class UnresolvedClosedChannelTest { void getWithId() { assertThat(CLOSED_CHANNEL_UNRESOLVED_ID.getWithId(CHANNEL_ID)).isEqualTo(UNRESOLVED_CLOSED_CHANNEL); } + + @Test + void getOwnPubkey() { + Channel channel = ChannelFixtures.create(PUBKEY_3, PUBKEY_2, CHANNEL_ID); + UnresolvedClosedChannel unresolvedClosedChannel = + new UnresolvedClosedChannel(channel, PUBKEY_3); + assertThat(unresolvedClosedChannel.getOwnPubkey()).isEqualTo(PUBKEY_3); + } } \ No newline at end of file diff --git a/model/src/testFixtures/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelFixtures.java b/model/src/testFixtures/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelFixtures.java index b97e655c..498851a7 100644 --- a/model/src/testFixtures/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelFixtures.java +++ b/model/src/testFixtures/java/de/cotto/lndmanagej/model/UnresolvedClosedChannelFixtures.java @@ -3,6 +3,7 @@ package de.cotto.lndmanagej.model; import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL; import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_2; import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_3; +import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_TO_NODE_3; import static de.cotto.lndmanagej.model.ChannelFixtures.CHANNEL_UNRESOLVED_ID; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; @@ -15,4 +16,6 @@ public class UnresolvedClosedChannelFixtures { new UnresolvedClosedChannel(CHANNEL_2, PUBKEY); public static final UnresolvedClosedChannel UNRESOLVED_CLOSED_CHANNEL_3 = new UnresolvedClosedChannel(CHANNEL_3, PUBKEY); + public static final UnresolvedClosedChannel UNRESOLVED_CLOSED_CHANNEL_TO_NODE_3 = + new UnresolvedClosedChannel(CHANNEL_TO_NODE_3, PUBKEY); }