diff --git a/application/src/integrationTest/java/de/cotto/lndmanagej/controller/ChannelDetailsControllerIT.java b/application/src/integrationTest/java/de/cotto/lndmanagej/controller/ChannelDetailsControllerIT.java index 501d9cb6..dd79032b 100644 --- a/application/src/integrationTest/java/de/cotto/lndmanagej/controller/ChannelDetailsControllerIT.java +++ b/application/src/integrationTest/java/de/cotto/lndmanagej/controller/ChannelDetailsControllerIT.java @@ -12,7 +12,7 @@ import org.springframework.test.web.servlet.MockMvc; import java.util.Optional; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; -import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; +import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_PRIVATE; import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS_2; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; import static org.hamcrest.core.Is.is; @@ -47,10 +47,11 @@ class ChannelDetailsControllerIT { @Test void getChannelDetails() throws Exception { when(nodeService.getAlias(PUBKEY_2)).thenReturn(ALIAS_2); - when(channelService.getLocalChannel(CHANNEL_ID)).thenReturn(Optional.of(LOCAL_OPEN_CHANNEL)); + when(channelService.getLocalChannel(CHANNEL_ID)).thenReturn(Optional.of(LOCAL_OPEN_CHANNEL_PRIVATE)); mockMvc.perform(get(CHANNEL_PREFIX + "/details")) .andExpect(jsonPath("$.channelId", is(String.valueOf(CHANNEL_ID.getShortChannelId())))) .andExpect(jsonPath("$.remotePubkey", is(PUBKEY_2.toString()))) - .andExpect(jsonPath("$.remoteAlias", is(ALIAS_2))); + .andExpect(jsonPath("$.remoteAlias", is(ALIAS_2))) + .andExpect(jsonPath("$.private", is(true))); } } \ No newline at end of file diff --git a/application/src/main/java/de/cotto/lndmanagej/controller/ChannelDetailsController.java b/application/src/main/java/de/cotto/lndmanagej/controller/ChannelDetailsController.java index 2d57cda8..4ac9062d 100644 --- a/application/src/main/java/de/cotto/lndmanagej/controller/ChannelDetailsController.java +++ b/application/src/main/java/de/cotto/lndmanagej/controller/ChannelDetailsController.java @@ -34,6 +34,7 @@ public class ChannelDetailsController { } Pubkey remotePubkey = localChannel.getRemotePubkey(); String remoteAlias = nodeService.getAlias(remotePubkey); - return new ChannelDetailsDto(localChannel.getId(), remotePubkey, remoteAlias); + boolean privateChannel = localChannel.isPrivateChannel(); + return new ChannelDetailsDto(localChannel.getId(), remotePubkey, remoteAlias, privateChannel); } } diff --git a/application/src/main/java/de/cotto/lndmanagej/controller/ChannelDetailsDto.java b/application/src/main/java/de/cotto/lndmanagej/controller/ChannelDetailsDto.java index 19144482..e7ecb5a3 100644 --- a/application/src/main/java/de/cotto/lndmanagej/controller/ChannelDetailsDto.java +++ b/application/src/main/java/de/cotto/lndmanagej/controller/ChannelDetailsDto.java @@ -1,5 +1,6 @@ package de.cotto.lndmanagej.controller; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import de.cotto.lndmanagej.model.ChannelId; @@ -8,6 +9,7 @@ import de.cotto.lndmanagej.model.Pubkey; public record ChannelDetailsDto( @JsonSerialize(using = ToStringSerializer.class) ChannelId channelId, @JsonSerialize(using = ToStringSerializer.class) Pubkey remotePubkey, - String remoteAlias + String remoteAlias, + @JsonProperty("private") boolean privateChannel ) { } diff --git a/application/src/test/java/de/cotto/lndmanagej/controller/ChannelDetailsControllerTest.java b/application/src/test/java/de/cotto/lndmanagej/controller/ChannelDetailsControllerTest.java index 46ac2b3d..0e18e5e4 100644 --- a/application/src/test/java/de/cotto/lndmanagej/controller/ChannelDetailsControllerTest.java +++ b/application/src/test/java/de/cotto/lndmanagej/controller/ChannelDetailsControllerTest.java @@ -13,6 +13,7 @@ import java.util.Optional; import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; +import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_PRIVATE; import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS_2; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; import static org.assertj.core.api.Assertions.assertThat; @@ -43,11 +44,21 @@ class ChannelDetailsControllerTest { @Test void getDetails() throws NotFoundException { - ChannelDetailsDto expectedDetails = new ChannelDetailsDto(CHANNEL_ID, PUBKEY_2, ALIAS_2); + ChannelDetailsDto expectedDetails = new ChannelDetailsDto(CHANNEL_ID, PUBKEY_2, ALIAS_2, false); when(nodeService.getAlias(PUBKEY_2)).thenReturn(ALIAS_2); when(channelService.getLocalChannel(CHANNEL_ID)).thenReturn(Optional.of(LOCAL_OPEN_CHANNEL)); assertThat(channelDetailsController.getDetails(CHANNEL_ID)).isEqualTo(expectedDetails); verify(metrics).mark(argThat(name -> name.endsWith(".getDetails"))); } + + @Test + void getDetails_private() throws NotFoundException { + ChannelDetailsDto expectedDetails = new ChannelDetailsDto(CHANNEL_ID, PUBKEY_2, ALIAS_2, true); + when(nodeService.getAlias(PUBKEY_2)).thenReturn(ALIAS_2); + when(channelService.getLocalChannel(CHANNEL_ID)).thenReturn(Optional.of(LOCAL_OPEN_CHANNEL_PRIVATE)); + + assertThat(channelDetailsController.getDetails(CHANNEL_ID)).isEqualTo(expectedDetails); + verify(metrics).mark(argThat(name -> name.endsWith(".getDetails"))); + } } \ No newline at end of file diff --git a/application/src/test/java/de/cotto/lndmanagej/service/TransactionBackgroundLoaderTest.java b/application/src/test/java/de/cotto/lndmanagej/service/TransactionBackgroundLoaderTest.java index 4b8f8025..2a1bfdf2 100644 --- a/application/src/test/java/de/cotto/lndmanagej/service/TransactionBackgroundLoaderTest.java +++ b/application/src/test/java/de/cotto/lndmanagej/service/TransactionBackgroundLoaderTest.java @@ -143,8 +143,8 @@ class TransactionBackgroundLoaderTest { PUBKEY, PUBKEY_2, BALANCE_INFORMATION, - LOCAL - ); + LOCAL, + false); LocalOpenChannel channel2 = new LocalOpenChannel( CHANNEL_ID_2, CHANNEL_POINT_2, @@ -152,8 +152,8 @@ class TransactionBackgroundLoaderTest { PUBKEY, PUBKEY_2, BALANCE_INFORMATION, - LOCAL - ); + LOCAL, + false); LocalOpenChannel channel3 = new LocalOpenChannel( CHANNEL_ID_3, CHANNEL_POINT_3, @@ -161,8 +161,8 @@ class TransactionBackgroundLoaderTest { PUBKEY, PUBKEY_2, BALANCE_INFORMATION, - LOCAL - ); + LOCAL, + false); when(channelService.getOpenChannels()).thenReturn(Set.of(channel1, channel2, channel3)); String unknownHash = CHANNEL_POINT_3.getTransactionHash(); when(transactionService.isUnknown(any())).thenReturn(false); diff --git a/grpc-adapter/src/main/java/de/cotto/lndmanagej/grpc/GrpcChannels.java b/grpc-adapter/src/main/java/de/cotto/lndmanagej/grpc/GrpcChannels.java index 6ed97fa8..7f2db712 100644 --- a/grpc-adapter/src/main/java/de/cotto/lndmanagej/grpc/GrpcChannels.java +++ b/grpc-adapter/src/main/java/de/cotto/lndmanagej/grpc/GrpcChannels.java @@ -123,7 +123,8 @@ public class GrpcChannels extends GrpcChannelsBase { ownPubkey, Pubkey.create(lndChannel.getRemotePubkey()), balanceInformation, - getOpenInitiator(lndChannel) + getOpenInitiator(lndChannel), + lndChannel.getPrivate() ); } diff --git a/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcChannelsTest.java b/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcChannelsTest.java index 45551282..9a3cbd3a 100644 --- a/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcChannelsTest.java +++ b/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcChannelsTest.java @@ -32,6 +32,7 @@ import static de.cotto.lndmanagej.model.ForceClosingChannelFixtures.FORCE_CLOSIN import static de.cotto.lndmanagej.model.ForceClosingChannelFixtures.HTLC_OUTPOINT; 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_PRIVATE; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; import static de.cotto.lndmanagej.model.WaitingCloseChannelFixtures.WAITING_CLOSE_CHANNEL; @@ -66,12 +67,20 @@ class GrpcChannelsTest { @Test void getChannels() { when(grpcService.getChannels()).thenReturn(List.of( - channel(CHANNEL_ID, true), - channel(CHANNEL_ID_2, false) + channel(CHANNEL_ID, true, false), + channel(CHANNEL_ID_2, false, false) )); assertThat(grpcChannels.getChannels()).containsExactlyInAnyOrder(LOCAL_OPEN_CHANNEL, LOCAL_OPEN_CHANNEL_2); } + @Test + void getChannels_private() { + when(grpcService.getChannels()).thenReturn(List.of( + channel(CHANNEL_ID, true, true) + )); + assertThat(grpcChannels.getChannels()).containsExactlyInAnyOrder(LOCAL_OPEN_CHANNEL_PRIVATE); + } + @Test void getForceClosingChannels_both_resolved() { when(channelIdResolver.resolveFromChannelPoint(CHANNEL_POINT)).thenReturn(Optional.of(CHANNEL_ID)); @@ -119,8 +128,8 @@ class GrpcChannelsTest { @Test void getChannel() { when(grpcService.getChannels()).thenReturn(List.of( - channel(CHANNEL_ID_2, false), - channel(CHANNEL_ID, true) + channel(CHANNEL_ID_2, false, false), + channel(CHANNEL_ID, true, false) )); assertThat(grpcChannels.getChannel(CHANNEL_ID)).contains(LOCAL_OPEN_CHANNEL); } @@ -130,7 +139,7 @@ class GrpcChannelsTest { assertThat(grpcChannels.getChannel(CHANNEL_ID)).isEmpty(); } - private Channel channel(ChannelId channelId, boolean isInitiator) { + private Channel channel(ChannelId channelId, boolean isInitiator, boolean isPrivate) { ChannelConstraints localConstraints = ChannelConstraints.newBuilder() .setChanReserveSat(BALANCE_INFORMATION.localReserve().satoshis()) .build(); @@ -147,6 +156,7 @@ class GrpcChannelsTest { .setLocalConstraints(localConstraints) .setRemoteConstraints(remoteConstraints) .setInitiator(isInitiator) + .setPrivate(isPrivate) .build(); } diff --git a/model/src/main/java/de/cotto/lndmanagej/model/ClosedOrClosingChannel.java b/model/src/main/java/de/cotto/lndmanagej/model/ClosedOrClosingChannel.java index 0fa89a4c..6f9e82df 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/ClosedOrClosingChannel.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/ClosedOrClosingChannel.java @@ -14,7 +14,7 @@ public class ClosedOrClosingChannel extends LocalChannel { String closeTransactionHash, OpenInitiator openInitiator ) { - super(channelId, channelPoint, capacity, ownPubkey, remotePubkey, openInitiator); + super(channelId, channelPoint, capacity, ownPubkey, remotePubkey, openInitiator, false); this.closeTransactionHash = closeTransactionHash; } diff --git a/model/src/main/java/de/cotto/lndmanagej/model/LocalChannel.java b/model/src/main/java/de/cotto/lndmanagej/model/LocalChannel.java index cbf77475..faddd5c6 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/LocalChannel.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/LocalChannel.java @@ -5,6 +5,7 @@ import java.util.Objects; public class LocalChannel extends Channel { private final Pubkey remotePubkey; private final OpenInitiator openInitiator; + private final boolean privateChannel; protected LocalChannel( ChannelId channelId, @@ -12,17 +13,27 @@ public class LocalChannel extends Channel { Coins capacity, Pubkey ownPubkey, Pubkey remotePubkey, - OpenInitiator openInitiator + OpenInitiator openInitiator, + boolean privateChannel ) { super(channelId, channelPoint, capacity, ownPubkey, remotePubkey); this.remotePubkey = remotePubkey; this.openInitiator = openInitiator; + this.privateChannel = privateChannel; } public Pubkey getRemotePubkey() { return remotePubkey; } + public OpenInitiator getOpenInitiator() { + return openInitiator; + } + + public boolean isPrivateChannel() { + return privateChannel; + } + @Override @SuppressWarnings("CPD-START") public boolean equals(Object other) { @@ -36,15 +47,13 @@ public class LocalChannel extends Channel { return false; } LocalChannel that = (LocalChannel) other; - return Objects.equals(remotePubkey, that.remotePubkey) && openInitiator == that.openInitiator; + return privateChannel == that.privateChannel + && Objects.equals(remotePubkey, that.remotePubkey) + && openInitiator == that.openInitiator; } @Override public int hashCode() { - return Objects.hash(super.hashCode(), remotePubkey, openInitiator); - } - - public OpenInitiator getOpenInitiator() { - return openInitiator; + return Objects.hash(super.hashCode(), remotePubkey, openInitiator, privateChannel); } } diff --git a/model/src/main/java/de/cotto/lndmanagej/model/LocalOpenChannel.java b/model/src/main/java/de/cotto/lndmanagej/model/LocalOpenChannel.java index c7b19f1c..df55225b 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/LocalOpenChannel.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/LocalOpenChannel.java @@ -12,9 +12,10 @@ public class LocalOpenChannel extends LocalChannel { Pubkey ownPubkey, Pubkey remotePubkey, BalanceInformation balanceInformation, - OpenInitiator openInitiator + OpenInitiator openInitiator, + boolean isPrivate ) { - super(channelId, channelPoint, capacity, ownPubkey, remotePubkey, openInitiator); + super(channelId, channelPoint, capacity, ownPubkey, remotePubkey, openInitiator, isPrivate); this.balanceInformation = balanceInformation; } diff --git a/model/src/main/java/de/cotto/lndmanagej/model/WaitingCloseChannel.java b/model/src/main/java/de/cotto/lndmanagej/model/WaitingCloseChannel.java index e609df1b..77d2ef19 100644 --- a/model/src/main/java/de/cotto/lndmanagej/model/WaitingCloseChannel.java +++ b/model/src/main/java/de/cotto/lndmanagej/model/WaitingCloseChannel.java @@ -9,6 +9,6 @@ public class WaitingCloseChannel extends LocalChannel { Pubkey remotePubkey, OpenInitiator openInitiator ) { - super(channelId, channelPoint, capacity, ownPubkey, remotePubkey, openInitiator); + super(channelId, channelPoint, capacity, ownPubkey, remotePubkey, openInitiator, false); } } diff --git a/model/src/test/java/de/cotto/lndmanagej/model/LocalOpenChannelTest.java b/model/src/test/java/de/cotto/lndmanagej/model/LocalOpenChannelTest.java index d32b2d46..144c84dd 100644 --- a/model/src/test/java/de/cotto/lndmanagej/model/LocalOpenChannelTest.java +++ b/model/src/test/java/de/cotto/lndmanagej/model/LocalOpenChannelTest.java @@ -25,8 +25,16 @@ class LocalOpenChannelTest { @Test void getRemotePubkey_swapped() { - LocalOpenChannel localOpenChannel = - new LocalOpenChannel(CHANNEL_ID, CHANNEL_POINT, CAPACITY, PUBKEY_2, PUBKEY, BALANCE_INFORMATION, LOCAL); + LocalOpenChannel localOpenChannel = new LocalOpenChannel( + CHANNEL_ID, + CHANNEL_POINT, + CAPACITY, + PUBKEY_2, + PUBKEY, + BALANCE_INFORMATION, + LOCAL, + false + ); assertThat(localOpenChannel.getRemotePubkey()).isEqualTo(PUBKEY); } diff --git a/model/src/testFixtures/java/de/cotto/lndmanagej/model/LocalOpenChannelFixtures.java b/model/src/testFixtures/java/de/cotto/lndmanagej/model/LocalOpenChannelFixtures.java index d13d56e7..89b52b9e 100644 --- a/model/src/testFixtures/java/de/cotto/lndmanagej/model/LocalOpenChannelFixtures.java +++ b/model/src/testFixtures/java/de/cotto/lndmanagej/model/LocalOpenChannelFixtures.java @@ -16,11 +16,58 @@ import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3; public class LocalOpenChannelFixtures { public static final LocalOpenChannel LOCAL_OPEN_CHANNEL = - new LocalOpenChannel(CHANNEL_ID, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_2, BALANCE_INFORMATION, LOCAL); + new LocalOpenChannel( + CHANNEL_ID, + CHANNEL_POINT, + CAPACITY, + PUBKEY, + PUBKEY_2, + BALANCE_INFORMATION, + LOCAL, + false + ); + public static final LocalOpenChannel LOCAL_OPEN_CHANNEL_PRIVATE = + new LocalOpenChannel( + CHANNEL_ID, + CHANNEL_POINT, + CAPACITY, + PUBKEY, + PUBKEY_2, + BALANCE_INFORMATION, + LOCAL, + true + ); public static final LocalOpenChannel LOCAL_OPEN_CHANNEL_2 = - new LocalOpenChannel(CHANNEL_ID_2, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_2, BALANCE_INFORMATION, REMOTE); + new LocalOpenChannel( + CHANNEL_ID_2, + CHANNEL_POINT, + CAPACITY, + PUBKEY, + PUBKEY_2, + BALANCE_INFORMATION, + REMOTE, + false + ); public static final LocalOpenChannel LOCAL_OPEN_CHANNEL_3 = - new LocalOpenChannel(CHANNEL_ID_3, CHANNEL_POINT, CAPACITY, PUBKEY, PUBKEY_2, BALANCE_INFORMATION, LOCAL); + new LocalOpenChannel( + CHANNEL_ID_3, + CHANNEL_POINT, + CAPACITY, + PUBKEY, + PUBKEY_2, + BALANCE_INFORMATION, + LOCAL, + false + ); public static final LocalOpenChannel LOCAL_OPEN_CHANNEL_TO_NODE_3 = - new LocalOpenChannel(CHANNEL_ID_4, CHANNEL_POINT, CAPACITY_2, PUBKEY, PUBKEY_3, BALANCE_INFORMATION, LOCAL); + new LocalOpenChannel( + CHANNEL_ID_4, + CHANNEL_POINT, + CAPACITY_2, + PUBKEY, + PUBKEY_3, + BALANCE_INFORMATION, + LOCAL, + false + ); }