mirror of
https://github.com/bisq-network/bisq-api-reference.git
synced 2026-05-23 12:54:13 +00:00
Tidy up and document TakeBestPricedOfferToBuyBtc bot
This commit is contained in:
parent
52a6d29687
commit
e138d35761
@ -32,35 +32,56 @@ import static java.math.RoundingMode.HALF_UP;
|
|||||||
import static protobuf.OfferDirection.BUY;
|
import static protobuf.OfferDirection.BUY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The TakeBestPricedOfferToBuyBtc bot waits for attractively priced BUY BTC for fiat offers to appear, takes the offers
|
* This bot's general use case is to sell your BTC for fiat at a high BTC price. It periodically checks the
|
||||||
* (up to a maximum of configured {@link #maxTakeOffers}), then shuts down both the API daemon and itself (the bot),
|
* Buy BTC market, and takes a configured maximum number of offers to buy BTC from you according to criteria you
|
||||||
* to allow the user to start the desktop UI application and complete the trades.
|
* define in the bot's configuration file: <b>TakeBestPricedOfferToBuyBtc.properties</b> (located in project's
|
||||||
|
* src/main/resources directory). You will need to replace the default values in the configuration file for your
|
||||||
|
* use cases.
|
||||||
|
* <p><br/>
|
||||||
|
* After the maximum number of offers have been taken (good to start with 1), the bot will shut down the API daemon,
|
||||||
|
* then itself. You have to confirm the offer maker's fiat payment(s) outside Bisq, then complete the trade(s) in
|
||||||
|
* the <a href="https://bisq.network">Bisq Desktop</a> application.
|
||||||
* <p>
|
* <p>
|
||||||
* The benefit this bot provides is freeing up the user time spent watching the offer book in the UI, waiting for the
|
* Here is one possible use case:
|
||||||
* right offer to take. This bot increases the chance of beating the other nodes at taking the offer.
|
|
||||||
* <p>
|
|
||||||
* The disadvantage is that if the user takes offers with the API, she must complete the trades with the desktop UI.
|
|
||||||
* This problem is due to the inability of the API to fully automate every step of the trading protocol. Sending fiat
|
|
||||||
* payments, and confirming their receipt, are manual activities performed outside the Bisq daemon and desktop UI.
|
|
||||||
* Also, the API and the desktop UI cannot run at the same time. Care must be taken to shut down one before starting
|
|
||||||
* the other.
|
|
||||||
* <p>
|
|
||||||
* The criteria for determining which offers to take are defined in the bot's configuration file
|
|
||||||
* TakeBestPricedOfferToBuyBtc.properties (located in project's src/main/resources directory). The individual
|
|
||||||
* configurations are commented in the existing TakeBestPricedOfferToBuyBtc.properties, which should be used as a
|
|
||||||
* template for your own use case.
|
|
||||||
* <p>
|
|
||||||
* One possible use case for this bot is sell BTC for GBP:
|
|
||||||
* <pre>
|
|
||||||
* Take a "Faster Payment (Santander)" offer to buy BTC with GBP at or above current market price if:
|
|
||||||
* the offer maker is a preferred trading peer,
|
|
||||||
* and the offer's BTC amount is between 0.10 and 0.25 BTC,
|
|
||||||
* and the current transaction mining fee rate is below 20 sats / byte.
|
|
||||||
*
|
*
|
||||||
* Usage: TakeBestPricedOfferToBuyBtc --password=api-password --port=api-port \
|
*
|
||||||
* [--conf=take-best-priced-offer-to-buy-btc.conf] \
|
* <pre>
|
||||||
* [--dryrun=true|false]
|
* Take 3 "Faster Payment" offers to buy BTC with GBP, priced no lower than 2.00% above the current market
|
||||||
* [--simulate-regtest-payment=true|false]
|
* price if:
|
||||||
|
*
|
||||||
|
* the offer's BTC amount is between 0.10 and 0.25 BTC
|
||||||
|
* the offer maker is one of two preferred trading peers
|
||||||
|
* the current transaction mining fee rate is below 20 sats / byte
|
||||||
|
*
|
||||||
|
* The bot configurations for these rules are set in TakeBestPricedOfferToBuyBtc.properties as follows:
|
||||||
|
*
|
||||||
|
* maxTakeOffers=3
|
||||||
|
* minMarketPriceMargin=2.00
|
||||||
|
* minAmount=0.10
|
||||||
|
* maxAmount=0.25
|
||||||
|
* preferredTradingPeers=preferred-address-1.onion:9999,preferred-address-2.onion:9999
|
||||||
|
* maxTxFeeRate=20
|
||||||
|
* </pre>
|
||||||
|
* <b>Usage</b>
|
||||||
|
* <p><br/>
|
||||||
|
* You must encrypt your wallet password before running this bot. If it is not already, you can use the CLI:
|
||||||
|
* <pre>
|
||||||
|
* $ ./bisq-cli --password=xyz --port=9998 setwalletpassword --wallet-password="be careful"
|
||||||
|
* </pre>
|
||||||
|
* There are some {@link bisq.bots.Config program options} common to all the Java bot examples, passed on the command
|
||||||
|
* line. The only one you must provide (no default value) is your API daemon's password option:
|
||||||
|
* `--password <String>`. The bot will prompt you for your wallet-password in the console.
|
||||||
|
* <p><br/>
|
||||||
|
* You can pass the '--dryrun=true' option to the program to see what offers your bot <i>would take</i> with a given
|
||||||
|
* configuration. This will help you avoid taking offers by mistake.
|
||||||
|
* <pre>
|
||||||
|
* TakeBestPricedOfferToBuyBtc --password=api-password --port=api-port [--dryrun=true|false]
|
||||||
|
* </pre>
|
||||||
|
* If your API daemon is running on a local regtest network (with a trading peer), you can pass the
|
||||||
|
* '--simulate-regtest-payment=true' option to the program to simulate the full trade protocol. The bot will print
|
||||||
|
* your regtest trading peer's CLI commands in the console, for you to copy/paste into another terminal.
|
||||||
|
* <pre>
|
||||||
|
* TakeBestPricedOfferToBuyBtc --password=api-password --port=api-port [--simulate-regtest-payment=true|false]
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -156,7 +177,6 @@ public class TakeBestPricedOfferToBuyBtc extends AbstractBot {
|
|||||||
takeCriteria.printOfferAgainstCriteria(highestPricedOffer);
|
takeCriteria.printOfferAgainstCriteria(highestPricedOffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
printDryRunProgress();
|
|
||||||
runCountdown(log, pollingInterval);
|
runCountdown(log, pollingInterval);
|
||||||
pingDaemon(startTime);
|
pingDaemon(startTime);
|
||||||
}
|
}
|
||||||
@ -170,16 +190,21 @@ public class TakeBestPricedOfferToBuyBtc extends AbstractBot {
|
|||||||
private void takeOffer(TakeCriteria takeCriteria, OfferInfo offer) {
|
private void takeOffer(TakeCriteria takeCriteria, OfferInfo offer) {
|
||||||
log.info("Will attempt to take offer '{}'.", offer.getId());
|
log.info("Will attempt to take offer '{}'.", offer.getId());
|
||||||
takeCriteria.printOfferAgainstCriteria(offer);
|
takeCriteria.printOfferAgainstCriteria(offer);
|
||||||
|
|
||||||
|
// An encrypted wallet must be unlocked before calling takeoffer and gettrade(s).
|
||||||
|
// Unlock the wallet for 5 minutes. If the wallet is already unlocked, this request
|
||||||
|
// will override the timeout of the previous unlock request.
|
||||||
|
try {
|
||||||
|
unlockWallet(walletPassword, 300);
|
||||||
|
} catch (NonFatalException nonFatalException) {
|
||||||
|
handleNonFatalException(nonFatalException, pollingInterval);
|
||||||
|
}
|
||||||
|
|
||||||
if (isDryRun) {
|
if (isDryRun) {
|
||||||
addToOffersTaken(offer);
|
addToOffersTaken(offer);
|
||||||
numOffersTaken++;
|
numOffersTaken++;
|
||||||
maybeShutdownAfterSuccessfulTradeCreation(numOffersTaken, maxTakeOffers);
|
|
||||||
} else {
|
} else {
|
||||||
// An encrypted wallet must be unlocked before calling takeoffer and gettrade.
|
|
||||||
// Unlock the wallet for 5 minutes. If the wallet is already unlocked,
|
|
||||||
// this command will override the timeout of the previous unlock command.
|
|
||||||
try {
|
try {
|
||||||
unlockWallet(walletPassword, 600);
|
|
||||||
printBTCBalances("BTC Balances Before Take Offer Attempt");
|
printBTCBalances("BTC Balances Before Take Offer Attempt");
|
||||||
// Blocks until new trade is prepared, or times out.
|
// Blocks until new trade is prepared, or times out.
|
||||||
takeV1ProtocolOffer(offer, paymentAccount, bisqTradeFeeCurrency, pollingInterval);
|
takeV1ProtocolOffer(offer, paymentAccount, bisqTradeFeeCurrency, pollingInterval);
|
||||||
@ -194,13 +219,13 @@ public class TakeBestPricedOfferToBuyBtc extends AbstractBot {
|
|||||||
printBTCBalances("BTC Balances After Simulated Trade Completion");
|
printBTCBalances("BTC Balances After Simulated Trade Completion");
|
||||||
}
|
}
|
||||||
numOffersTaken++;
|
numOffersTaken++;
|
||||||
maybeShutdownAfterSuccessfulTradeCreation(numOffersTaken, maxTakeOffers);
|
|
||||||
} catch (NonFatalException nonFatalException) {
|
} catch (NonFatalException nonFatalException) {
|
||||||
handleNonFatalException(nonFatalException, pollingInterval);
|
handleNonFatalException(nonFatalException, pollingInterval);
|
||||||
} catch (StatusRuntimeException fatalException) {
|
} catch (StatusRuntimeException fatalException) {
|
||||||
shutdownAfterTakeOfferFailure(fatalException);
|
shutdownAfterTakeOfferFailure(fatalException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
maybeShutdownAfterSuccessfulTradeCreation(numOffersTaken, maxTakeOffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -218,6 +243,8 @@ public class TakeBestPricedOfferToBuyBtc extends AbstractBot {
|
|||||||
configsByLabel.put("Bot OS:", getOSName() + " " + getOSVersion());
|
configsByLabel.put("Bot OS:", getOSName() + " " + getOSVersion());
|
||||||
var network = getNetwork();
|
var network = getNetwork();
|
||||||
configsByLabel.put("BTC Network:", network);
|
configsByLabel.put("BTC Network:", network);
|
||||||
|
configsByLabel.put("Dry Run?", isDryRun ? "YES" : "NO");
|
||||||
|
configsByLabel.put("Simulate Regtest Trade?", canSimulatePaymentSteps ? "YES" : "NO");
|
||||||
configsByLabel.put("My Payment Account:", "");
|
configsByLabel.put("My Payment Account:", "");
|
||||||
configsByLabel.put("\tPayment Account Id:", paymentAccount.getId());
|
configsByLabel.put("\tPayment Account Id:", paymentAccount.getId());
|
||||||
configsByLabel.put("\tAccount Name:", paymentAccount.getAccountName());
|
configsByLabel.put("\tAccount Name:", paymentAccount.getAccountName());
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user