Adjust CLI to support getting/taking BSQ swaps

Also refactored some of the opt parsers.
This commit is contained in:
ghubstan 2021-11-24 13:10:34 -03:00
parent 3aae052813
commit 0c5c343fe0
No known key found for this signature in database
GPG key ID: E35592D6800A861E
11 changed files with 57 additions and 104 deletions

View file

@ -18,6 +18,7 @@
package bisq.cli;
import bisq.proto.grpc.OfferInfo;
import bisq.proto.grpc.TradeInfo;
import io.grpc.StatusRuntimeException;
@ -45,6 +46,7 @@ import static bisq.cli.CurrencyFormat.*;
import static bisq.cli.Method.*;
import static bisq.cli.opts.OptLabel.*;
import static bisq.cli.table.builder.TableType.*;
import static bisq.proto.grpc.GetOfferCategoryReply.OfferCategory.BSQ_SWAP;
import static java.lang.String.format;
import static java.lang.System.err;
import static java.lang.System.exit;
@ -62,11 +64,11 @@ import bisq.cli.opts.EditOfferOptionParser;
import bisq.cli.opts.GetAddressBalanceOptionParser;
import bisq.cli.opts.GetBTCMarketPriceOptionParser;
import bisq.cli.opts.GetBalanceOptionParser;
import bisq.cli.opts.GetOfferOptionParser;
import bisq.cli.opts.GetOffersOptionParser;
import bisq.cli.opts.GetPaymentAcctFormOptionParser;
import bisq.cli.opts.GetTradeOptionParser;
import bisq.cli.opts.GetTransactionOptionParser;
import bisq.cli.opts.OfferIdOptionParser;
import bisq.cli.opts.RegisterDisputeAgentOptionParser;
import bisq.cli.opts.RemoveWalletPasswordOptionParser;
import bisq.cli.opts.SendBsqOptionParser;
@ -392,7 +394,7 @@ public class CliMain {
return;
}
case getoffer: {
var opts = new GetOfferOptionParser(args).parse();
var opts = new OfferIdOptionParser(args).parse();
if (opts.isForHelp()) {
out.println(client.getMethodHelp(method));
return;
@ -403,7 +405,7 @@ public class CliMain {
return;
}
case getmyoffer: {
var opts = new GetOfferOptionParser(args).parse();
var opts = new OfferIdOptionParser(args).parse();
if (opts.isForHelp()) {
out.println(client.getMethodHelp(method));
return;
@ -446,15 +448,25 @@ public class CliMain {
return;
}
case takeoffer: {
var opts = new TakeOfferOptionParser(args).parse();
if (opts.isForHelp()) {
var offerIdOpt = new OfferIdOptionParser(args).parse();
if (offerIdOpt.isForHelp()) {
out.println(client.getMethodHelp(method));
return;
}
var offerId = opts.getOfferId();
var paymentAccountId = opts.getPaymentAccountId();
var takerFeeCurrencyCode = opts.getTakerFeeCurrencyCode();
var trade = client.takeOffer(offerId, paymentAccountId, takerFeeCurrencyCode);
var offerId = offerIdOpt.getOfferId();
TradeInfo trade;
// We only send an 'offer-id' param when taking a BsqSwapOffer.
// Find out what kind of offer is being taken before sending a
// 'takeoffer' request.
var offerCategory = client.getAvailableOfferCategory(offerId);
if (offerCategory.equals(BSQ_SWAP)) {
trade = client.takeBsqSwapOffer(offerId);
} else {
var opts = new TakeOfferOptionParser(args).parse();
var paymentAccountId = opts.getPaymentAccountId();
var takerFeeCurrencyCode = opts.getTakerFeeCurrencyCode();
trade = client.takeOffer(offerId, paymentAccountId, takerFeeCurrencyCode);
}
out.printf("trade %s successfully taken%n", trade.getTradeId());
return;
}
@ -825,7 +837,7 @@ public class CliMain {
stream.format(rowFormat, "", "--currency-code=<currency-code>", "");
stream.println();
stream.format(rowFormat, takeoffer.name(), "--offer-id=<offer-id> \\", "Take offer with id");
stream.format(rowFormat, "", "--payment-account=<payment-account-id>", "");
stream.format(rowFormat, "", "[--payment-account=<payment-account-id>]", "");
stream.format(rowFormat, "", "[--fee-currency=<btc|bsq>]", "");
stream.println();
stream.format(rowFormat, gettrade.name(), "--trade-id=<trade-id> \\", "Get trade summary or full contract");

View file

@ -27,7 +27,6 @@ import bisq.proto.grpc.GetVersionRequest;
import bisq.proto.grpc.OfferInfo;
import bisq.proto.grpc.RegisterDisputeAgentRequest;
import bisq.proto.grpc.StopRequest;
import bisq.proto.grpc.TakeBsqSwapOfferReply;
import bisq.proto.grpc.TakeOfferReply;
import bisq.proto.grpc.TradeInfo;
import bisq.proto.grpc.TxFeeRateInfo;
@ -349,34 +348,18 @@ public final class GrpcClient {
return offersServiceRequest.sortOffersByDate(offers);
}
public TakeBsqSwapOfferReply getTakeBsqSwapOfferReply(String offerId,
String paymentAccountId,
String takerFeeCurrencyCode) {
return tradesServiceRequest.getTakeBsqSwapOfferReply(offerId,
paymentAccountId,
takerFeeCurrencyCode);
}
public TakeOfferReply getTakeOfferReply(String offerId, String paymentAccountId, String takerFeeCurrencyCode) {
return tradesServiceRequest.getTakeOfferReply(offerId, paymentAccountId, takerFeeCurrencyCode);
}
public TradeInfo takeBsqSwapOffer(String offerId, String paymentAccountId, String takerFeeCurrencyCode) {
var reply = getTakeBsqSwapOfferReply(offerId, paymentAccountId, takerFeeCurrencyCode);
if (reply.hasBsqSwapTrade())
return reply.getBsqSwapTrade();
else
throw new IllegalStateException(reply.getFailureReason().getDescription());
public TradeInfo takeBsqSwapOffer(String offerId) {
return tradesServiceRequest.takeBsqSwapOffer(offerId);
}
public TradeInfo takeOffer(String offerId, String paymentAccountId, String takerFeeCurrencyCode) {
return tradesServiceRequest.takeOffer(offerId, paymentAccountId, takerFeeCurrencyCode);
}
public TradeInfo getBsqSwapTrade(String tradeId) {
return tradesServiceRequest.getBsqSwapTrade(tradeId);
}
public TradeInfo getTrade(String tradeId) {
return tradesServiceRequest.getTrade(tradeId);
}

View file

@ -18,14 +18,7 @@
package bisq.cli.opts;
import joptsimple.OptionSpec;
import static bisq.cli.opts.OptLabel.OPT_OFFER_ID;
public class CancelOfferOptionParser extends AbstractMethodOptionParser implements MethodOpts {
final OptionSpec<String> offerIdOpt = parser.accepts(OPT_OFFER_ID, "id of offer to cancel")
.withRequiredArg();
public class CancelOfferOptionParser extends OfferIdOptionParser implements MethodOpts {
public CancelOfferOptionParser(String[] args) {
super(args);
@ -34,12 +27,7 @@ public class CancelOfferOptionParser extends AbstractMethodOptionParser implemen
public CancelOfferOptionParser parse() {
super.parse();
// Short circuit opt validation if user just wants help.
if (options.has(helpOpt))
return this;
if (!options.has(offerIdOpt) || options.valueOf(offerIdOpt).isEmpty())
throw new IllegalArgumentException("no offer id specified");
// Super class will short-circuit parsing if help option is present.
return this;
}

View file

@ -28,7 +28,7 @@ import static joptsimple.internal.Strings.EMPTY;
public class CreateOfferOptionParser extends AbstractMethodOptionParser implements MethodOpts {
final OptionSpec<String> paymentAccountIdOpt = parser.accepts(OPT_PAYMENT_ACCOUNT,
"id of payment account used for offer")
"id of payment account used for offer")
.withRequiredArg()
.defaultsTo(EMPTY);

View file

@ -29,7 +29,7 @@ import static java.lang.String.format;
public class CreatePaymentAcctOptionParser extends AbstractMethodOptionParser implements MethodOpts {
final OptionSpec<String> paymentAcctFormPathOpt = parser.accepts(OPT_PAYMENT_ACCOUNT_FORM,
"path to json payment account form")
"path to json payment account form")
.withRequiredArg();
public CreatePaymentAcctOptionParser(String[] args) {

View file

@ -24,7 +24,10 @@ import joptsimple.OptionSpec;
import java.math.BigDecimal;
import static bisq.cli.opts.OptLabel.*;
import static bisq.cli.opts.OptLabel.OPT_ENABLE;
import static bisq.cli.opts.OptLabel.OPT_FIXED_PRICE;
import static bisq.cli.opts.OptLabel.OPT_MKT_PRICE_MARGIN;
import static bisq.cli.opts.OptLabel.OPT_TRIGGER_PRICE;
import static bisq.proto.grpc.EditOfferRequest.EditType.*;
import static java.lang.String.format;
@ -32,26 +35,23 @@ import static java.lang.String.format;
import org.checkerframework.checker.nullness.qual.Nullable;
public class EditOfferOptionParser extends AbstractMethodOptionParser implements MethodOpts {
public class EditOfferOptionParser extends OfferIdOptionParser implements MethodOpts {
static int OPT_ENABLE_ON = 1;
static int OPT_ENABLE_OFF = 0;
static int OPT_ENABLE_IGNORED = -1;
final OptionSpec<String> offerIdOpt = parser.accepts(OPT_OFFER_ID, "id of offer to cancel")
.withRequiredArg();
final OptionSpec<String> fixedPriceOpt = parser.accepts(OPT_FIXED_PRICE, "fixed btc price")
.withOptionalArg()
.defaultsTo("0");
final OptionSpec<String> mktPriceMarginOpt = parser.accepts(OPT_MKT_PRICE_MARGIN,
"market btc price margin (%)")
"market btc price margin (%)")
.withOptionalArg()
.defaultsTo("0.00");
final OptionSpec<String> triggerPriceOpt = parser.accepts(OPT_TRIGGER_PRICE,
"trigger price (applies to mkt price margin based offers)")
"trigger price (applies to mkt price margin based offers)")
.withOptionalArg()
.defaultsTo("0");
@ -59,7 +59,7 @@ public class EditOfferOptionParser extends AbstractMethodOptionParser implements
// activation state). For this reason, a boolean type is not used (can only be
// true or false).
final OptionSpec<String> enableOpt = parser.accepts(OPT_ENABLE,
"enable or disable offer")
"enable or disable offer")
.withOptionalArg()
.ofType(String.class);
@ -72,12 +72,7 @@ public class EditOfferOptionParser extends AbstractMethodOptionParser implements
public EditOfferOptionParser parse() {
super.parse();
// Short circuit opt validation if user just wants help.
if (options.has(helpOpt))
return this;
if (!options.has(offerIdOpt) || options.valueOf(offerIdOpt).isEmpty())
throw new IllegalArgumentException("no offer id specified");
// Super class will short-circuit parsing if help option is present.
boolean hasNoEditDetails = !options.has(fixedPriceOpt)
&& !options.has(mktPriceMarginOpt)
@ -201,10 +196,6 @@ public class EditOfferOptionParser extends AbstractMethodOptionParser implements
return this;
}
public String getOfferId() {
return options.valueOf(offerIdOpt);
}
public String getFixedPrice() {
if (offerEditType.equals(FIXED_PRICE_ONLY) || offerEditType.equals(FIXED_PRICE_AND_ACTIVATION_STATE)) {
return options.has(fixedPriceOpt) ? options.valueOf(fixedPriceOpt) : "0";

View file

@ -25,7 +25,7 @@ import static bisq.cli.opts.OptLabel.OPT_PAYMENT_METHOD_ID;
public class GetPaymentAcctFormOptionParser extends AbstractMethodOptionParser implements MethodOpts {
final OptionSpec<String> paymentMethodIdOpt = parser.accepts(OPT_PAYMENT_METHOD_ID,
"id of payment method type used by a payment account")
"id of payment method type used by a payment account")
.withRequiredArg();
public GetPaymentAcctFormOptionParser(String[] args) {

View file

@ -22,16 +22,20 @@ import joptsimple.OptionSpec;
import static bisq.cli.opts.OptLabel.OPT_OFFER_ID;
public class GetOfferOptionParser extends AbstractMethodOptionParser implements MethodOpts {
/**
* Superclass for option parsers requiring an offer-id. Avoids a small amount of
* duplicated boilerplate.
*/
public class OfferIdOptionParser extends AbstractMethodOptionParser implements MethodOpts {
final OptionSpec<String> offerIdOpt = parser.accepts(OPT_OFFER_ID, "id of offer to get")
final OptionSpec<String> offerIdOpt = parser.accepts(OPT_OFFER_ID, "id of offer")
.withRequiredArg();
public GetOfferOptionParser(String[] args) {
public OfferIdOptionParser(String[] args) {
super(args);
}
public GetOfferOptionParser parse() {
public OfferIdOptionParser parse() {
super.parse();
// Short circuit opt validation if user just wants help.

View file

@ -25,7 +25,7 @@ import static bisq.cli.opts.OptLabel.OPT_TX_FEE_RATE;
public class SetTxFeeRateOptionParser extends AbstractMethodOptionParser implements MethodOpts {
final OptionSpec<String> feeRateOpt = parser.accepts(OPT_TX_FEE_RATE,
"tx fee rate preference (sats/byte)")
"tx fee rate preference (sats/byte)")
.withRequiredArg();
public SetTxFeeRateOptionParser(String[] args) {

View file

@ -21,13 +21,9 @@ package bisq.cli.opts;
import joptsimple.OptionSpec;
import static bisq.cli.opts.OptLabel.OPT_FEE_CURRENCY;
import static bisq.cli.opts.OptLabel.OPT_OFFER_ID;
import static bisq.cli.opts.OptLabel.OPT_PAYMENT_ACCOUNT;
public class TakeOfferOptionParser extends AbstractMethodOptionParser implements MethodOpts {
final OptionSpec<String> offerIdOpt = parser.accepts(OPT_OFFER_ID, "id of offer to take")
.withRequiredArg();
public class TakeOfferOptionParser extends OfferIdOptionParser implements MethodOpts {
final OptionSpec<String> paymentAccountIdOpt = parser.accepts(OPT_PAYMENT_ACCOUNT, "id of payment account used for trade")
.withRequiredArg();
@ -43,12 +39,7 @@ public class TakeOfferOptionParser extends AbstractMethodOptionParser implements
public TakeOfferOptionParser parse() {
super.parse();
// Short circuit opt validation if user just wants help.
if (options.has(helpOpt))
return this;
if (!options.has(offerIdOpt) || options.valueOf(offerIdOpt).isEmpty())
throw new IllegalArgumentException("no offer id specified");
// Super class will short-circuit parsing if help option is present.
if (!options.has(paymentAccountIdOpt) || options.valueOf(paymentAccountIdOpt).isEmpty())
throw new IllegalArgumentException("no payment account id specified");
@ -56,10 +47,6 @@ public class TakeOfferOptionParser extends AbstractMethodOptionParser implements
return this;
}
public String getOfferId() {
return options.valueOf(offerIdOpt);
}
public String getPaymentAccountId() {
return options.valueOf(paymentAccountIdOpt);
}

View file

@ -21,8 +21,6 @@ import bisq.proto.grpc.ConfirmPaymentReceivedRequest;
import bisq.proto.grpc.ConfirmPaymentStartedRequest;
import bisq.proto.grpc.GetTradeRequest;
import bisq.proto.grpc.KeepFundsRequest;
import bisq.proto.grpc.TakeBsqSwapOfferReply;
import bisq.proto.grpc.TakeBsqSwapOfferRequest;
import bisq.proto.grpc.TakeOfferReply;
import bisq.proto.grpc.TakeOfferRequest;
import bisq.proto.grpc.TradeInfo;
@ -40,17 +38,6 @@ public class TradesServiceRequest {
this.grpcStubs = grpcStubs;
}
public TakeBsqSwapOfferReply getTakeBsqSwapOfferReply(String offerId,
String paymentAccountId,
String takerFeeCurrencyCode) {
var request = TakeBsqSwapOfferRequest.newBuilder()
.setOfferId(offerId)
.setPaymentAccountId(paymentAccountId)
.setTakerFeeCurrencyCode(takerFeeCurrencyCode)
.build();
return grpcStubs.tradesService.takeBsqSwapOffer(request);
}
public TakeOfferReply getTakeOfferReply(String offerId, String paymentAccountId, String takerFeeCurrencyCode) {
var request = TakeOfferRequest.newBuilder()
.setOfferId(offerId)
@ -60,19 +47,20 @@ public class TradesServiceRequest {
return grpcStubs.tradesService.takeOffer(request);
}
public TradeInfo takeOffer(String offerId, String paymentAccountId, String takerFeeCurrencyCode) {
var reply = getTakeOfferReply(offerId, paymentAccountId, takerFeeCurrencyCode);
public TradeInfo takeBsqSwapOffer(String offerId) {
var reply = getTakeOfferReply(offerId, "", "");
if (reply.hasTrade())
return reply.getTrade();
else
throw new IllegalStateException(reply.getFailureReason().getDescription());
}
public TradeInfo getBsqSwapTrade(String tradeId) {
var request = GetTradeRequest.newBuilder()
.setTradeId(tradeId)
.build();
return grpcStubs.tradesService.getBsqSwapTrade(request).getBsqSwapTrade();
public TradeInfo takeOffer(String offerId, String paymentAccountId, String takerFeeCurrencyCode) {
var reply = getTakeOfferReply(offerId, paymentAccountId, takerFeeCurrencyCode);
if (reply.hasTrade())
return reply.getTrade();
else
throw new IllegalStateException(reply.getFailureReason().getDescription());
}
public TradeInfo getTrade(String tradeId) {