From dede9ea6db000678b64b5a82d3fe24ea84baf74d Mon Sep 17 00:00:00 2001 From: Carsten Otto Date: Wed, 15 Dec 2021 13:16:22 +0100 Subject: [PATCH] add rebalance amounts endpoints, rename controller --- .../lndmanagej/service/RebalanceService.java | 28 +++++++ .../service/RebalanceServiceTest.java | 70 ++++++++++++----- ...lerIT.java => RebalancesControllerIT.java} | 36 ++++++++- ...troller.java => RebalancesController.java} | 31 +++++++- .../OffChainCostsControllerTest.java | 47 ----------- .../controller/RebalancesControllerTest.java | 77 +++++++++++++++++++ 6 files changed, 220 insertions(+), 69 deletions(-) rename web/src/integrationTest/java/de/cotto/lndmanagej/controller/{OffChainCostsControllerIT.java => RebalancesControllerIT.java} (63%) rename web/src/main/java/de/cotto/lndmanagej/controller/{OffChainCostsController.java => RebalancesController.java} (56%) delete mode 100644 web/src/test/java/de/cotto/lndmanagej/controller/OffChainCostsControllerTest.java create mode 100644 web/src/test/java/de/cotto/lndmanagej/controller/RebalancesControllerTest.java diff --git a/backend/src/main/java/de/cotto/lndmanagej/service/RebalanceService.java b/backend/src/main/java/de/cotto/lndmanagej/service/RebalanceService.java index 2598eab5..4180ce7c 100644 --- a/backend/src/main/java/de/cotto/lndmanagej/service/RebalanceService.java +++ b/backend/src/main/java/de/cotto/lndmanagej/service/RebalanceService.java @@ -3,10 +3,12 @@ package de.cotto.lndmanagej.service; import com.codahale.metrics.annotation.Timed; import de.cotto.lndmanagej.model.Channel; import de.cotto.lndmanagej.model.ChannelId; +import de.cotto.lndmanagej.model.Coins; import de.cotto.lndmanagej.model.Pubkey; import de.cotto.lndmanagej.model.SelfPayment; import org.springframework.stereotype.Component; +import java.util.Collection; import java.util.Set; import static java.util.stream.Collectors.toSet; @@ -28,6 +30,11 @@ public class RebalanceService { .collect(toSet()); } + @Timed + public Coins getRebalanceAmountFromChannel(ChannelId channelId) { + return getSumOfAmountPaid(getRebalancesFromChannel(channelId)); + } + @Timed public Set getRebalancesFromPeer(Pubkey pubkey) { return channelService.getAllChannelsWith(pubkey).parallelStream() @@ -37,6 +44,11 @@ public class RebalanceService { .collect(toSet()); } + @Timed + public Coins getRebalanceAmountFromPeer(Pubkey pubkey) { + return getSumOfAmountPaid(getRebalancesFromPeer(pubkey)); + } + @Timed public Set getRebalancesToChannel(ChannelId channelId) { return selfPaymentsService.getSelfPaymentsToChannel(channelId).stream() @@ -44,6 +56,11 @@ public class RebalanceService { .collect(toSet()); } + @Timed + public Coins getRebalanceAmountToChannel(ChannelId channelId) { + return getSumOfAmountPaid(getRebalancesToChannel(channelId)); + } + @Timed public Set getRebalancesToPeer(Pubkey pubkey) { return channelService.getAllChannelsWith(pubkey).parallelStream() @@ -53,6 +70,17 @@ public class RebalanceService { .collect(toSet()); } + @Timed + public Coins getRebalanceAmountToPeer(Pubkey pubkey) { + return getSumOfAmountPaid(getRebalancesToPeer(pubkey)); + } + + private Coins getSumOfAmountPaid(Collection selfPayments) { + return selfPayments.stream() + .map(SelfPayment::amountPaid) + .reduce(Coins.NONE, Coins::add); + } + private boolean memoMentionsChannel(SelfPayment selfPayment, ChannelId expectedChannel) { String memo = selfPayment.memo(); return memo.contains(String.valueOf(expectedChannel.getShortChannelId())) diff --git a/backend/src/test/java/de/cotto/lndmanagej/service/RebalanceServiceTest.java b/backend/src/test/java/de/cotto/lndmanagej/service/RebalanceServiceTest.java index 0109cef8..1edf2648 100644 --- a/backend/src/test/java/de/cotto/lndmanagej/service/RebalanceServiceTest.java +++ b/backend/src/test/java/de/cotto/lndmanagej/service/RebalanceServiceTest.java @@ -50,28 +50,38 @@ class RebalanceServiceTest { @Test void getRebalancesFromPeer() { - ChannelId id1 = LOCAL_OPEN_CHANNEL.getId(); - ChannelId id2 = CLOSED_CHANNEL_2.getId(); - when(channelService.getAllChannelsWith(PUBKEY)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, CLOSED_CHANNEL_2)); - SelfPayment selfPayment1 = getSelfPayment(id1.toString(), 0); - SelfPayment selfPayment2 = getSelfPayment(id2.toString(), 1); - when(selfPaymentsService.getSelfPaymentsFromChannel(id1)).thenReturn(List.of(selfPayment1)); - when(selfPaymentsService.getSelfPaymentsFromChannel(id2)).thenReturn(List.of(selfPayment2)); - assertThat(rebalanceService.getRebalancesFromPeer(PUBKEY)) - .containsExactlyInAnyOrder(selfPayment1, selfPayment2); + Set selfPayments = mockTwoChannelsAndPaymentsFromPeer(); + assertThat(rebalanceService.getRebalancesFromPeer(PUBKEY)).isEqualTo(selfPayments); } @Test void getRebalancesToPeer() { - ChannelId id1 = LOCAL_OPEN_CHANNEL_3.getId(); - ChannelId id2 = CLOSED_CHANNEL_2.getId(); - when(channelService.getAllChannelsWith(PUBKEY)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL_3, CLOSED_CHANNEL_2)); - SelfPayment selfPayment1 = getSelfPayment(id1.toString(), 0); - SelfPayment selfPayment2 = getSelfPayment(id2.toString(), 1); - when(selfPaymentsService.getSelfPaymentsToChannel(id1)).thenReturn(List.of(selfPayment1)); - when(selfPaymentsService.getSelfPaymentsToChannel(id2)).thenReturn(List.of(selfPayment2)); - assertThat(rebalanceService.getRebalancesToPeer(PUBKEY)) - .containsExactlyInAnyOrder(selfPayment1, selfPayment2); + Set selfPayments = mockTwoChannelsAndPaymentsToPeer(); + assertThat(rebalanceService.getRebalancesToPeer(PUBKEY)).isEqualTo(selfPayments); + } + + @Test + void getRebalanceAmountFromPeer() { + mockTwoChannelsAndPaymentsFromPeer(); + assertThat(rebalanceService.getRebalanceAmountFromPeer(PUBKEY)).isEqualTo(AMOUNT_PAID.add(AMOUNT_PAID)); + } + + @Test + void getRebalanceAmountToPeer() { + mockTwoChannelsAndPaymentsToPeer(); + assertThat(rebalanceService.getRebalanceAmountToPeer(PUBKEY)).isEqualTo(AMOUNT_PAID.add(AMOUNT_PAID)); + } + + @Test + void getRebalanceAmountFromChannel() { + mockSelfPaymentsFromChannel("from " + CHANNEL_ID.getShortChannelId()); + assertThat(rebalanceService.getRebalanceAmountFromChannel(CHANNEL_ID)).isEqualTo(AMOUNT_PAID.add(AMOUNT_PAID)); + } + + @Test + void getRebalanceAmountToChannel() { + mockSelfPaymentsToChannel("to " + CHANNEL_ID_2.getShortChannelId()); + assertThat(rebalanceService.getRebalanceAmountToChannel(CHANNEL_ID_2)).isEqualTo(AMOUNT_PAID.add(AMOUNT_PAID)); } @Test @@ -197,4 +207,28 @@ class RebalanceServiceTest { PaymentRoute route = new PaymentRoute(List.of(firstHop, lastHop)); return List.of(route); } + + private Set mockTwoChannelsAndPaymentsToPeer() { + ChannelId id1 = LOCAL_OPEN_CHANNEL_3.getId(); + ChannelId id2 = CLOSED_CHANNEL_2.getId(); + when(channelService.getAllChannelsWith(PUBKEY)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL_3, CLOSED_CHANNEL_2)); + SelfPayment selfPayment1 = getSelfPayment(id1.toString(), 0); + SelfPayment selfPayment2 = getSelfPayment(id2.toString(), 1); + Set selfPayments = Set.of(selfPayment1, selfPayment2); + when(selfPaymentsService.getSelfPaymentsToChannel(id1)).thenReturn(List.of(selfPayment1)); + when(selfPaymentsService.getSelfPaymentsToChannel(id2)).thenReturn(List.of(selfPayment2)); + return selfPayments; + } + + private Set mockTwoChannelsAndPaymentsFromPeer() { + ChannelId id1 = LOCAL_OPEN_CHANNEL.getId(); + ChannelId id2 = CLOSED_CHANNEL_2.getId(); + when(channelService.getAllChannelsWith(PUBKEY)).thenReturn(Set.of(LOCAL_OPEN_CHANNEL, CLOSED_CHANNEL_2)); + SelfPayment selfPayment1 = getSelfPayment(id1.toString(), 0); + SelfPayment selfPayment2 = getSelfPayment(id2.toString(), 1); + Set selfPayments = Set.of(selfPayment1, selfPayment2); + when(selfPaymentsService.getSelfPaymentsFromChannel(id1)).thenReturn(List.of(selfPayment1)); + when(selfPaymentsService.getSelfPaymentsFromChannel(id2)).thenReturn(List.of(selfPayment2)); + return selfPayments; + } } \ No newline at end of file diff --git a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/OffChainCostsControllerIT.java b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/RebalancesControllerIT.java similarity index 63% rename from web/src/integrationTest/java/de/cotto/lndmanagej/controller/OffChainCostsControllerIT.java rename to web/src/integrationTest/java/de/cotto/lndmanagej/controller/RebalancesControllerIT.java index 2d597a3e..c2ce84a4 100644 --- a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/OffChainCostsControllerIT.java +++ b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/RebalancesControllerIT.java @@ -3,6 +3,7 @@ package de.cotto.lndmanagej.controller; import de.cotto.lndmanagej.model.ChannelIdResolver; import de.cotto.lndmanagej.model.Coins; import de.cotto.lndmanagej.service.OffChainCostService; +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; @@ -15,8 +16,8 @@ import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -@WebMvcTest(controllers = OffChainCostsController.class) -class OffChainCostsControllerIT { +@WebMvcTest(controllers = RebalancesController.class) +class RebalancesControllerIT { private static final String CHANNEL_PREFIX = "/api/channel/" + CHANNEL_ID.getShortChannelId() + "/"; private static final String NODE_PREFIX = "/api/node/" + PUBKEY + "/"; @@ -30,6 +31,9 @@ class OffChainCostsControllerIT { @MockBean private OffChainCostService offChainCostService; + @MockBean + private RebalanceService rebalanceService; + @Test void getRebalanceSourceCostsForChannel() throws Exception { when(offChainCostService.getRebalanceSourceCostsForChannel(CHANNEL_ID)).thenReturn(Coins.ofMilliSatoshis(123)); @@ -37,6 +41,13 @@ class OffChainCostsControllerIT { .andExpect(content().string("123")); } + @Test + void getRebalanceSourceAmountForChannel() throws Exception { + when(rebalanceService.getRebalanceAmountFromChannel(CHANNEL_ID)).thenReturn(Coins.ofMilliSatoshis(456)); + mockMvc.perform(get(CHANNEL_PREFIX + "/rebalance-source-amount/")) + .andExpect(content().string("456")); + } + @Test void getRebalanceSourceCostsForPeer() throws Exception { when(offChainCostService.getRebalanceSourceCostsForPeer(PUBKEY)).thenReturn(Coins.ofMilliSatoshis(124)); @@ -44,6 +55,13 @@ class OffChainCostsControllerIT { .andExpect(content().string("124")); } + @Test + void getRebalanceSourceAmountForPeer() throws Exception { + when(rebalanceService.getRebalanceAmountFromPeer(PUBKEY)).thenReturn(Coins.ofMilliSatoshis(666)); + mockMvc.perform(get(NODE_PREFIX + "/rebalance-source-amount/")) + .andExpect(content().string("666")); + } + @Test void getRebalanceTargetCostsForChannel() throws Exception { when(offChainCostService.getRebalanceTargetCostsForChannel(CHANNEL_ID)).thenReturn(Coins.ofMilliSatoshis(125)); @@ -51,10 +69,24 @@ class OffChainCostsControllerIT { .andExpect(content().string("125")); } + @Test + void getRebalanceTargetAmountForChannel() throws Exception { + when(rebalanceService.getRebalanceAmountToChannel(CHANNEL_ID)).thenReturn(Coins.ofMilliSatoshis(7777)); + mockMvc.perform(get(CHANNEL_PREFIX + "/rebalance-target-amount/")) + .andExpect(content().string("7777")); + } + @Test void getRebalanceTargetCostsForPeer() throws Exception { when(offChainCostService.getRebalanceTargetCostsForPeer(PUBKEY)).thenReturn(Coins.ofMilliSatoshis(126)); mockMvc.perform(get(NODE_PREFIX + "/rebalance-target-costs/")) .andExpect(content().string("126")); } + + @Test + void getRebalanceTargetAmountForPeer() throws Exception { + when(rebalanceService.getRebalanceAmountToPeer(PUBKEY)).thenReturn(Coins.ofMilliSatoshis(999)); + mockMvc.perform(get(NODE_PREFIX + "/rebalance-target-amount/")) + .andExpect(content().string("999")); + } } \ No newline at end of file diff --git a/web/src/main/java/de/cotto/lndmanagej/controller/OffChainCostsController.java b/web/src/main/java/de/cotto/lndmanagej/controller/RebalancesController.java similarity index 56% rename from web/src/main/java/de/cotto/lndmanagej/controller/OffChainCostsController.java rename to web/src/main/java/de/cotto/lndmanagej/controller/RebalancesController.java index 0d061663..36d8dee8 100644 --- a/web/src/main/java/de/cotto/lndmanagej/controller/OffChainCostsController.java +++ b/web/src/main/java/de/cotto/lndmanagej/controller/RebalancesController.java @@ -4,6 +4,7 @@ import com.codahale.metrics.annotation.Timed; import de.cotto.lndmanagej.model.ChannelId; import de.cotto.lndmanagej.model.Pubkey; import de.cotto.lndmanagej.service.OffChainCostService; +import de.cotto.lndmanagej.service.RebalanceService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -11,11 +12,13 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/") -public class OffChainCostsController { +public class RebalancesController { private final OffChainCostService offChainCostService; + private final RebalanceService rebalanceService; - public OffChainCostsController(OffChainCostService offChainCostService) { + public RebalancesController(OffChainCostService offChainCostService, RebalanceService rebalanceService) { this.offChainCostService = offChainCostService; + this.rebalanceService = rebalanceService; } @Timed @@ -24,21 +27,45 @@ public class OffChainCostsController { return offChainCostService.getRebalanceSourceCostsForPeer(pubkey).milliSatoshis(); } + @Timed + @GetMapping("/node/{pubkey}/rebalance-source-amount") + public long getRebalanceSourceAmountForPeer(@PathVariable Pubkey pubkey) { + return rebalanceService.getRebalanceAmountFromPeer(pubkey).milliSatoshis(); + } + @Timed @GetMapping("/channel/{channelId}/rebalance-source-costs") public long getRebalanceSourceCostsForChannel(@PathVariable ChannelId channelId) { return offChainCostService.getRebalanceSourceCostsForChannel(channelId).milliSatoshis(); } + @Timed + @GetMapping("/channel/{channelId}/rebalance-source-amount") + public long getRebalanceSourceAmountForChannel(@PathVariable ChannelId channelId) { + return rebalanceService.getRebalanceAmountFromChannel(channelId).milliSatoshis(); + } + @Timed @GetMapping("/node/{pubkey}/rebalance-target-costs") public long getRebalanceTargetCostsForPeer(@PathVariable Pubkey pubkey) { return offChainCostService.getRebalanceTargetCostsForPeer(pubkey).milliSatoshis(); } + @Timed + @GetMapping("/node/{pubkey}/rebalance-target-amount") + public long getRebalanceTargetAmountForPeer(@PathVariable Pubkey pubkey) { + return rebalanceService.getRebalanceAmountToPeer(pubkey).milliSatoshis(); + } + @Timed @GetMapping("/channel/{channelId}/rebalance-target-costs") public long getRebalanceTargetCostsForChannel(@PathVariable ChannelId channelId) { return offChainCostService.getRebalanceTargetCostsForChannel(channelId).milliSatoshis(); } + + @Timed + @GetMapping("/channel/{channelId}/rebalance-target-amount") + public long getRebalanceTargetAmountForChannel(@PathVariable ChannelId channelId) { + return rebalanceService.getRebalanceAmountToChannel(channelId).milliSatoshis(); + } } diff --git a/web/src/test/java/de/cotto/lndmanagej/controller/OffChainCostsControllerTest.java b/web/src/test/java/de/cotto/lndmanagej/controller/OffChainCostsControllerTest.java deleted file mode 100644 index acaa529d..00000000 --- a/web/src/test/java/de/cotto/lndmanagej/controller/OffChainCostsControllerTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package de.cotto.lndmanagej.controller; - -import de.cotto.lndmanagej.model.Coins; -import de.cotto.lndmanagej.service.OffChainCostService; -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 static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; -import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class OffChainCostsControllerTest { - @InjectMocks - private OffChainCostsController offChainCostsController; - - @Mock - private OffChainCostService offChainCostService; - - @Test - void getRebalanceSourceCostsForChannel() { - when(offChainCostService.getRebalanceSourceCostsForChannel(CHANNEL_ID)).thenReturn(Coins.ofMilliSatoshis(123)); - assertThat(offChainCostsController.getRebalanceSourceCostsForChannel(CHANNEL_ID)).isEqualTo(123); - } - - @Test - void getRebalanceSourceCostsForPeer() { - when(offChainCostService.getRebalanceSourceCostsForPeer(PUBKEY)).thenReturn(Coins.ofMilliSatoshis(123)); - assertThat(offChainCostsController.getRebalanceSourceCostsForPeer(PUBKEY)).isEqualTo(123); - } - - @Test - void getRebalanceTargetCostsForChannel() { - when(offChainCostService.getRebalanceTargetCostsForChannel(CHANNEL_ID)).thenReturn(Coins.ofMilliSatoshis(123)); - assertThat(offChainCostsController.getRebalanceTargetCostsForChannel(CHANNEL_ID)).isEqualTo(123); - } - - @Test - void getRebalanceTargetCostsForPeer() { - when(offChainCostService.getRebalanceTargetCostsForPeer(PUBKEY)).thenReturn(Coins.ofMilliSatoshis(123)); - assertThat(offChainCostsController.getRebalanceTargetCostsForPeer(PUBKEY)).isEqualTo(123); - } -} \ No newline at end of file diff --git a/web/src/test/java/de/cotto/lndmanagej/controller/RebalancesControllerTest.java b/web/src/test/java/de/cotto/lndmanagej/controller/RebalancesControllerTest.java new file mode 100644 index 00000000..d6290639 --- /dev/null +++ b/web/src/test/java/de/cotto/lndmanagej/controller/RebalancesControllerTest.java @@ -0,0 +1,77 @@ +package de.cotto.lndmanagej.controller; + +import de.cotto.lndmanagej.model.Coins; +import de.cotto.lndmanagej.service.OffChainCostService; +import de.cotto.lndmanagej.service.RebalanceService; +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 static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class RebalancesControllerTest { + private static final Coins COINS = Coins.ofMilliSatoshis(123); + + @InjectMocks + private RebalancesController rebalancesController; + + @Mock + private OffChainCostService offChainCostService; + + @Mock + private RebalanceService rebalanceService; + + @Test + void getRebalanceSourceCostsForChannel() { + when(offChainCostService.getRebalanceSourceCostsForChannel(CHANNEL_ID)).thenReturn(COINS); + assertThat(rebalancesController.getRebalanceSourceCostsForChannel(CHANNEL_ID)).isEqualTo(123); + } + + @Test + void getRebalanceSourceCostsForPeer() { + when(offChainCostService.getRebalanceSourceCostsForPeer(PUBKEY)).thenReturn(COINS); + assertThat(rebalancesController.getRebalanceSourceCostsForPeer(PUBKEY)).isEqualTo(123); + } + + @Test + void getRebalanceTargetCostsForChannel() { + when(offChainCostService.getRebalanceTargetCostsForChannel(CHANNEL_ID)).thenReturn(COINS); + assertThat(rebalancesController.getRebalanceTargetCostsForChannel(CHANNEL_ID)).isEqualTo(123); + } + + @Test + void getRebalanceTargetCostsForPeer() { + when(offChainCostService.getRebalanceTargetCostsForPeer(PUBKEY)).thenReturn(COINS); + assertThat(rebalancesController.getRebalanceTargetCostsForPeer(PUBKEY)).isEqualTo(123); + } + + @Test + void getRebalanceSourceAmountForChannel() { + when(rebalanceService.getRebalanceAmountFromChannel(CHANNEL_ID)).thenReturn(COINS); + assertThat(rebalancesController.getRebalanceSourceAmountForChannel(CHANNEL_ID)).isEqualTo(123); + } + + @Test + void getRebalanceSourceAmountForPeer() { + when(rebalanceService.getRebalanceAmountFromPeer(PUBKEY)).thenReturn(COINS); + assertThat(rebalancesController.getRebalanceSourceAmountForPeer(PUBKEY)).isEqualTo(123); + } + + @Test + void getRebalanceTargetAmountForChannel() { + when(rebalanceService.getRebalanceAmountToChannel(CHANNEL_ID)).thenReturn(COINS); + assertThat(rebalancesController.getRebalanceTargetAmountForChannel(CHANNEL_ID)).isEqualTo(123); + } + + @Test + void getRebalanceTargetAmountForPeer() { + when(rebalanceService.getRebalanceAmountToPeer(PUBKEY)).thenReturn(COINS); + assertThat(rebalancesController.getRebalanceTargetAmountForPeer(PUBKEY)).isEqualTo(123); + } +} \ No newline at end of file