mirror of
https://github.com/aljazceru/lnd-manageJ.git
synced 2026-01-21 06:54:29 +01:00
add self payments endpoints
This commit is contained in:
@@ -8,6 +8,7 @@ dependencies {
|
||||
runtimeOnly project(':invoices')
|
||||
runtimeOnly project(':payments')
|
||||
runtimeOnly project(':statistics')
|
||||
runtimeOnly project(':selfpayments')
|
||||
runtimeOnly 'org.postgresql:postgresql'
|
||||
testRuntimeOnly 'com.h2database:h2'
|
||||
testImplementation project(':backend')
|
||||
|
||||
@@ -8,6 +8,7 @@ dependencies {
|
||||
implementation project(':grpc-adapter')
|
||||
implementation project(':model')
|
||||
implementation project(':transactions')
|
||||
implementation project(':selfpayments')
|
||||
testImplementation testFixtures(project(':model'))
|
||||
testImplementation testFixtures(project(':transactions'))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.cotto.lndmanagej.service;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.model.SelfPayment;
|
||||
import de.cotto.lndmanagej.selfpayments.SelfPaymentsDao;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class SelfPaymentsService {
|
||||
private final SelfPaymentsDao dao;
|
||||
|
||||
public SelfPaymentsService(SelfPaymentsDao dao) {
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
public List<SelfPayment> getSelfPaymentsToChannel(ChannelId channelId) {
|
||||
return dao.getSelfPaymentsToChannel(channelId);
|
||||
}
|
||||
|
||||
public List<SelfPayment> getSelfPaymentsFromChannel(ChannelId channelId) {
|
||||
return dao.getSelfPaymentsFromChannel(channelId).stream().distinct().toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package de.cotto.lndmanagej.service;
|
||||
|
||||
import de.cotto.lndmanagej.selfpayments.SelfPaymentsDao;
|
||||
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.List;
|
||||
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class SelfPaymentsServiceTest {
|
||||
@InjectMocks
|
||||
private SelfPaymentsService selfPaymentsService;
|
||||
|
||||
@Mock
|
||||
private SelfPaymentsDao selfPaymentsDao;
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsToChannel() {
|
||||
when(selfPaymentsDao.getSelfPaymentsToChannel(CHANNEL_ID)).thenReturn(List.of(SELF_PAYMENT));
|
||||
assertThat(selfPaymentsService.getSelfPaymentsToChannel(CHANNEL_ID)).containsExactly(SELF_PAYMENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsFromChannel() {
|
||||
when(selfPaymentsDao.getSelfPaymentsFromChannel(CHANNEL_ID)).thenReturn(List.of(SELF_PAYMENT));
|
||||
assertThat(selfPaymentsService.getSelfPaymentsFromChannel(CHANNEL_ID)).containsExactly(SELF_PAYMENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsFromChannel_no_duplicates() {
|
||||
when(selfPaymentsDao.getSelfPaymentsFromChannel(CHANNEL_ID)).thenReturn(List.of(SELF_PAYMENT, SELF_PAYMENT));
|
||||
assertThat(selfPaymentsService.getSelfPaymentsFromChannel(CHANNEL_ID)).containsExactly(SELF_PAYMENT);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import lnrpc.ListInvoiceResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.HexFormat;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -19,6 +18,8 @@ import java.util.Spliterators;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
|
||||
@Component
|
||||
public class GrpcInvoices {
|
||||
private static final int LIMIT = 1_000;
|
||||
@@ -62,7 +63,7 @@ public class GrpcInvoices {
|
||||
return new SettledInvoice(
|
||||
lndInvoice.getAddIndex(),
|
||||
lndInvoice.getSettleIndex(),
|
||||
LocalDateTime.ofEpochSecond(lndInvoice.getSettleDate(), 0, ZoneOffset.UTC),
|
||||
LocalDateTime.ofEpochSecond(lndInvoice.getSettleDate(), 0, UTC).atZone(UTC),
|
||||
HEX_FORMAT.formatHex(lndInvoice.getRHash().toByteArray()),
|
||||
Coins.ofMilliSatoshis(lndInvoice.getAmtPaidMsat()),
|
||||
lndInvoice.getMemo(),
|
||||
|
||||
@@ -13,7 +13,6 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Collections;
|
||||
import java.util.HexFormat;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -250,7 +249,7 @@ class GrpcInvoicesTest {
|
||||
.setSettleIndex(settledInvoice.settleIndex())
|
||||
.setRHash(ByteString.copyFrom(HEX_FORMAT.parseHex(settledInvoice.hash())))
|
||||
.setMemo(settledInvoice.memo())
|
||||
.setSettleDate(settledInvoice.settleDate().toEpochSecond(ZoneOffset.UTC))
|
||||
.setSettleDate(settledInvoice.settleDate().toEpochSecond())
|
||||
.setAmtPaidMsat(settledInvoice.amountPaid().milliSatoshis())
|
||||
.addHtlcs(htlc)
|
||||
.build();
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
@@ -59,7 +60,7 @@ class SettledInvoicesRepositoryIT {
|
||||
return SettledInvoiceJpaDto.createFromModel(new SettledInvoice(
|
||||
addIndex,
|
||||
settleIndex,
|
||||
LocalDateTime.MIN,
|
||||
LocalDateTime.MIN.atZone(ZoneOffset.UTC),
|
||||
"",
|
||||
Coins.NONE,
|
||||
"",
|
||||
|
||||
@@ -11,10 +11,12 @@ import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
|
||||
@Entity
|
||||
@Table(name = "settled_invoices", indexes = {@Index(unique = true, columnList = "settleIndex")})
|
||||
public class SettledInvoiceJpaDto {
|
||||
@@ -47,7 +49,7 @@ public class SettledInvoiceJpaDto {
|
||||
SettledInvoiceJpaDto jpaDto = new SettledInvoiceJpaDto();
|
||||
jpaDto.addIndex = settledInvoice.addIndex();
|
||||
jpaDto.settleIndex = settledInvoice.settleIndex();
|
||||
jpaDto.settleDate = settledInvoice.settleDate().toEpochSecond(ZoneOffset.UTC);
|
||||
jpaDto.settleDate = settledInvoice.settleDate().toEpochSecond();
|
||||
jpaDto.hash = settledInvoice.hash();
|
||||
jpaDto.amountPaid = settledInvoice.amountPaid().milliSatoshis();
|
||||
jpaDto.memo = settledInvoice.memo();
|
||||
@@ -57,7 +59,7 @@ public class SettledInvoiceJpaDto {
|
||||
}
|
||||
|
||||
public SettledInvoice toModel() {
|
||||
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(settleDate, 0, ZoneOffset.UTC);
|
||||
ZonedDateTime dateTime = LocalDateTime.ofEpochSecond(settleDate, 0, UTC).atZone(UTC);
|
||||
Optional<ChannelId> channelId;
|
||||
if (receivedVia > 0) {
|
||||
channelId = Optional.of(ChannelId.fromShortChannelId(receivedVia));
|
||||
@@ -67,7 +69,7 @@ public class SettledInvoiceJpaDto {
|
||||
return new SettledInvoice(
|
||||
addIndex,
|
||||
settleIndex,
|
||||
localDateTime,
|
||||
dateTime,
|
||||
Objects.requireNonNull(hash),
|
||||
Coins.ofMilliSatoshis(amountPaid),
|
||||
Objects.requireNonNull(memo),
|
||||
|
||||
@@ -4,10 +4,10 @@ import de.cotto.lndmanagej.model.SettledInvoice;
|
||||
import de.cotto.lndmanagej.model.SettledInvoiceFixtures;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
|
||||
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.SettledInvoiceFixtures.KEYSEND_MESSAGE;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE_KEYSEND;
|
||||
@@ -21,13 +21,12 @@ class SettledSettledInvoiceJpaDtoTest {
|
||||
SettledInvoiceJpaDto jpaDto = SettledInvoiceJpaDto.createFromModel(SETTLED_INVOICE);
|
||||
assertThat(jpaDto.getAddIndex()).isEqualTo(SETTLED_INVOICE.addIndex());
|
||||
assertThat(jpaDto.getSettleIndex()).isEqualTo(SETTLED_INVOICE.settleIndex());
|
||||
assertThat(jpaDto.getSettleDate())
|
||||
.isEqualTo(SETTLED_INVOICE.settleDate().toEpochSecond(ZoneOffset.UTC));
|
||||
assertThat(jpaDto.getSettleDate()).isEqualTo(SETTLED_INVOICE.settleDate().toEpochSecond());
|
||||
assertThat(jpaDto.getHash()).isEqualTo(SETTLED_INVOICE.hash());
|
||||
assertThat(jpaDto.getAmountPaid()).isEqualTo(SETTLED_INVOICE.amountPaid().milliSatoshis());
|
||||
assertThat(jpaDto.getMemo()).isEqualTo(SETTLED_INVOICE.memo());
|
||||
assertThat(jpaDto.getKeysendMessage()).isNull();
|
||||
assertThat(jpaDto.getReceivedVia()).isEqualTo(CHANNEL_ID.getShortChannelId());
|
||||
assertThat(jpaDto.getReceivedVia()).isEqualTo(CHANNEL_ID_2.getShortChannelId());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.cotto.lndmanagej.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public record Payment(
|
||||
long index,
|
||||
@@ -11,4 +12,7 @@ public record Payment(
|
||||
Coins fees,
|
||||
List<PaymentRoute> routes
|
||||
) {
|
||||
public Optional<ChannelId> getFirstChannel() {
|
||||
return routes.stream().flatMap(route -> route.hops().stream()).map(PaymentHop::channelId).findFirst();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package de.cotto.lndmanagej.model;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
public record SelfPayment(
|
||||
String memo,
|
||||
ZonedDateTime settleDate,
|
||||
Coins value,
|
||||
Coins fees,
|
||||
Optional<ChannelId> firstChannel,
|
||||
Optional<ChannelId> lastChannel
|
||||
) {
|
||||
public SelfPayment(Payment payment, SettledInvoice settledInvoice) {
|
||||
this(
|
||||
settledInvoice.memo(),
|
||||
settledInvoice.settleDate(),
|
||||
payment.value(),
|
||||
payment.fees(),
|
||||
payment.getFirstChannel(),
|
||||
settledInvoice.receivedVia()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
package de.cotto.lndmanagej.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
public record SettledInvoice(
|
||||
long addIndex,
|
||||
long settleIndex,
|
||||
LocalDateTime settleDate,
|
||||
ZonedDateTime settleDate,
|
||||
String hash,
|
||||
Coins amountPaid,
|
||||
String memo,
|
||||
@@ -16,7 +18,7 @@ public record SettledInvoice(
|
||||
public static final SettledInvoice INVALID = new SettledInvoice(
|
||||
-1,
|
||||
-1,
|
||||
LocalDateTime.MIN,
|
||||
LocalDateTime.MIN.atZone(ZoneOffset.UTC),
|
||||
"",
|
||||
Coins.NONE,
|
||||
"",
|
||||
|
||||
@@ -2,18 +2,18 @@ package de.cotto.lndmanagej.model;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_4;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_4;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PaymentHopTest {
|
||||
@Test
|
||||
void channelId() {
|
||||
assertThat(PAYMENT_HOP.channelId()).isEqualTo(CHANNEL_ID);
|
||||
assertThat(PAYMENT_HOP_CHANNEL_4.channelId()).isEqualTo(CHANNEL_ID_4);
|
||||
}
|
||||
|
||||
@Test
|
||||
void amount() {
|
||||
assertThat(PAYMENT_HOP.amount()).isEqualTo(Coins.ofSatoshis(1));
|
||||
assertThat(PAYMENT_HOP_CHANNEL_4.amount()).isEqualTo(Coins.ofSatoshis(4));
|
||||
}
|
||||
}
|
||||
@@ -4,16 +4,18 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_3;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_3;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_4;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE_4_TO_2;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PaymentRouteTest {
|
||||
@Test
|
||||
void hops() {
|
||||
assertThat(PAYMENT_ROUTE.hops()).isEqualTo(List.of(PAYMENT_HOP, PAYMENT_HOP_2, PAYMENT_HOP_3));
|
||||
assertThat(PAYMENT_ROUTE_4_TO_2.hops()).isEqualTo(
|
||||
List.of(PAYMENT_HOP_CHANNEL_4, PAYMENT_HOP_CHANNEL_3, PAYMENT_HOP_CHANNEL_2)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_4;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_CREATION_DATE_TIME;
|
||||
@@ -11,8 +12,8 @@ import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_FEES;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_HASH;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_INDEX;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_VALUE;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE_3_TO_1;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE_4_TO_1;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PaymentTest {
|
||||
@@ -43,6 +44,11 @@ class PaymentTest {
|
||||
|
||||
@Test
|
||||
void routes() {
|
||||
assertThat(PAYMENT_2.routes()).isEqualTo(List.of(PAYMENT_ROUTE, PAYMENT_ROUTE_2));
|
||||
assertThat(PAYMENT_2.routes()).isEqualTo(List.of(PAYMENT_ROUTE_4_TO_1, PAYMENT_ROUTE_3_TO_1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFirstChannel() {
|
||||
assertThat(PAYMENT.getFirstChannel()).contains(CHANNEL_ID_4);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package de.cotto.lndmanagej.model;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT;
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_2;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE_2;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class SelfPaymentTest {
|
||||
@Test
|
||||
void memo() {
|
||||
assertThat(SELF_PAYMENT.memo()).isEqualTo(SETTLED_INVOICE.memo());
|
||||
}
|
||||
|
||||
@Test
|
||||
void settleDate() {
|
||||
assertThat(SELF_PAYMENT_2.settleDate()).isEqualTo(SETTLED_INVOICE_2.settleDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
void value() {
|
||||
assertThat(SELF_PAYMENT_2.value()).isEqualTo(PAYMENT_2.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void fees() {
|
||||
assertThat(SELF_PAYMENT_2.fees()).isEqualTo(PAYMENT_2.fees());
|
||||
}
|
||||
|
||||
@Test
|
||||
void firstChannel() {
|
||||
assertThat(SELF_PAYMENT_2.firstChannel()).isEqualTo(PAYMENT_2.getFirstChannel());
|
||||
}
|
||||
|
||||
@Test
|
||||
void lastChannel() {
|
||||
assertThat(SELF_PAYMENT_2.lastChannel()).isEqualTo(SETTLED_INVOICE_2.receivedVia());
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,10 @@ package de.cotto.lndmanagej.model;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
|
||||
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.SettledInvoiceFixtures.ADD_INDEX;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.AMOUNT_PAID;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.HASH;
|
||||
@@ -23,7 +24,7 @@ class SettledInvoiceTest {
|
||||
SettledInvoice expected = new SettledInvoice(
|
||||
-1,
|
||||
-1,
|
||||
LocalDateTime.MIN,
|
||||
LocalDateTime.MIN.atZone(ZoneOffset.UTC),
|
||||
"",
|
||||
Coins.NONE,
|
||||
"",
|
||||
@@ -81,6 +82,6 @@ class SettledInvoiceTest {
|
||||
|
||||
@Test
|
||||
void receivedVia() {
|
||||
assertThat(SETTLED_INVOICE.receivedVia()).contains(CHANNEL_ID);
|
||||
assertThat(SETTLED_INVOICE.receivedVia()).contains(CHANNEL_ID_2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.cotto.lndmanagej;
|
||||
|
||||
import de.cotto.lndmanagej.model.SelfPayment;
|
||||
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_2;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE_2;
|
||||
|
||||
public class SelfPaymentFixtures {
|
||||
public static final SelfPayment SELF_PAYMENT = new SelfPayment(PAYMENT, SETTLED_INVOICE);
|
||||
public static final SelfPayment SELF_PAYMENT_2 = new SelfPayment(PAYMENT_2, SETTLED_INVOICE_2);
|
||||
}
|
||||
@@ -3,25 +3,33 @@ package de.cotto.lndmanagej.model;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE_3_TO_1;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE_4_TO_1;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE_4_TO_2;
|
||||
|
||||
public class PaymentFixtures {
|
||||
public static final int PAYMENT_INDEX = 2;
|
||||
public static final int PAYMENT_INDEX_2 = 3;
|
||||
public static final String PAYMENT_HASH = "abc";
|
||||
public static final int PAYMENT_INDEX_3 = 4;
|
||||
public static final String PAYMENT_HASH = "1234";
|
||||
public static final String PAYMENT_HASH_2 = "aaa0";
|
||||
public static final String PAYMENT_HASH_3 = "aaa1";
|
||||
public static final Coins PAYMENT_VALUE = Coins.ofSatoshis(1_000_000);
|
||||
public static final Coins PAYMENT_FEES = Coins.ofMilliSatoshis(10);
|
||||
private static final List<PaymentRoute> ONE_ROUTE = List.of(PAYMENT_ROUTE);
|
||||
private static final List<PaymentRoute> TWO_ROUTES = List.of(PAYMENT_ROUTE, PAYMENT_ROUTE_2);
|
||||
private static final List<PaymentRoute> ONE_ROUTE_4_TO_2 = List.of(PAYMENT_ROUTE_4_TO_2);
|
||||
private static final List<PaymentRoute> TWO_ROUTES = List.of(PAYMENT_ROUTE_4_TO_1, PAYMENT_ROUTE_3_TO_1);
|
||||
public static final LocalDateTime PAYMENT_CREATION_DATE_TIME =
|
||||
LocalDateTime.of(2021, 12, 5, 22, 22, 22, 500_000_000);
|
||||
|
||||
public static final Payment PAYMENT = new Payment(
|
||||
PAYMENT_INDEX, PAYMENT_HASH, PAYMENT_CREATION_DATE_TIME, PAYMENT_VALUE, PAYMENT_FEES, ONE_ROUTE
|
||||
PAYMENT_INDEX, PAYMENT_HASH, PAYMENT_CREATION_DATE_TIME, PAYMENT_VALUE, PAYMENT_FEES, ONE_ROUTE_4_TO_2
|
||||
);
|
||||
|
||||
public static final Payment PAYMENT_2 = new Payment(
|
||||
PAYMENT_INDEX_2, PAYMENT_HASH, PAYMENT_CREATION_DATE_TIME, PAYMENT_VALUE, PAYMENT_FEES, TWO_ROUTES
|
||||
PAYMENT_INDEX_2, PAYMENT_HASH_2, PAYMENT_CREATION_DATE_TIME, PAYMENT_VALUE, PAYMENT_FEES, TWO_ROUTES
|
||||
);
|
||||
|
||||
public static final Payment PAYMENT_3 = new Payment(
|
||||
PAYMENT_INDEX_3, PAYMENT_HASH_3, PAYMENT_CREATION_DATE_TIME, PAYMENT_VALUE, PAYMENT_FEES, TWO_ROUTES
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ package de.cotto.lndmanagej.model;
|
||||
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;
|
||||
|
||||
public class PaymentHopFixtures {
|
||||
public static final PaymentHop PAYMENT_HOP = new PaymentHop(CHANNEL_ID, Coins.ofSatoshis(1));
|
||||
public static final PaymentHop PAYMENT_HOP_2 = new PaymentHop(CHANNEL_ID_2, Coins.ofSatoshis(2));
|
||||
public static final PaymentHop PAYMENT_HOP_3 = new PaymentHop(CHANNEL_ID_3, Coins.ofSatoshis(3));
|
||||
public static final PaymentHop PAYMENT_HOP_CHANNEL_1 = new PaymentHop(CHANNEL_ID, Coins.ofSatoshis(1));
|
||||
public static final PaymentHop PAYMENT_HOP_CHANNEL_2 = new PaymentHop(CHANNEL_ID_2, Coins.ofSatoshis(2));
|
||||
public static final PaymentHop PAYMENT_HOP_CHANNEL_3 = new PaymentHop(CHANNEL_ID_3, Coins.ofSatoshis(3));
|
||||
public static final PaymentHop PAYMENT_HOP_CHANNEL_4 = new PaymentHop(CHANNEL_ID_4, Coins.ofSatoshis(4));
|
||||
}
|
||||
|
||||
@@ -2,13 +2,16 @@ package de.cotto.lndmanagej.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_3;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_1;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_3;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_4;
|
||||
|
||||
public class PaymentRouteFixtures {
|
||||
public static final PaymentRoute PAYMENT_ROUTE =
|
||||
new PaymentRoute(List.of(PAYMENT_HOP, PAYMENT_HOP_2, PAYMENT_HOP_3));
|
||||
public static final PaymentRoute PAYMENT_ROUTE_2 =
|
||||
new PaymentRoute(List.of(PAYMENT_HOP, PAYMENT_HOP_2));
|
||||
public static final PaymentRoute PAYMENT_ROUTE_4_TO_2 =
|
||||
new PaymentRoute(List.of(PAYMENT_HOP_CHANNEL_4, PAYMENT_HOP_CHANNEL_3, PAYMENT_HOP_CHANNEL_2));
|
||||
public static final PaymentRoute PAYMENT_ROUTE_4_TO_1 =
|
||||
new PaymentRoute(List.of(PAYMENT_HOP_CHANNEL_4, PAYMENT_HOP_CHANNEL_3, PAYMENT_HOP_CHANNEL_1));
|
||||
public static final PaymentRoute PAYMENT_ROUTE_3_TO_1 =
|
||||
new PaymentRoute(List.of(PAYMENT_HOP_CHANNEL_3, PAYMENT_HOP_CHANNEL_1));
|
||||
}
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
package de.cotto.lndmanagej.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
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;
|
||||
|
||||
public class SettledInvoiceFixtures {
|
||||
public static final LocalDateTime SETTLE_DATE = LocalDateTime.of(2021, 12, 2, 16, 4, 30);
|
||||
public static final ZonedDateTime SETTLE_DATE = ZonedDateTime.of(2021, 12, 2, 16, 4, 30, 0, ZoneOffset.UTC);
|
||||
public static final int ADD_INDEX = 2;
|
||||
public static final int ADD_INDEX_2 = 1;
|
||||
public static final int ADD_INDEX_3 = 3;
|
||||
public static final int SETTLE_INDEX = 1;
|
||||
public static final int SETTLE_INDEX_2 = 2;
|
||||
public static final int SETTLE_INDEX_3 = 3;
|
||||
public static final String HASH = "1234";
|
||||
public static final String HASH_2 = "aaa0";
|
||||
public static final String HASH_3 = "010101";
|
||||
public static final Coins AMOUNT_PAID = Coins.ofMilliSatoshis(123);
|
||||
public static final Coins AMOUNT_PAID_2 = Coins.ofMilliSatoshis(4_567);
|
||||
public static final String MEMO = "this is a memo";
|
||||
@@ -27,7 +33,7 @@ public class SettledInvoiceFixtures {
|
||||
AMOUNT_PAID,
|
||||
MEMO,
|
||||
Optional.empty(),
|
||||
Optional.of(CHANNEL_ID)
|
||||
Optional.of(CHANNEL_ID_2)
|
||||
);
|
||||
|
||||
public static final SettledInvoice SETTLED_INVOICE_NO_CHANNEL_ID = new SettledInvoice(
|
||||
@@ -49,7 +55,7 @@ public class SettledInvoiceFixtures {
|
||||
AMOUNT_PAID,
|
||||
MEMO,
|
||||
Optional.of(KEYSEND_MESSAGE),
|
||||
Optional.of(CHANNEL_ID)
|
||||
Optional.of(CHANNEL_ID_2)
|
||||
);
|
||||
|
||||
public static final SettledInvoice SETTLED_INVOICE_2 = new SettledInvoice(
|
||||
@@ -62,4 +68,15 @@ public class SettledInvoiceFixtures {
|
||||
Optional.empty(),
|
||||
Optional.of(CHANNEL_ID)
|
||||
);
|
||||
|
||||
public static final SettledInvoice SETTLED_INVOICE_3 = new SettledInvoice(
|
||||
ADD_INDEX_3,
|
||||
SETTLE_INDEX_3,
|
||||
SETTLE_DATE.plusSeconds(2),
|
||||
HASH_3,
|
||||
AMOUNT_PAID_2,
|
||||
MEMO_2,
|
||||
Optional.empty(),
|
||||
Optional.of(CHANNEL_ID_3)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import de.cotto.lndmanagej.model.PaymentHop;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
@Embeddable
|
||||
public class PaymentHopJpaDto {
|
||||
class PaymentHopJpaDto {
|
||||
private long channelId;
|
||||
private long amount;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "payments")
|
||||
class PaymentJpaDto {
|
||||
public class PaymentJpaDto {
|
||||
@Id
|
||||
private long paymentIndex;
|
||||
|
||||
|
||||
@@ -9,19 +9,21 @@ import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.Table;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "payment_routes")
|
||||
public class PaymentRouteJpaDto {
|
||||
class PaymentRouteJpaDto {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
@SuppressWarnings("unused")
|
||||
private long routeId;
|
||||
|
||||
@Nullable
|
||||
@OrderColumn
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "payment_route_hops")
|
||||
private List<PaymentHopJpaDto> hops;
|
||||
|
||||
@@ -4,18 +4,19 @@ import de.cotto.lndmanagej.model.Coins;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_1;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_4;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PaymentHopJpaDtoTest {
|
||||
@Test
|
||||
void toModel() {
|
||||
assertThat(new PaymentHopJpaDto(CHANNEL_ID.getShortChannelId(), Coins.ofSatoshis(1).milliSatoshis()).toModel())
|
||||
.isEqualTo(PAYMENT_HOP);
|
||||
.isEqualTo(PAYMENT_HOP_CHANNEL_1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createFromModel() {
|
||||
assertThat(PaymentHopJpaDto.createFromModel(PAYMENT_HOP).toModel()).isEqualTo(PAYMENT_HOP);
|
||||
assertThat(PaymentHopJpaDto.createFromModel(PAYMENT_HOP_CHANNEL_4).toModel()).isEqualTo(PAYMENT_HOP_CHANNEL_4);
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_3;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_3;
|
||||
import static de.cotto.lndmanagej.model.PaymentHopFixtures.PAYMENT_HOP_CHANNEL_4;
|
||||
import static de.cotto.lndmanagej.model.PaymentRouteFixtures.PAYMENT_ROUTE_4_TO_2;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PaymentRouteJpaDtoTest {
|
||||
@@ -15,15 +15,15 @@ class PaymentRouteJpaDtoTest {
|
||||
void toModel() {
|
||||
assertThat(new PaymentRouteJpaDto(
|
||||
List.of(
|
||||
PaymentHopJpaDto.createFromModel(PAYMENT_HOP),
|
||||
PaymentHopJpaDto.createFromModel(PAYMENT_HOP_2),
|
||||
PaymentHopJpaDto.createFromModel(PAYMENT_HOP_3)
|
||||
PaymentHopJpaDto.createFromModel(PAYMENT_HOP_CHANNEL_4),
|
||||
PaymentHopJpaDto.createFromModel(PAYMENT_HOP_CHANNEL_3),
|
||||
PaymentHopJpaDto.createFromModel(PAYMENT_HOP_CHANNEL_2)
|
||||
)
|
||||
).toModel()).isEqualTo(PAYMENT_ROUTE);
|
||||
).toModel()).isEqualTo(PAYMENT_ROUTE_4_TO_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createFromModel() {
|
||||
assertThat(PaymentRouteJpaDto.createFromModel(PAYMENT_ROUTE).toModel()).isEqualTo(PAYMENT_ROUTE);
|
||||
assertThat(PaymentRouteJpaDto.createFromModel(PAYMENT_ROUTE_4_TO_2).toModel()).isEqualTo(PAYMENT_ROUTE_4_TO_2);
|
||||
}
|
||||
}
|
||||
12
selfpayments/build.gradle
Normal file
12
selfpayments/build.gradle
Normal file
@@ -0,0 +1,12 @@
|
||||
plugins {
|
||||
id 'lnd-manageJ.java-library-conventions'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation project(':model')
|
||||
implementation project(':invoices')
|
||||
implementation project(':payments')
|
||||
testRuntimeOnly 'com.h2database:h2'
|
||||
testFixturesApi testFixtures(project(':model'))
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.cotto.lndmanagej;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SpringBootConfiguration {
|
||||
public SpringBootConfiguration() {
|
||||
// default constructor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package de.cotto.lndmanagej.selfpayments.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.invoices.persistence.SettledInvoiceJpaDto;
|
||||
import de.cotto.lndmanagej.invoices.persistence.SettledInvoicesRepository;
|
||||
import de.cotto.lndmanagej.payments.persistence.PaymentJpaDto;
|
||||
import de.cotto.lndmanagej.payments.persistence.PaymentsRepository;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT;
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT_2;
|
||||
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.PaymentFixtures.PAYMENT;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_2;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_3;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE_2;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE_3;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DataJpaTest
|
||||
class SelfPaymentsRepositoryIT {
|
||||
@Autowired
|
||||
private SelfPaymentsRepository repository;
|
||||
|
||||
@Autowired
|
||||
private SettledInvoicesRepository invoicesRepository;
|
||||
|
||||
@Autowired
|
||||
private PaymentsRepository paymentsRepository;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
paymentsRepository.save(PaymentJpaDto.createFromModel(PAYMENT));
|
||||
paymentsRepository.save(PaymentJpaDto.createFromModel(PAYMENT_2));
|
||||
paymentsRepository.save(PaymentJpaDto.createFromModel(PAYMENT_3));
|
||||
invoicesRepository.save(SettledInvoiceJpaDto.createFromModel(SETTLED_INVOICE));
|
||||
invoicesRepository.save(SettledInvoiceJpaDto.createFromModel(SETTLED_INVOICE_2));
|
||||
invoicesRepository.save(SettledInvoiceJpaDto.createFromModel(SETTLED_INVOICE_3));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSelfPayments() {
|
||||
assertThat(repository.getAllSelfPayments()).map(SelfPaymentJpaDto::toModel)
|
||||
.containsExactlyInAnyOrder(SELF_PAYMENT, SELF_PAYMENT_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsToChannel() {
|
||||
assertThat(repository.getSelfPaymentsToChannel(CHANNEL_ID_2.getShortChannelId()))
|
||||
.map(SelfPaymentJpaDto::toModel)
|
||||
.containsExactly(SELF_PAYMENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsFromChannel() {
|
||||
assertThat(repository.getSelfPaymentsFromChannel(CHANNEL_ID_3.getShortChannelId()))
|
||||
.map(SelfPaymentJpaDto::toModel)
|
||||
.containsExactly(SELF_PAYMENT_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsFromChannel_two_payments() {
|
||||
assertThat(repository.getSelfPaymentsFromChannel(CHANNEL_ID_4.getShortChannelId()))
|
||||
.map(SelfPaymentJpaDto::toModel)
|
||||
.containsExactly(SELF_PAYMENT, SELF_PAYMENT_2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package de.cotto.lndmanagej.selfpayments;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.model.SelfPayment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SelfPaymentsDao {
|
||||
List<SelfPayment> getAllSelfPayments();
|
||||
|
||||
List<SelfPayment> getSelfPaymentsToChannel(ChannelId channelId);
|
||||
|
||||
List<SelfPayment> getSelfPaymentsFromChannel(ChannelId channelId);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package de.cotto.lndmanagej.selfpayments.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.invoices.persistence.SettledInvoiceJpaDto;
|
||||
import de.cotto.lndmanagej.model.SelfPayment;
|
||||
import de.cotto.lndmanagej.payments.persistence.PaymentJpaDto;
|
||||
|
||||
public record SelfPaymentJpaDto(
|
||||
PaymentJpaDto payment,
|
||||
SettledInvoiceJpaDto settledInvoice
|
||||
) {
|
||||
public SelfPayment toModel() {
|
||||
return new SelfPayment(payment.toModel(), settledInvoice.toModel());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package de.cotto.lndmanagej.selfpayments.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.model.SelfPayment;
|
||||
import de.cotto.lndmanagej.selfpayments.SelfPaymentsDao;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Transactional
|
||||
public class SelfPaymentsDaoImpl implements SelfPaymentsDao {
|
||||
private final SelfPaymentsRepository repository;
|
||||
|
||||
public SelfPaymentsDaoImpl(SelfPaymentsRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SelfPayment> getAllSelfPayments() {
|
||||
return toModel(repository.getAllSelfPayments());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SelfPayment> getSelfPaymentsToChannel(ChannelId channelId) {
|
||||
return toModel(repository.getSelfPaymentsToChannel(channelId.getShortChannelId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SelfPayment> getSelfPaymentsFromChannel(ChannelId channelId) {
|
||||
return toModel(repository.getSelfPaymentsFromChannel(channelId.getShortChannelId()));
|
||||
}
|
||||
|
||||
private List<SelfPayment> toModel(List<SelfPaymentJpaDto> selfPayments) {
|
||||
return selfPayments.stream().map(SelfPaymentJpaDto::toModel).toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package de.cotto.lndmanagej.selfpayments.persistence;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.List;
|
||||
|
||||
public interface SelfPaymentsRepository extends JpaRepository<SelfPaymentsRepository.DummyEntity, Long> {
|
||||
@Query("SELECT NEW de.cotto.lndmanagej.selfpayments.persistence.SelfPaymentJpaDto(p, i) " +
|
||||
"FROM PaymentJpaDto p " +
|
||||
"JOIN SettledInvoiceJpaDto i ON p.hash = i.hash " +
|
||||
"ORDER BY i.settleDate ASC")
|
||||
List<SelfPaymentJpaDto> getAllSelfPayments();
|
||||
|
||||
@Query("SELECT NEW de.cotto.lndmanagej.selfpayments.persistence.SelfPaymentJpaDto(p, i) " +
|
||||
"FROM PaymentJpaDto p " +
|
||||
"JOIN SettledInvoiceJpaDto i ON p.hash = i.hash " +
|
||||
"WHERE i.receivedVia = ?1 " +
|
||||
"ORDER BY i.settleDate ASC")
|
||||
List<SelfPaymentJpaDto> getSelfPaymentsToChannel(long channelId);
|
||||
|
||||
@Query("SELECT NEW de.cotto.lndmanagej.selfpayments.persistence.SelfPaymentJpaDto(p, i) " +
|
||||
"FROM PaymentJpaDto p " +
|
||||
"JOIN SettledInvoiceJpaDto i ON p.hash = i.hash " +
|
||||
"JOIN p.routes route " +
|
||||
"JOIN route.hops hop " +
|
||||
"WHERE hop.channelId = ?1 AND INDEX(hop) = 0 " +
|
||||
"ORDER BY i.settleDate ASC")
|
||||
List<SelfPaymentJpaDto> getSelfPaymentsFromChannel(long channelId);
|
||||
|
||||
@Entity
|
||||
@Table(name = "dummy")
|
||||
class DummyEntity {
|
||||
@Id
|
||||
@SuppressWarnings("unused")
|
||||
private long dummyId;
|
||||
|
||||
public DummyEntity() {
|
||||
// for JPA
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package de.cotto.lndmanagej.selfpayments.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.invoices.persistence.SettledInvoiceJpaDto;
|
||||
import de.cotto.lndmanagej.payments.persistence.PaymentJpaDto;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class SelfPaymentJpaDtoTest {
|
||||
private SelfPaymentJpaDto selfPaymentJpaDto;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
SettledInvoiceJpaDto invoice = SettledInvoiceJpaDto.createFromModel(SETTLED_INVOICE);
|
||||
PaymentJpaDto payment = PaymentJpaDto.createFromModel(PAYMENT);
|
||||
selfPaymentJpaDto = new SelfPaymentJpaDto(payment, invoice);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toModel() {
|
||||
assertThat(selfPaymentJpaDto.toModel()).isEqualTo(SELF_PAYMENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void payment() {
|
||||
assertThat(selfPaymentJpaDto.payment().toModel()).isEqualTo(PAYMENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void settledInvoice() {
|
||||
assertThat(selfPaymentJpaDto.settledInvoice().toModel()).isEqualTo(SETTLED_INVOICE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package de.cotto.lndmanagej.selfpayments.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.invoices.persistence.SettledInvoiceJpaDto;
|
||||
import de.cotto.lndmanagej.model.Payment;
|
||||
import de.cotto.lndmanagej.model.SettledInvoice;
|
||||
import de.cotto.lndmanagej.payments.persistence.PaymentJpaDto;
|
||||
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.List;
|
||||
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT;
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT_2;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT;
|
||||
import static de.cotto.lndmanagej.model.PaymentFixtures.PAYMENT_2;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE;
|
||||
import static de.cotto.lndmanagej.model.SettledInvoiceFixtures.SETTLED_INVOICE_2;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class SelfPaymentsDaoImplTest {
|
||||
@InjectMocks
|
||||
private SelfPaymentsDaoImpl selfPaymentsDaoImpl;
|
||||
|
||||
@Mock
|
||||
private SelfPaymentsRepository repository;
|
||||
|
||||
@Test
|
||||
void getAllSelfPayments_empty() {
|
||||
assertThat(selfPaymentsDaoImpl.getAllSelfPayments()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAllSelfPayments() {
|
||||
when(repository.getAllSelfPayments())
|
||||
.thenReturn(List.of(getDto(PAYMENT, SETTLED_INVOICE), getDto(PAYMENT_2, SETTLED_INVOICE_2)));
|
||||
assertThat(selfPaymentsDaoImpl.getAllSelfPayments()).containsExactlyInAnyOrder(SELF_PAYMENT, SELF_PAYMENT_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsToChannel() {
|
||||
when(repository.getSelfPaymentsToChannel(CHANNEL_ID.getShortChannelId()))
|
||||
.thenReturn(List.of(getDto(PAYMENT, SETTLED_INVOICE)));
|
||||
assertThat(selfPaymentsDaoImpl.getSelfPaymentsToChannel(CHANNEL_ID)).containsExactlyInAnyOrder(SELF_PAYMENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsFromChannel() {
|
||||
when(repository.getSelfPaymentsFromChannel(CHANNEL_ID.getShortChannelId()))
|
||||
.thenReturn(List.of(getDto(PAYMENT, SETTLED_INVOICE)));
|
||||
assertThat(selfPaymentsDaoImpl.getSelfPaymentsFromChannel(CHANNEL_ID)).containsExactlyInAnyOrder(SELF_PAYMENT);
|
||||
}
|
||||
|
||||
private SelfPaymentJpaDto getDto(Payment payment, SettledInvoice settledInvoice) {
|
||||
return new SelfPaymentJpaDto(
|
||||
PaymentJpaDto.createFromModel(payment),
|
||||
SettledInvoiceJpaDto.createFromModel(settledInvoice)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.cotto.lndmanagej.selfpayments.persistence;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class SelfPaymentsRepositoryTest {
|
||||
@Test
|
||||
void dummyEntity() {
|
||||
// the class is required to define a repository
|
||||
assertThat(new SelfPaymentsRepository.DummyEntity()).isNotNull();
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ include 'grpc-client'
|
||||
include 'invoices'
|
||||
include 'model'
|
||||
include 'payments'
|
||||
include 'selfpayments'
|
||||
include 'statistics'
|
||||
include 'transactions'
|
||||
include 'web'
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package de.cotto.lndmanagej.controller;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelIdResolver;
|
||||
import de.cotto.lndmanagej.service.SelfPaymentsService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT;
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT_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_4;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
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.jsonPath;
|
||||
|
||||
@WebMvcTest(controllers = SelfPaymentsController.class)
|
||||
class SelfPaymentsControllerIT {
|
||||
private static final String CHANNEL_PREFIX = "/api/channel/" + CHANNEL_ID.getShortChannelId() + "/";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockBean
|
||||
@SuppressWarnings("unused")
|
||||
private ChannelIdResolver channelIdResolver;
|
||||
|
||||
@MockBean
|
||||
private SelfPaymentsService selfPaymentsService;
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsFromChannel() throws Exception {
|
||||
when(selfPaymentsService.getSelfPaymentsFromChannel(CHANNEL_ID))
|
||||
.thenReturn(List.of(SELF_PAYMENT_2, SELF_PAYMENT));
|
||||
mockMvc.perform(get(CHANNEL_PREFIX + "/self-payments-from-channel/"))
|
||||
.andExpect(jsonPath("$[0].memo", is(SELF_PAYMENT_2.memo())))
|
||||
.andExpect(jsonPath("$[1].memo", is(SELF_PAYMENT.memo())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsToChannel() throws Exception {
|
||||
when(selfPaymentsService.getSelfPaymentsToChannel(CHANNEL_ID))
|
||||
.thenReturn(List.of(SELF_PAYMENT, SELF_PAYMENT_2));
|
||||
mockMvc.perform(get(CHANNEL_PREFIX + "/self-payments-to-channel/"))
|
||||
.andExpect(jsonPath("$[0].memo", is(SELF_PAYMENT.memo())))
|
||||
.andExpect(jsonPath("$[0].settleDate", is(SELF_PAYMENT.settleDate().toString())))
|
||||
.andExpect(jsonPath("$[0].value", is(String.valueOf(SELF_PAYMENT.value().milliSatoshis()))))
|
||||
.andExpect(jsonPath("$[0].fees", is(String.valueOf(SELF_PAYMENT.fees().milliSatoshis()))))
|
||||
.andExpect(jsonPath("$[0].firstChannel", is(CHANNEL_ID_4.toString())))
|
||||
.andExpect(jsonPath("$[0].lastChannel", is(CHANNEL_ID_2.toString())))
|
||||
.andExpect(jsonPath("$[1].memo", is(SELF_PAYMENT_2.memo())))
|
||||
.andExpect(jsonPath("$[1].settleDate", is(SELF_PAYMENT_2.settleDate().toString())))
|
||||
.andExpect(jsonPath("$[1].value", is(String.valueOf(SELF_PAYMENT_2.value().milliSatoshis()))))
|
||||
.andExpect(jsonPath("$[1].fees", is(String.valueOf(SELF_PAYMENT_2.fees().milliSatoshis()))))
|
||||
.andExpect(jsonPath("$[1].firstChannel", is(not(empty()))))
|
||||
.andExpect(jsonPath("$[1].lastChannel", is(CHANNEL_ID.toString())));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package de.cotto.lndmanagej.controller;
|
||||
|
||||
import com.codahale.metrics.annotation.Timed;
|
||||
import de.cotto.lndmanagej.controller.dto.ObjectMapperConfiguration;
|
||||
import de.cotto.lndmanagej.controller.dto.SelfPaymentDto;
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.service.SelfPaymentsService;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/")
|
||||
@Import(ObjectMapperConfiguration.class)
|
||||
public class SelfPaymentsController {
|
||||
private final SelfPaymentsService selfPaymentsService;
|
||||
|
||||
public SelfPaymentsController(SelfPaymentsService selfPaymentsService) {
|
||||
this.selfPaymentsService = selfPaymentsService;
|
||||
}
|
||||
|
||||
@Timed
|
||||
@GetMapping("/channel/{channelId}/self-payments-to-channel")
|
||||
public List<SelfPaymentDto> getSelfPaymentsToChannel(@PathVariable ChannelId channelId) {
|
||||
return selfPaymentsService.getSelfPaymentsToChannel(channelId).stream()
|
||||
.map(SelfPaymentDto::createFromModel)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Timed
|
||||
@GetMapping("/channel/{channelId}/self-payments-from-channel")
|
||||
public List<SelfPaymentDto> getSelfPaymentsFromChannel(@PathVariable ChannelId channelId) {
|
||||
return selfPaymentsService.getSelfPaymentsFromChannel(channelId).stream()
|
||||
.map(SelfPaymentDto::createFromModel)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Configuration
|
||||
public class ObjectMapperConfiguration {
|
||||
public ObjectMapperConfiguration() {
|
||||
@@ -23,6 +25,7 @@ public class ObjectMapperConfiguration {
|
||||
module.addSerializer(Pubkey.class, new ToStringSerializer());
|
||||
module.addSerializer(ChannelId.class, new ToStringSerializer());
|
||||
module.addSerializer(ChannelPoint.class, new ToStringSerializer());
|
||||
module.addSerializer(ZonedDateTime.class, new ToStringSerializer());
|
||||
return new ObjectMapper().registerModule(module);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package de.cotto.lndmanagej.controller.dto;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.model.SelfPayment;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
public record SelfPaymentDto(
|
||||
ZonedDateTime settleDate,
|
||||
String memo,
|
||||
String value,
|
||||
String fees,
|
||||
ChannelId firstChannel,
|
||||
ChannelId lastChannel
|
||||
) {
|
||||
public static SelfPaymentDto createFromModel(SelfPayment selfPayment) {
|
||||
return new SelfPaymentDto(
|
||||
selfPayment.settleDate(),
|
||||
selfPayment.memo(),
|
||||
String.valueOf(selfPayment.value().milliSatoshis()),
|
||||
String.valueOf(selfPayment.fees().milliSatoshis()),
|
||||
selfPayment.firstChannel().orElseThrow(),
|
||||
selfPayment.lastChannel().orElseThrow()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package de.cotto.lndmanagej.controller;
|
||||
|
||||
import de.cotto.lndmanagej.controller.dto.SelfPaymentDto;
|
||||
import de.cotto.lndmanagej.service.SelfPaymentsService;
|
||||
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.List;
|
||||
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT;
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT_2;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class SelfPaymentsControllerTest {
|
||||
@InjectMocks
|
||||
private SelfPaymentsController selfPaymentsController;
|
||||
|
||||
@Mock
|
||||
private SelfPaymentsService service;
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsToChannel() {
|
||||
when(service.getSelfPaymentsToChannel(CHANNEL_ID)).thenReturn(List.of(SELF_PAYMENT, SELF_PAYMENT_2));
|
||||
assertThat(selfPaymentsController.getSelfPaymentsToChannel(CHANNEL_ID)).containsExactly(
|
||||
SelfPaymentDto.createFromModel(SELF_PAYMENT),
|
||||
SelfPaymentDto.createFromModel(SELF_PAYMENT_2)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSelfPaymentsFromChannel() {
|
||||
when(service.getSelfPaymentsFromChannel(CHANNEL_ID)).thenReturn(List.of(SELF_PAYMENT, SELF_PAYMENT_2));
|
||||
assertThat(selfPaymentsController.getSelfPaymentsFromChannel(CHANNEL_ID)).containsExactly(
|
||||
SelfPaymentDto.createFromModel(SELF_PAYMENT),
|
||||
SelfPaymentDto.createFromModel(SELF_PAYMENT_2)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package de.cotto.lndmanagej.controller.dto;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static de.cotto.lndmanagej.SelfPaymentFixtures.SELF_PAYMENT;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class SelfPaymentDtoTest {
|
||||
|
||||
private final SelfPaymentDto dto = SelfPaymentDto.createFromModel(SELF_PAYMENT);
|
||||
|
||||
@Test
|
||||
void settleDate() {
|
||||
assertThat(dto.settleDate()).isEqualTo(SELF_PAYMENT.settleDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
void memo() {
|
||||
assertThat(dto.memo()).isEqualTo(SELF_PAYMENT.memo());
|
||||
}
|
||||
|
||||
@Test
|
||||
void value() {
|
||||
assertThat(dto.value()).isEqualTo(String.valueOf(SELF_PAYMENT.value().milliSatoshis()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void fees() {
|
||||
assertThat(dto.fees()).isEqualTo(String.valueOf(SELF_PAYMENT.fees().milliSatoshis()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void firstChannel() {
|
||||
assertThat(dto.firstChannel()).isEqualTo(SELF_PAYMENT.firstChannel().orElseThrow());
|
||||
}
|
||||
|
||||
@Test
|
||||
void lastChannel() {
|
||||
assertThat(dto.lastChannel()).isEqualTo(SELF_PAYMENT.lastChannel().orElseThrow());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user