mirror of
https://github.com/aljazceru/lnd-manageJ.git
synced 2026-01-24 08:24:20 +01:00
add OnChainCostService
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package de.cotto.lndmanagej.controller;
|
||||
|
||||
public class CostException extends Exception {
|
||||
public CostException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.cotto.lndmanagej.controller;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
|
||||
@ControllerAdvice
|
||||
public class CostExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
public CostExceptionHandler() {
|
||||
super();
|
||||
}
|
||||
|
||||
@ExceptionHandler(CostException.class)
|
||||
public ResponseEntity<String> handleException(CostException exception) {
|
||||
return ResponseEntity
|
||||
.badRequest()
|
||||
.body(exception.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package de.cotto.lndmanagej.controller;
|
||||
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import de.cotto.lndmanagej.metrics.Metrics;
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.model.Coins;
|
||||
import de.cotto.lndmanagej.service.OnChainCostService;
|
||||
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;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/")
|
||||
public class OnChainCostsController {
|
||||
private final OnChainCostService onChainCostService;
|
||||
private final Metrics metrics;
|
||||
|
||||
public OnChainCostsController(OnChainCostService onChainCostService, Metrics metrics) {
|
||||
this.onChainCostService = onChainCostService;
|
||||
this.metrics = metrics;
|
||||
}
|
||||
|
||||
@GetMapping("/channel/{channelId}/open-costs")
|
||||
public long getOpenCostsForChannel(@PathVariable ChannelId channelId) throws CostException {
|
||||
metrics.mark(MetricRegistry.name(getClass(), "getOpenCostsForChannel"));
|
||||
return onChainCostService.getOpenCosts(channelId).map(Coins::satoshis)
|
||||
.orElseThrow(() -> new CostException("Unable to get open costs for channel with ID " + channelId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.google.common.cache.LoadingCache;
|
||||
import de.cotto.lndmanagej.caching.CacheBuilder;
|
||||
import de.cotto.lndmanagej.grpc.GrpcChannels;
|
||||
import de.cotto.lndmanagej.grpc.GrpcClosedChannels;
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.model.ClosedChannel;
|
||||
import de.cotto.lndmanagej.model.ForceClosingChannel;
|
||||
import de.cotto.lndmanagej.model.LocalChannel;
|
||||
@@ -13,6 +14,7 @@ import de.cotto.lndmanagej.model.WaitingCloseChannel;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -64,13 +66,27 @@ public class ChannelService {
|
||||
}
|
||||
|
||||
public Set<LocalChannel> getAllChannelsWith(Pubkey pubkey) {
|
||||
Set<LocalOpenChannel> openChannels = getOpenChannelsWith(pubkey);
|
||||
Set<WaitingCloseChannel> waitingCloseChannels = getWaitingCloseChannels();
|
||||
Set<ForceClosingChannel> forceClosingChannels = getForceClosingChannels();
|
||||
Set<ClosedChannel> closedChannels = getClosedChannels();
|
||||
return Stream.of(openChannels, closedChannels, waitingCloseChannels, forceClosingChannels)
|
||||
.flatMap(Collection::stream)
|
||||
return getAllLocalChannels()
|
||||
.filter(c -> c.getRemotePubkey().equals(pubkey))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public Optional<LocalChannel> getLocalChannel(ChannelId channelId) {
|
||||
return getAllLocalChannels()
|
||||
.filter(c -> c.getId().equals(channelId))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
public Stream<LocalChannel> getAllLocalChannels() {
|
||||
Set<LocalOpenChannel> openChannels = getOpenChannels();
|
||||
Set<WaitingCloseChannel> waitingCloseChannels = getWaitingCloseChannels();
|
||||
Set<ForceClosingChannel> forceClosingChannels = getForceClosingChannels();
|
||||
Set<ClosedChannel> closedChannels = getClosedChannels();
|
||||
return Stream.of(
|
||||
openChannels,
|
||||
closedChannels,
|
||||
waitingCloseChannels,
|
||||
forceClosingChannels
|
||||
).flatMap(Collection::stream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package de.cotto.lndmanagej.service;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.model.ChannelPoint;
|
||||
import de.cotto.lndmanagej.model.ClosedChannel;
|
||||
import de.cotto.lndmanagej.model.Coins;
|
||||
import de.cotto.lndmanagej.model.LocalChannel;
|
||||
import de.cotto.lndmanagej.model.OpenInitiator;
|
||||
import de.cotto.lndmanagej.transactions.model.Transaction;
|
||||
import de.cotto.lndmanagej.transactions.service.TransactionService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class OnChainCostService {
|
||||
private final TransactionService transactionService;
|
||||
private final ChannelService channelService;
|
||||
|
||||
public OnChainCostService(TransactionService transactionService, ChannelService channelService) {
|
||||
this.transactionService = transactionService;
|
||||
this.channelService = channelService;
|
||||
}
|
||||
|
||||
public Optional<Coins> getOpenCosts(ChannelId channelId) {
|
||||
return channelService.getLocalChannel(channelId).flatMap(this::getOpenCosts);
|
||||
}
|
||||
|
||||
public Optional<Coins> getOpenCosts(LocalChannel localChannel) {
|
||||
if (localChannel.getOpenInitiator().equals(OpenInitiator.LOCAL)) {
|
||||
String openTransactionHash = localChannel.getChannelPoint().getTransactionHash();
|
||||
return transactionService.getTransaction(openTransactionHash)
|
||||
.map(Transaction::fees)
|
||||
.map(Coins::satoshis)
|
||||
.map(sat -> {
|
||||
long channels = getNumberOfChannelsWithOpenTransactionHash(openTransactionHash);
|
||||
return Coins.ofSatoshis(sat / channels);
|
||||
});
|
||||
}
|
||||
if (localChannel.getOpenInitiator().equals(OpenInitiator.REMOTE)) {
|
||||
return Optional.of(Coins.NONE);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public Optional<Coins> getCloseCosts(ClosedChannel closedChannel) {
|
||||
if (closedChannel.getOpenInitiator().equals(OpenInitiator.LOCAL)) {
|
||||
return transactionService.getTransaction(closedChannel.getCloseTransactionHash())
|
||||
.map(Transaction::fees);
|
||||
}
|
||||
if (closedChannel.getOpenInitiator().equals(OpenInitiator.REMOTE)) {
|
||||
return Optional.of(Coins.NONE);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private long getNumberOfChannelsWithOpenTransactionHash(String openTransactionHash) {
|
||||
return channelService.getAllLocalChannels()
|
||||
.map(LocalChannel::getChannelPoint)
|
||||
.map(ChannelPoint::getTransactionHash)
|
||||
.filter(x -> x.equals(openTransactionHash))
|
||||
.count();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user