From 0bd725e70f2273e637bc169703f790e1f56afd37 Mon Sep 17 00:00:00 2001 From: "chris.orogvany" Date: Sun, 28 Jan 2018 20:56:50 -0800 Subject: [PATCH] Add payout at given time Allow folks to set a time of day for payments --- src/main/java/com/semuxpool/pool/Pool.java | 53 +++++++++++++++++-- .../java/com/semuxpool/pool/PoolRunner.java | 26 +++++++-- .../semuxpool/pool/block/PayoutFactory.java | 2 + .../pool/persistence/JsonPersistence.java | 10 ++-- .../com/semuxpool/pool/state/PoolState.java | 12 +++++ 5 files changed, 90 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/semuxpool/pool/Pool.java b/src/main/java/com/semuxpool/pool/Pool.java index 2db0c81..e8a6c90 100644 --- a/src/main/java/com/semuxpool/pool/Pool.java +++ b/src/main/java/com/semuxpool/pool/Pool.java @@ -16,7 +16,12 @@ import org.slf4j.LoggerFactory; import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,17 +38,18 @@ public class Pool implements Runnable private final Persistence persistence; private final Set delegates; private final StatusLogger statusLogger = new StatusLogger(); - private final int payOutNBlocks; + private final Integer payOutNBlocks; private final BlockResultFactory blockResultFactory; private final long fee; private final PoolPayer payer; private final String payoutAddress; private final Long startBlock; + private final LocalTime payoutTime; private PoolState poolState; private PayoutFactory payoutFactory; - public Pool(SemuxClient client, Persistence persistence, Set delegates, int payOutNBlocks, BlockResultFactory blockResultFactory, long fee, PoolPayer payer, String payoutAddress, Long startBlock) + public Pool(SemuxClient client, Persistence persistence, Set delegates, Integer payOutNBlocks, BlockResultFactory blockResultFactory, long fee, PoolPayer payer, String payoutAddress, Long startBlock, LocalTime payoutTime) { this.client = client; this.persistence = persistence; @@ -54,6 +60,7 @@ public Pool(SemuxClient client, Persistence persistence, Set delegates, this.payer = payer; this.payoutAddress = payoutAddress; this.startBlock = startBlock; + this.payoutTime = payoutTime; } @Override @@ -102,8 +109,13 @@ public void run() //clear existing block results so we don't pay again. blockResults.clear(); //set the current paid up to block - poolState.setCurrentBlock(currentBlock + 1); + poolState.setLastPayoutDate(payout.getDate()); } + else + { + poolState.setLastPayoutDate(new Date()); + } + poolState.setCurrentBlock(currentBlock + 1); } //next loop will add new block @@ -161,7 +173,38 @@ private Block getBlock(long currentBlock) */ private boolean shouldPay(long currentBlock, boolean isSynced) { - return (currentBlock > (poolState.getCurrentBlock() + payOutNBlocks)) && isSynced; + if (payoutTime != null) + { + LocalDateTime currentTime = LocalDateTime.now(); + + Date lastPayout = poolState.getLastPayoutDate(); + if (lastPayout != null) + { + LocalDateTime lastPaymentDate = LocalDateTime.ofInstant(lastPayout.toInstant(), ZoneId.systemDefault()); + + LocalDate dateOfPayment = lastPaymentDate.toLocalDate(); + dateOfPayment = dateOfPayment.plusDays(1); + + LocalDateTime targetDate = LocalDateTime.of(dateOfPayment, payoutTime); + if (currentTime.compareTo(targetDate) > 0) + { + return isSynced; + } + } + else + { + //is it past that hour today + if (currentTime.toLocalTime().compareTo(payoutTime) > 0) + { + return isSynced; + } + } + return false; + } + else + { + return (currentBlock > (poolState.getCurrentBlock() + payOutNBlocks)) && isSynced; + } } /** @@ -190,7 +233,7 @@ private void initializePoolState() //create the PayoutFactory payoutFactory = new PayoutFactory(delegateNameMap, payoutAddress, fee); - if(startBlock > poolState.getCurrentBlock()) + if (startBlock > poolState.getCurrentBlock()) { poolState.setCurrentBlock(startBlock); } diff --git a/src/main/java/com/semuxpool/pool/PoolRunner.java b/src/main/java/com/semuxpool/pool/PoolRunner.java index 913d62a..738463e 100644 --- a/src/main/java/com/semuxpool/pool/PoolRunner.java +++ b/src/main/java/com/semuxpool/pool/PoolRunner.java @@ -11,6 +11,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.time.LocalTime; import java.util.Collections; import java.util.HashSet; import java.util.Properties; @@ -24,7 +25,14 @@ public class PoolRunner public static void main(String[] args) throws IOException, SemuxException { Properties properties = new Properties(); - properties.load(new FileInputStream(new File("./config/semuxpool.properties"))); + if (args.length > 0) + { + properties.load(new FileInputStream(new File("./config/" + args[0]))); + } + else + { + properties.load(new FileInputStream(new File("./config/semuxpool.properties"))); + } Set delegates = new HashSet<>(); @@ -33,13 +41,21 @@ public static void main(String[] args) throws IOException, SemuxException Collections.addAll(delegates, delegatesAr); String host = properties.getProperty("apiHost"); + String payoutsDirectory = properties.getProperty("dataDirectory"); String user = properties.getProperty("apiUser"); String password = properties.getProperty("apiPass"); int port = Integer.valueOf(properties.getProperty("apiPort")); float poolPayoutPercent = Math.max(0, Float.valueOf(properties.getProperty("poolFeePercent"))); String note = properties.getProperty("paymentNote"); float donationPercent = Math.max(0, Float.valueOf(properties.getProperty("developerDonationPercent"))); - int payoutEveryBlock = Integer.valueOf(properties.getProperty("payoutEveryNBlocks")); + Integer payoutEveryBlock = Integer.valueOf(properties.getProperty("payoutEveryNBlocks")); + String payoutTimeString = properties.getProperty("payoutTime"); + LocalTime payoutTime = null; + if (payoutTimeString != null) + { + payoutEveryBlock = null; + payoutTime = LocalTime.parse(payoutTimeString); + } boolean debugMode = Boolean.valueOf(properties.getProperty("debugMode")); String poolProfitsAddress = properties.getProperty("poolProfitsAddress"); @@ -66,13 +82,15 @@ public static void main(String[] args) throws IOException, SemuxException long minPayout = fee * minPayoutMultiplier; //persistence - Persistence persistence = new JsonPersistence(); + Persistence persistence = new JsonPersistence(payoutsDirectory); BlockResultFactory blockResultFactory = new BlockResultFactory(client, poolPayoutPercent, donationPercent, blockReward, poolProfitsAddress); //payer PoolPayer payer = new PoolPayer(client, delegates, delegates.iterator().next(), persistence, fee, minPayout, note); - Pool pool = new Pool(client, persistence, delegates, payoutEveryBlock, blockResultFactory, fee, payer, poolProfitsAddress, startBlock); + Pool pool = new Pool( + client, persistence, delegates, payoutEveryBlock, blockResultFactory, + fee, payer, poolProfitsAddress, startBlock, payoutTime); pool.run(); } } diff --git a/src/main/java/com/semuxpool/pool/block/PayoutFactory.java b/src/main/java/com/semuxpool/pool/block/PayoutFactory.java index 7e50f8a..1358e00 100644 --- a/src/main/java/com/semuxpool/pool/block/PayoutFactory.java +++ b/src/main/java/com/semuxpool/pool/block/PayoutFactory.java @@ -3,6 +3,7 @@ import com.semuxpool.pool.api.BlockResult; import com.semuxpool.pool.api.Payout; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -63,6 +64,7 @@ public synchronized Payout getPayoutForBlockResults(List blocks, Lo payout.setPayouts(getPayouts(blocks)); payout.setPoolProfits(totalPoolFees); payout.setFee(fee); + payout.setDate(new Date()); return payout; } diff --git a/src/main/java/com/semuxpool/pool/persistence/JsonPersistence.java b/src/main/java/com/semuxpool/pool/persistence/JsonPersistence.java index 1700eb1..21e5145 100644 --- a/src/main/java/com/semuxpool/pool/persistence/JsonPersistence.java +++ b/src/main/java/com/semuxpool/pool/persistence/JsonPersistence.java @@ -21,10 +21,11 @@ public class JsonPersistence implements Persistence { private static final Logger logger = LoggerFactory.getLogger(JsonPersistence.class); private static final ObjectMapper MAPPER = new ObjectMapper(); - private static final String PAYOUT_DIRECTORY = "payouts"; + private static String payoutsDirectory = "payouts"; - public JsonPersistence() + public JsonPersistence(String payoutsDirectory) { + this.payoutsDirectory = payoutsDirectory; MAPPER.enable(SerializationFeature.INDENT_OUTPUT); } @@ -34,7 +35,7 @@ public String persistPayout(Payout payout) { return null; } - String fileName = PAYOUT_DIRECTORY + File.separator + "Payout-" + System.currentTimeMillis() + "-" + payout.getStartBlock() + "-" + payout.getEndBlock() + ".json"; + String fileName = payoutsDirectory + File.separator + "Payout-" + System.currentTimeMillis() + "-" + payout.getStartBlock() + "-" + payout.getEndBlock() + ".json"; //persist the block try { @@ -70,6 +71,7 @@ public PoolState loadPoolState() throws IOException { poolState.addPayout(payout); block = payout.getEndBlock(); + poolState.setLastPayoutDate(payout.getDate()); } //start with block after last tallied. @@ -101,7 +103,7 @@ public List getAllPayouts() throws IOException //load all the payouts ObjectMapper mapper = new ObjectMapper(); - File directory = new File(PAYOUT_DIRECTORY); + File directory = new File(payoutsDirectory); if (!directory.isDirectory()) { boolean success = directory.mkdir(); diff --git a/src/main/java/com/semuxpool/pool/state/PoolState.java b/src/main/java/com/semuxpool/pool/state/PoolState.java index 8e137d6..9ad6da5 100644 --- a/src/main/java/com/semuxpool/pool/state/PoolState.java +++ b/src/main/java/com/semuxpool/pool/state/PoolState.java @@ -6,6 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -27,6 +28,7 @@ public class PoolState private Set delegates; private long currentBlock; + private Date lastPayoutDate; public long getTotalPoolProfits() @@ -170,4 +172,14 @@ private Long add(Long a, Long b) } return a + b; } + + public Date getLastPayoutDate() + { + return lastPayoutDate; + } + + public void setLastPayoutDate(Date lastPayoutDate) + { + this.lastPayoutDate = lastPayoutDate; + } }