From 03102125b53ccc5eb093b91183b75b7e419083e7 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sun, 26 Jun 2022 11:52:46 -0300 Subject: [PATCH 1/2] Read wallet password in bot instance, not main() - Remove some duplicated code in the bots' main() methods. - Validate wallet password first. - Fix a bot config text alignment problem. --- .../src/main/java/bisq/bots/AbstractBot.java | 4 ++-- .../src/main/java/bisq/bots/BotUtils.java | 15 ++++++++++++++- .../bisq/bots/TakeBestPricedOfferToBuyBsq.java | 13 +++++-------- .../bisq/bots/TakeBestPricedOfferToBuyBtc.java | 14 +++++--------- .../bisq/bots/TakeBestPricedOfferToSellBsq.java | 13 +++++-------- .../bisq/bots/TakeBestPricedOfferToSellBtc.java | 13 +++++-------- .../TakeBestPricedOfferToBuyBtc.properties | 2 +- .../TakeBestPricedOfferToSellBsq.properties | 6 +++--- .../TakeBestPricedOfferToSellBtc.properties | 2 +- 9 files changed, 41 insertions(+), 41 deletions(-) diff --git a/java-examples/src/main/java/bisq/bots/AbstractBot.java b/java-examples/src/main/java/bisq/bots/AbstractBot.java index 4d27082..f6ba7c9 100644 --- a/java-examples/src/main/java/bisq/bots/AbstractBot.java +++ b/java-examples/src/main/java/bisq/bots/AbstractBot.java @@ -84,8 +84,8 @@ public abstract class AbstractBot { // Constructor public AbstractBot(String[] args) { - this.args = args; - Config bisqClientOpts = new Config(args, defaultPropertiesFilename.get()); + this.args = toArgsWithWalletPassword.apply(args); + Config bisqClientOpts = new Config(this.args, defaultPropertiesFilename.get()); this.walletPassword = bisqClientOpts.getWalletPassword(); this.conf = bisqClientOpts.getConf(); this.grpcStubs = new GrpcStubs(bisqClientOpts.getHost(), bisqClientOpts.getPort(), bisqClientOpts.getPassword()); diff --git a/java-examples/src/main/java/bisq/bots/BotUtils.java b/java-examples/src/main/java/bisq/bots/BotUtils.java index 7bc5f3e..4fe1202 100644 --- a/java-examples/src/main/java/bisq/bots/BotUtils.java +++ b/java-examples/src/main/java/bisq/bots/BotUtils.java @@ -256,6 +256,19 @@ public static void sleep(long ms) { } } + /** + * Reads a wallet password from the console, and appends it to the given program args + * array as an additional config option, e.g., --wallet-password="be careful". + * The returned String[] is the original args array, plus the wallet-password option. + */ + public static final Function toArgsWithWalletPassword = (args) -> { + var walletPasswordPrompt = "An encrypted wallet must be unlocked" + + " for requests that read or update your wallet.\n" + + "Please enter your wallet password:"; + var unvalidatedWalletPassword = readWalletPassword(walletPasswordPrompt); + return appendWalletPasswordOpt(args, unvalidatedWalletPassword); + }; + /** * Return a wallet password read from stdin. If read from a command terminal, input will not be echoed. * If run in a virtual terminal (IDE console), the input will be echoed. @@ -284,7 +297,7 @@ public static String readWalletPassword(String prompt) { } /** - * Return the given String[] args with an additional --wallet-password=xyz option appended to it. + * Return the given String[] args with an additional --wallet-password="be careful" option appended to it. * * @param args program arguments * @param walletPassword wallet password diff --git a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBsq.java b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBsq.java index b93ef4b..3212478 100644 --- a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBsq.java +++ b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBsq.java @@ -93,6 +93,7 @@ public TakeBestPricedOfferToBuyBsq(String[] args) { @Override public void run() { var startTime = new Date().getTime(); + validateWalletPassword(walletPassword); validatePollingInterval(pollingInterval); printBotConfiguration(); @@ -169,9 +170,9 @@ private void takeOffer(TakeCriteria takeCriteria, OfferInfo offer) { private void printBotConfiguration() { var configsByLabel = new LinkedHashMap(); - configsByLabel.put("Bot OS:", "\t" + getOSName() + " " + getOSVersion()); + configsByLabel.put("Bot OS:", getOSName() + " " + getOSVersion()); var network = getNetwork(); - configsByLabel.put("BTC Network:", "\t" + network); + configsByLabel.put("BTC Network:", network); var isMainnet = network.equalsIgnoreCase("mainnet"); var mainnet30DayAvgBsqPrice = isMainnet ? get30DayAvgBsqPriceInBtc() : null; configsByLabel.put("My Payment Account:", ""); @@ -194,7 +195,7 @@ private void printBotConfiguration() { } else { configsByLabel.put("\tPreferred Trading Peers:", "N/A"); } - configsByLabel.put("Bot Polling Interval:", "\t" + pollingInterval + " ms"); + configsByLabel.put("Bot Polling Interval:", pollingInterval + " ms"); log.info(toTable.apply("Bot Configuration", configsByLabel)); } @@ -260,11 +261,7 @@ private void maybeShutdownAfterSuccessfulSwap() { BotUtils.isWithinBTCAmountBounds(offer, getMinAmount(), getMaxAmount()); public static void main(String[] args) { - @SuppressWarnings("unused") - String prompt = "An encrypted wallet must be unlocked before any offer can be taken.\n" - + "Please enter your wallet password:"; - String walletPassword = readWalletPassword(prompt); - TakeBestPricedOfferToBuyBsq bot = new TakeBestPricedOfferToBuyBsq(appendWalletPasswordOpt(args, walletPassword)); + TakeBestPricedOfferToBuyBsq bot = new TakeBestPricedOfferToBuyBsq(args); bot.run(); } diff --git a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBtc.java b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBtc.java index 08babaf..c281b39 100644 --- a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBtc.java +++ b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBtc.java @@ -132,8 +132,8 @@ public TakeBestPricedOfferToBuyBtc(String[] args) { @Override public void run() { var startTime = new Date().getTime(); - validatePollingInterval(pollingInterval); validateWalletPassword(walletPassword); + validatePollingInterval(pollingInterval); validateTradeFeeCurrencyCode(bisqTradeFeeCurrency); validatePaymentAccount(paymentAccount); printBotConfiguration(); @@ -306,9 +306,9 @@ private void shutdownAfterFailedTradePreparation() { private void printBotConfiguration() { var configsByLabel = new LinkedHashMap(); - configsByLabel.put("Bot OS:", "\t" + getOSName() + " " + getOSVersion()); + configsByLabel.put("Bot OS:", getOSName() + " " + getOSVersion()); var network = getNetwork(); - configsByLabel.put("BTC Network:", "\t" + network); + configsByLabel.put("BTC Network:", network); configsByLabel.put("My Payment Account:", ""); configsByLabel.put("\tPayment Account Id:", paymentAccount.getId()); configsByLabel.put("\tAccount Name:", paymentAccount.getAccountName()); @@ -324,16 +324,12 @@ private void printBotConfiguration() { } else { configsByLabel.put("\tPreferred Trading Peers:", "N/A"); } - configsByLabel.put("Bot Polling Interval:", "\t" + pollingInterval + " ms"); + configsByLabel.put("Bot Polling Interval:", pollingInterval + " ms"); log.info(toTable.apply("Bot Configuration", configsByLabel)); } public static void main(String[] args) { - @SuppressWarnings("unused") - String prompt = "An encrypted wallet must be unlocked before any offer can be taken.\n" - + "Please enter your wallet password:"; - String walletPassword = readWalletPassword(prompt); - TakeBestPricedOfferToBuyBtc bot = new TakeBestPricedOfferToBuyBtc(appendWalletPasswordOpt(args, walletPassword)); + TakeBestPricedOfferToBuyBtc bot = new TakeBestPricedOfferToBuyBtc(args); bot.run(); } diff --git a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBsq.java b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBsq.java index 2b13346..0933053 100644 --- a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBsq.java +++ b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBsq.java @@ -93,6 +93,7 @@ public TakeBestPricedOfferToSellBsq(String[] args) { @Override public void run() { var startTime = new Date().getTime(); + validateWalletPassword(walletPassword); validatePollingInterval(pollingInterval); printBotConfiguration(); @@ -169,9 +170,9 @@ private void takeOffer(TakeCriteria takeCriteria, OfferInfo offer) { private void printBotConfiguration() { var configsByLabel = new LinkedHashMap(); - configsByLabel.put("Bot OS:", "\t" + getOSName() + " " + getOSVersion()); + configsByLabel.put("Bot OS:", getOSName() + " " + getOSVersion()); var network = getNetwork(); - configsByLabel.put("BTC Network:", "\t" + network); + configsByLabel.put("BTC Network:", network); var isMainnet = network.equalsIgnoreCase("mainnet"); var mainnet30DayAvgBsqPrice = isMainnet ? get30DayAvgBsqPriceInBtc() : null; configsByLabel.put("My Payment Account:", ""); @@ -194,7 +195,7 @@ private void printBotConfiguration() { } else { configsByLabel.put("\tPreferred Trading Peers:", "N/A"); } - configsByLabel.put("Bot Polling Interval:", "\t" + pollingInterval + " ms"); + configsByLabel.put("Bot Polling Interval:", pollingInterval + " ms"); log.info(toTable.apply("Bot Configuration", configsByLabel)); } @@ -260,11 +261,7 @@ private void maybeShutdownAfterSuccessfulSwap() { BotUtils.isWithinBTCAmountBounds(offer, getMinAmount(), getMaxAmount()); public static void main(String[] args) { - @SuppressWarnings("unused") - String prompt = "An encrypted wallet must be unlocked before any offer can be taken.\n" - + "Please enter your wallet password:"; - String walletPassword = readWalletPassword(prompt); - TakeBestPricedOfferToSellBsq bot = new TakeBestPricedOfferToSellBsq(appendWalletPasswordOpt(args, walletPassword)); + TakeBestPricedOfferToSellBsq bot = new TakeBestPricedOfferToSellBsq(args); bot.run(); } diff --git a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBtc.java b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBtc.java index f6502b8..a6bd5b5 100644 --- a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBtc.java +++ b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBtc.java @@ -133,6 +133,7 @@ public TakeBestPricedOfferToSellBtc(String[] args) { @Override public void run() { var startTime = new Date().getTime(); + validateWalletPassword(walletPassword); validatePollingInterval(pollingInterval); validateTradeFeeCurrencyCode(bisqTradeFeeCurrency); validatePaymentAccount(paymentAccount); @@ -306,9 +307,9 @@ private void shutdownAfterFailedTradePreparation() { private void printBotConfiguration() { var configsByLabel = new LinkedHashMap(); - configsByLabel.put("Bot OS:", "\t" + getOSName() + " " + getOSVersion()); + configsByLabel.put("Bot OS:", getOSName() + " " + getOSVersion()); var network = getNetwork(); - configsByLabel.put("BTC Network:", "\t" + network); + configsByLabel.put("BTC Network:", network); configsByLabel.put("My Payment Account:", ""); configsByLabel.put("\tPayment Account Id:", paymentAccount.getId()); configsByLabel.put("\tAccount Name:", paymentAccount.getAccountName()); @@ -324,16 +325,12 @@ private void printBotConfiguration() { } else { configsByLabel.put("\tPreferred Trading Peers:", "N/A"); } - configsByLabel.put("Bot Polling Interval:", "\t" + pollingInterval + " ms"); + configsByLabel.put("Bot Polling Interval:", pollingInterval + " ms"); log.info(toTable.apply("Bot Configuration", configsByLabel)); } public static void main(String[] args) { - @SuppressWarnings("unused") - String prompt = "An encrypted wallet must be unlocked before any offer can be taken.\n" - + "Please enter your wallet password:"; - String walletPassword = readWalletPassword(prompt); - TakeBestPricedOfferToSellBtc bot = new TakeBestPricedOfferToSellBtc(appendWalletPasswordOpt(args, walletPassword)); + TakeBestPricedOfferToSellBtc bot = new TakeBestPricedOfferToSellBtc(args); bot.run(); } diff --git a/java-examples/src/main/resources/TakeBestPricedOfferToBuyBtc.properties b/java-examples/src/main/resources/TakeBestPricedOfferToBuyBtc.properties index 8a7c941..89783e7 100644 --- a/java-examples/src/main/resources/TakeBestPricedOfferToBuyBtc.properties +++ b/java-examples/src/main/resources/TakeBestPricedOfferToBuyBtc.properties @@ -3,7 +3,7 @@ maxTakeOffers=1 # # Taker bot's payment account id. Only BUY BTC offers using the same payment method will be considered for taking. -paymentAccountId=28030c83-f07d-4f0b-b824-019529279630 +paymentAccountId=6e58f3d9-e7a3-4799-aa38-e28e624d79a3 # # Taker bot's min market price margin. A candidate BUY BTC offer's price margin must be >= minMarketPriceMargin. # diff --git a/java-examples/src/main/resources/TakeBestPricedOfferToSellBsq.properties b/java-examples/src/main/resources/TakeBestPricedOfferToSellBsq.properties index f45e0a8..f09e8b0 100644 --- a/java-examples/src/main/resources/TakeBestPricedOfferToSellBsq.properties +++ b/java-examples/src/main/resources/TakeBestPricedOfferToSellBsq.properties @@ -1,18 +1,18 @@ # Maximum # of offers to take during one bot session. When reached, bot will shut down (but not the API daemon). -maxTakeOffers=10 +maxTakeOffers=100 # # Maximum distance from 30-day average BSQ trade price. # Note: all BSQ Swap offers have a fixed-price, but the bot uses a margin (%) of the 30-day price for comparison. maxMarketPriceMargin=0.00 # # Hard coded 30-day average BSQ trade price, used for development over regtest. -regtest30DayAvgBsqPrice=0.00005 +regtest30DayAvgBsqPrice=0.00037 # # Taker bot's min BTC amount to buy. The candidate BUY BTC offer's amount must be >= minAmount BTC. minAmount=0.01 # # Taker bot's max BTC amount to buy. The candidate BUY BTC offer's amount must be <= maxAmount BTC. -maxAmount=0.50 +maxAmount=0.90 # # Taker bot's max acceptable transaction fee rate (sats / byte). # Regtest fee rates are from https://price.bisq.wiz.biz/getFees diff --git a/java-examples/src/main/resources/TakeBestPricedOfferToSellBtc.properties b/java-examples/src/main/resources/TakeBestPricedOfferToSellBtc.properties index f689581..a4f51e2 100644 --- a/java-examples/src/main/resources/TakeBestPricedOfferToSellBtc.properties +++ b/java-examples/src/main/resources/TakeBestPricedOfferToSellBtc.properties @@ -3,7 +3,7 @@ maxTakeOffers=4 # # Taker bot's payment account id. Only SELL BTC offers using the same payment method will be considered for taking. -paymentAccountId=9ad3cc7a-7d32-453c-b9db-a3714b5b8f61 +paymentAccountId=6e58f3d9-e7a3-4799-aa38-e28e624d79a3 # # Taker bot's max market price margin. A candidate SELL BTC offer's price margin must be <= maxMarketPriceMargin. maxMarketPriceMargin=3.00 From c5d0259833f0755f1eee45103ccf1b9f9f33fe56 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sun, 26 Jun 2022 12:24:23 -0300 Subject: [PATCH 2/2] Print the day's BSQ swaps after each completed swap --- java-examples/src/main/java/bisq/bots/BotUtils.java | 1 - .../main/java/bisq/bots/TakeBestPricedOfferToBuyBsq.java | 4 ++++ .../main/java/bisq/bots/TakeBestPricedOfferToSellBsq.java | 4 ++++ .../main/resources/TakeBestPricedOfferToBuyBsq.properties | 6 +++--- .../main/resources/TakeBestPricedOfferToSellBsq.properties | 2 +- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/java-examples/src/main/java/bisq/bots/BotUtils.java b/java-examples/src/main/java/bisq/bots/BotUtils.java index 4fe1202..3582fae 100644 --- a/java-examples/src/main/java/bisq/bots/BotUtils.java +++ b/java-examples/src/main/java/bisq/bots/BotUtils.java @@ -416,7 +416,6 @@ public static void printTradeSummary(TradeInfo trade) { * @param trades list of trades */ public static void printTradesSummary(GetTradesRequest.Category category, List trades) { - log.info("{} trades:", category.name()); switch (category) { case CLOSED -> new TableBuilder(CLOSED_TRADES_TBL, trades).build().print(out); case FAILED -> new TableBuilder(FAILED_TRADES_TBL, trades).build().print(out); diff --git a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBsq.java b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBsq.java index 3212478..57c9ed5 100644 --- a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBsq.java +++ b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToBuyBsq.java @@ -28,6 +28,7 @@ import java.util.function.Predicate; import static bisq.bots.BotUtils.*; +import static bisq.proto.grpc.GetTradesRequest.Category.CLOSED; import static java.lang.String.format; import static java.lang.System.exit; import static java.math.RoundingMode.HALF_UP; @@ -227,6 +228,9 @@ private void handleFatalException(StatusRuntimeException fatalException) { * Lock the wallet, stop the API daemon, and terminate the bot. */ private void maybeShutdownAfterSuccessfulSwap() { + log.info("Here are today's completed trades:"); + printTradesSummaryForToday(CLOSED); + if (!isDryRun) { try { lockWallet(); diff --git a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBsq.java b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBsq.java index 0933053..b3f809e 100644 --- a/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBsq.java +++ b/java-examples/src/main/java/bisq/bots/TakeBestPricedOfferToSellBsq.java @@ -28,6 +28,7 @@ import java.util.function.Predicate; import static bisq.bots.BotUtils.*; +import static bisq.proto.grpc.GetTradesRequest.Category.CLOSED; import static java.lang.String.format; import static java.lang.System.exit; import static java.math.RoundingMode.HALF_UP; @@ -227,6 +228,9 @@ private void handleFatalException(StatusRuntimeException fatalException) { * Lock the wallet, stop the API daemon, and terminate the bot. */ private void maybeShutdownAfterSuccessfulSwap() { + log.info("Here are today's completed trades:"); + printTradesSummaryForToday(CLOSED); + if (!isDryRun) { try { lockWallet(); diff --git a/java-examples/src/main/resources/TakeBestPricedOfferToBuyBsq.properties b/java-examples/src/main/resources/TakeBestPricedOfferToBuyBsq.properties index 22176e7..444bc92 100644 --- a/java-examples/src/main/resources/TakeBestPricedOfferToBuyBsq.properties +++ b/java-examples/src/main/resources/TakeBestPricedOfferToBuyBsq.properties @@ -1,9 +1,9 @@ # Maximum # of offers to take during one bot session. When reached, bot will shut down (but not the API daemon). -maxTakeOffers=1 +maxTakeOffers=50 # # Minimum distance from 30-day average BSQ trade price. # Note: all BSQ Swap offers have a fixed-price, but the bot uses a margin (%) of the 30-day price for comparison. -minMarketPriceMargin=0 +minMarketPriceMargin=0.00 # # Hard coded 30-day average BSQ trade price, used for development over regtest. regtest30DayAvgBsqPrice=0.00005 @@ -12,7 +12,7 @@ regtest30DayAvgBsqPrice=0.00005 minAmount=0.01 # # Taker bot's max BTC amount to sell. The candidate SELL BTC offer's amount must be <= maxAmount BTC. -maxAmount=0.50 +maxAmount=0.90 # # Taker bot's max acceptable transaction fee rate (sats / byte). # Regtest fee rates are from https://price.bisq.wiz.biz/getFees diff --git a/java-examples/src/main/resources/TakeBestPricedOfferToSellBsq.properties b/java-examples/src/main/resources/TakeBestPricedOfferToSellBsq.properties index f09e8b0..97f13a0 100644 --- a/java-examples/src/main/resources/TakeBestPricedOfferToSellBsq.properties +++ b/java-examples/src/main/resources/TakeBestPricedOfferToSellBsq.properties @@ -1,5 +1,5 @@ # Maximum # of offers to take during one bot session. When reached, bot will shut down (but not the API daemon). -maxTakeOffers=100 +maxTakeOffers=50 # # Maximum distance from 30-day average BSQ trade price. # Note: all BSQ Swap offers have a fixed-price, but the bot uses a margin (%) of the 30-day price for comparison.