mirror of
https://github.com/aljazceru/lnd-manageJ.git
synced 2026-01-24 00:14:25 +01:00
provide better failure reporting
This commit is contained in:
@@ -69,16 +69,16 @@ public class MultiPathPaymentSplitter {
|
||||
List<BasicRoute> basicRoutes = BasicRoutes.fromFlows(source, intermediateTarget, flows);
|
||||
List<BasicRoute> extendedBasicRoutes = extendBasicRoutes(basicRoutes, paymentOptions, target);
|
||||
if (extendedBasicRoutes.isEmpty()) {
|
||||
return MultiPathPayment.FAILURE;
|
||||
return MultiPathPayment.failure("Unable to extend channel back to own node");
|
||||
}
|
||||
List<Route> routes = getWithLiquidityInformation(extendedBasicRoutes);
|
||||
List<Route> fixedRoutes = Routes.getFixedWithTotalAmount(routes, amount);
|
||||
if (fixedRoutes.isEmpty()) {
|
||||
return MultiPathPayment.FAILURE;
|
||||
return MultiPathPayment.failure("Not enough liquidity for first hop (due to fees?)");
|
||||
}
|
||||
|
||||
if (isTooExpensive(paymentOptions, fixedRoutes)) {
|
||||
return MultiPathPayment.FAILURE;
|
||||
return MultiPathPayment.failure("At least one route is too expensive (fee rate limit)");
|
||||
}
|
||||
return new MultiPathPayment(fixedRoutes);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import de.cotto.lndmanagej.model.Route;
|
||||
import de.cotto.lndmanagej.pickhardtpayments.model.MultiPathPayment;
|
||||
import de.cotto.lndmanagej.pickhardtpayments.model.PaymentOptions;
|
||||
import de.cotto.lndmanagej.pickhardtpayments.model.PaymentStatus;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -81,9 +82,18 @@ public class PaymentLoop {
|
||||
MultiPathPayment multiPathPayment =
|
||||
multiPathPaymentSplitter.getMultiPathPaymentTo(destination, residualAmount, paymentOptions);
|
||||
if (multiPathPayment.isFailure()) {
|
||||
paymentStatus.failed(
|
||||
"Unable to find route (trying to send %s)".formatted(residualAmount.toStringSat())
|
||||
);
|
||||
String information = multiPathPayment.getInformation();
|
||||
if (Strings.isNotEmpty(information)) {
|
||||
paymentStatus.failed(
|
||||
"Unable to find route (trying to send %s): %s"
|
||||
.formatted(residualAmount.toStringSat(), information)
|
||||
);
|
||||
} else {
|
||||
paymentStatus.failed(
|
||||
"Unable to find route (trying to send %s)"
|
||||
.formatted(residualAmount.toStringSat())
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
List<Route> routes = multiPathPayment.routes();
|
||||
|
||||
@@ -10,10 +10,11 @@ public record MultiPathPayment(
|
||||
Coins fees,
|
||||
Coins feesWithFirstHop,
|
||||
double probability,
|
||||
List<Route> routes
|
||||
List<Route> routes,
|
||||
String information
|
||||
) {
|
||||
public static final MultiPathPayment FAILURE =
|
||||
new MultiPathPayment(Coins.NONE, Coins.NONE, Coins.NONE, 0.0, List.of());
|
||||
new MultiPathPayment(Coins.NONE, Coins.NONE, Coins.NONE, 0.0, List.of(), "");
|
||||
|
||||
public MultiPathPayment(List<Route> routes) {
|
||||
this(
|
||||
@@ -21,12 +22,17 @@ public record MultiPathPayment(
|
||||
routes.stream().map(Route::getFees).reduce(Coins.NONE, Coins::add),
|
||||
routes.stream().map(Route::getFeesWithFirstHop).reduce(Coins.NONE, Coins::add),
|
||||
routes.stream().mapToDouble(Route::getProbability).reduce(1.0, (a, b) -> a * b),
|
||||
routes
|
||||
routes,
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
public static MultiPathPayment failure(String information) {
|
||||
return new MultiPathPayment(Coins.NONE, Coins.NONE, Coins.NONE, 0.0, List.of(), information);
|
||||
}
|
||||
|
||||
public boolean isFailure() {
|
||||
return equals(FAILURE);
|
||||
return routes.isEmpty() && amount.equals(Coins.NONE);
|
||||
}
|
||||
|
||||
public long getFeeRate() {
|
||||
@@ -37,6 +43,10 @@ public record MultiPathPayment(
|
||||
return getFeeRateForFees(feesWithFirstHop);
|
||||
}
|
||||
|
||||
public String getInformation() {
|
||||
return information;
|
||||
}
|
||||
|
||||
private long getFeeRateForFees(Coins feesToConsider) {
|
||||
if (amount.isPositive()) {
|
||||
return feesToConsider.milliSatoshis() * 1_000_000 / amount.milliSatoshis();
|
||||
|
||||
@@ -82,6 +82,18 @@ class PaymentLoopTest {
|
||||
verifyNoInteractions(grpcSendToRoute);
|
||||
}
|
||||
|
||||
@Test
|
||||
void failure_with_information() {
|
||||
when(multiPathPaymentSplitter.getMultiPathPaymentTo(any(), any(), any()))
|
||||
.thenReturn(MultiPathPayment.failure("something"));
|
||||
paymentLoop.start(DECODED_PAYMENT_REQUEST, PAYMENT_OPTIONS, paymentStatus);
|
||||
|
||||
assertThat(paymentStatus.isFailure()).isTrue();
|
||||
assertThat(paymentStatus.getMessages().stream().map(InstantWithString::string))
|
||||
.contains("Unable to find route (trying to send 123): something");
|
||||
verifyNoInteractions(grpcSendToRoute);
|
||||
}
|
||||
|
||||
@Test
|
||||
void requests_route_with_expected_parameters() {
|
||||
mockSuccessOnFirstAttempt();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.cotto.lndmanagej.pickhardtpayments.model;
|
||||
|
||||
import de.cotto.lndmanagej.model.Coins;
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static de.cotto.lndmanagej.model.RouteFixtures.ROUTE;
|
||||
@@ -74,4 +75,18 @@ class MultiPathPaymentTest {
|
||||
void feeRateWithFirstHop() {
|
||||
assertThat(MULTI_PATH_PAYMENT.getFeeRateWithFirstHop()).isEqualTo(466);
|
||||
}
|
||||
|
||||
@Test
|
||||
void failure_with_information() {
|
||||
assertThat(MultiPathPayment.failure("something").isFailure()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInformation() {
|
||||
SoftAssertions softly = new SoftAssertions();
|
||||
softly.assertThat(MultiPathPayment.FAILURE.getInformation()).isEqualTo("");
|
||||
softly.assertThat(MultiPathPayment.failure("hello").getInformation()).isEqualTo("hello");
|
||||
softly.assertThat(MULTI_PATH_PAYMENT.getInformation()).isEqualTo("");
|
||||
softly.assertAll();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user