Add API CLI's takeoffer amount param

This commit is contained in:
ghubstan 2022-08-06 15:09:52 -03:00
parent c57b573d5c
commit 2a5bc45af1
No known key found for this signature in database
GPG key ID: E35592D6800A861E
6 changed files with 180 additions and 15 deletions

View file

@ -80,6 +80,7 @@ import bisq.cli.opts.SendBtcOptionParser;
import bisq.cli.opts.SetTxFeeRateOptionParser;
import bisq.cli.opts.SetWalletPasswordOptionParser;
import bisq.cli.opts.SimpleMethodOptionParser;
import bisq.cli.opts.TakeBsqSwapOfferOptionParser;
import bisq.cli.opts.TakeOfferOptionParser;
import bisq.cli.opts.UnlockWalletOptionParser;
import bisq.cli.opts.VerifyBsqSentToAddressOptionParser;
@ -504,12 +505,15 @@ public class CliMain {
// 'takeoffer' request.
var offerCategory = client.getAvailableOfferCategory(offerId);
if (offerCategory.equals(BSQ_SWAP)) {
trade = client.takeBsqSwapOffer(offerId);
var opts = new TakeBsqSwapOfferOptionParser(args).parse();
var amount = toSatoshis(opts.getAmount());
trade = client.takeBsqSwapOffer(offerId, amount);
} else {
var opts = new TakeOfferOptionParser(args).parse();
var amount = toSatoshis(opts.getAmount());
var paymentAccountId = opts.getPaymentAccountId();
var takerFeeCurrencyCode = opts.getTakerFeeCurrencyCode();
trade = client.takeOffer(offerId, paymentAccountId, takerFeeCurrencyCode);
trade = client.takeOffer(offerId, paymentAccountId, takerFeeCurrencyCode, amount);
}
out.printf("trade %s successfully taken%n", trade.getTradeId());
return;
@ -912,6 +916,7 @@ public class CliMain {
stream.format(rowFormat, takeoffer.name(), "--offer-id=<offer-id> \\", "Take offer with id");
stream.format(rowFormat, "", "[--payment-account=<payment-account-id>]", "");
stream.format(rowFormat, "", "[--fee-currency=<btc|bsq>]", "");
stream.format(rowFormat, "", "[--amount=<min-btc-amount >= amount <= btc-amount>]", "");
stream.println();
stream.format(rowFormat, gettrade.name(), "--trade-id=<trade-id> \\", "Get trade summary or full contract");
stream.format(rowFormat, "", "[--show-contract=<true|false>]", "");

View file

@ -325,12 +325,18 @@ public final class GrpcClient {
return offersServiceRequest.getMyBsqSwapOffersSortedByDate();
}
public TradeInfo takeBsqSwapOffer(String offerId) {
return tradesServiceRequest.takeBsqSwapOffer(offerId);
public TradeInfo takeBsqSwapOffer(String offerId, long amount) {
return tradesServiceRequest.takeBsqSwapOffer(offerId, amount);
}
public TradeInfo takeOffer(String offerId, String paymentAccountId, String takerFeeCurrencyCode) {
return tradesServiceRequest.takeOffer(offerId, paymentAccountId, takerFeeCurrencyCode);
public TradeInfo takeOffer(String offerId,
String paymentAccountId,
String takerFeeCurrencyCode,
long amount) {
return tradesServiceRequest.takeOffer(offerId,
paymentAccountId,
takerFeeCurrencyCode,
amount);
}
public TradeInfo getTrade(String tradeId) {

View file

@ -0,0 +1,60 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.cli.opts;
import joptsimple.OptionSpec;
import static bisq.cli.CurrencyFormat.toSatoshis;
import static bisq.cli.opts.OptLabel.OPT_AMOUNT;
import static bisq.cli.opts.OptLabel.OPT_FEE_CURRENCY;
import static bisq.cli.opts.OptLabel.OPT_PAYMENT_ACCOUNT_ID;
public class TakeBsqSwapOfferOptionParser extends OfferIdOptionParser implements MethodOpts {
final OptionSpec<String> amountOpt = parser.accepts(OPT_AMOUNT, "intended amount of btc to buy or sell")
.withRequiredArg()
.defaultsTo("0");
public TakeBsqSwapOfferOptionParser(String[] args) {
super(args, true);
}
public TakeBsqSwapOfferOptionParser parse() {
super.parse();
// Super class will short-circuit parsing if help option is present.
if (options.has(amountOpt)) {
if (options.valueOf(amountOpt).isEmpty())
throw new IllegalArgumentException("no intended btc trade amount specified");
try {
toSatoshis(options.valueOf(amountOpt));
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException("invalid amount: " + ex.getMessage());
}
}
return this;
}
public String getAmount() {
return options.valueOf(amountOpt);
}
}

View file

@ -20,11 +20,16 @@ package bisq.cli.opts;
import joptsimple.OptionSpec;
import static bisq.cli.CurrencyFormat.toSatoshis;
import static bisq.cli.opts.OptLabel.OPT_AMOUNT;
import static bisq.cli.opts.OptLabel.OPT_FEE_CURRENCY;
import static bisq.cli.opts.OptLabel.OPT_PAYMENT_ACCOUNT_ID;
public class TakeOfferOptionParser extends OfferIdOptionParser implements MethodOpts {
final OptionSpec<String> amountOpt = parser.accepts(OPT_AMOUNT, "intended amount of btc to buy or sell")
.withRequiredArg()
.defaultsTo("0");
final OptionSpec<String> paymentAccountIdOpt = parser.accepts(OPT_PAYMENT_ACCOUNT_ID, "id of payment account used for trade")
.withRequiredArg();
@ -41,12 +46,27 @@ public class TakeOfferOptionParser extends OfferIdOptionParser implements Method
// Super class will short-circuit parsing if help option is present.
if (options.has(amountOpt)) {
if (options.valueOf(amountOpt).isEmpty())
throw new IllegalArgumentException("no intended btc trade amount specified");
try {
toSatoshis(options.valueOf(amountOpt));
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException("invalid amount: " + ex.getMessage());
}
}
if (!options.has(paymentAccountIdOpt) || options.valueOf(paymentAccountIdOpt).isEmpty())
throw new IllegalArgumentException("no payment account id specified");
return this;
}
public String getAmount() {
return options.valueOf(amountOpt);
}
public String getPaymentAccountId() {
return options.valueOf(paymentAccountIdOpt);
}

View file

@ -46,25 +46,38 @@ public class TradesServiceRequest {
this.grpcStubs = grpcStubs;
}
public TakeOfferReply getTakeOfferReply(String offerId, String paymentAccountId, String takerFeeCurrencyCode) {
public TakeOfferReply getTakeOfferReply(String offerId,
String paymentAccountId,
String takerFeeCurrencyCode,
long amount) {
var request = TakeOfferRequest.newBuilder()
.setOfferId(offerId)
.setPaymentAccountId(paymentAccountId)
.setTakerFeeCurrencyCode(takerFeeCurrencyCode)
.setAmount(amount)
.build();
return grpcStubs.tradesService.takeOffer(request);
}
public TradeInfo takeBsqSwapOffer(String offerId) {
var reply = getTakeOfferReply(offerId, "", "");
public TradeInfo takeBsqSwapOffer(String offerId, long amount) {
var reply = getTakeOfferReply(offerId,
"",
"",
amount);
if (reply.hasTrade())
return reply.getTrade();
else
throw new IllegalStateException(reply.getFailureReason().getDescription());
}
public TradeInfo takeOffer(String offerId, String paymentAccountId, String takerFeeCurrencyCode) {
var reply = getTakeOfferReply(offerId, paymentAccountId, takerFeeCurrencyCode);
public TradeInfo takeOffer(String offerId,
String paymentAccountId,
String takerFeeCurrencyCode,
long amount) {
var reply = getTakeOfferReply(offerId,
paymentAccountId,
takerFeeCurrencyCode,
amount);
if (reply.hasTrade())
return reply.getTrade();
else

View file

@ -2,10 +2,8 @@ package bisq.cli.opts;
import org.junit.jupiter.api.Test;
import static bisq.cli.Method.canceloffer;
import static bisq.cli.Method.createcryptopaymentacct;
import static bisq.cli.Method.createoffer;
import static bisq.cli.Method.createpaymentacct;
import static bisq.cli.Method.*;
import static bisq.cli.Method.takeoffer;
import static bisq.cli.opts.OptLabel.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ -383,4 +381,67 @@ public class OptionParsersTest {
assertEquals(currencyCode, parser.getCurrencyCode());
assertEquals(address, parser.getAddress());
}
// takeoffer opt parser tests
@Test
public void testTakeOfferForDefaultAmount() {
var offerId = "ABC-OFFER-ID";
var paymentAccountId = "ABC-ACCT-ID";
var takerFeeCurrencyCode = "BSQ";
var defaultAmount = "0";
String[] args = new String[]{
PASSWORD_OPT,
takeoffer.name(),
"--" + OPT_OFFER_ID + "=" + offerId,
"--" + OPT_PAYMENT_ACCOUNT_ID + "=" + paymentAccountId,
"--" + OPT_FEE_CURRENCY + "=" + takerFeeCurrencyCode
};
var parser = new TakeOfferOptionParser(args).parse();
assertEquals(offerId, parser.getOfferId());
assertEquals(paymentAccountId, parser.getPaymentAccountId());
assertEquals(takerFeeCurrencyCode, parser.getTakerFeeCurrencyCode());
assertEquals(defaultAmount, parser.getAmount());
}
@Test
public void testTakeOfferForNegativeAmount() {
var offerId = "ABC-OFFER-ID";
var paymentAccountId = "ABC-ACCT-ID";
var takerFeeCurrencyCode = "BSQ";
var amount = "-0.05";
String[] args = new String[]{
PASSWORD_OPT,
takeoffer.name(),
"--" + OPT_OFFER_ID + "=" + offerId,
"--" + OPT_PAYMENT_ACCOUNT_ID + "=" + paymentAccountId,
"--" + OPT_FEE_CURRENCY + "=" + takerFeeCurrencyCode,
"--" + OPT_AMOUNT + "=" + amount
};
Throwable exception = assertThrows(RuntimeException.class, () ->
new TakeOfferOptionParser(args).parse());
assertEquals("invalid amount: '-0.05' is not a positive number", exception.getMessage());
}
@Test
public void testTakeOffer() {
var offerId = "ABC-OFFER-ID";
var paymentAccountId = "ABC-ACCT-ID";
var takerFeeCurrencyCode = "BSQ";
var amount = "0.05";
String[] args = new String[]{
PASSWORD_OPT,
takeoffer.name(),
"--" + OPT_OFFER_ID + "=" + offerId,
"--" + OPT_PAYMENT_ACCOUNT_ID + "=" + paymentAccountId,
"--" + OPT_FEE_CURRENCY + "=" + takerFeeCurrencyCode,
"--" + OPT_AMOUNT + "=" + amount
};
var parser = new TakeOfferOptionParser(args).parse();
assertEquals(offerId, parser.getOfferId());
assertEquals(paymentAccountId, parser.getPaymentAccountId());
assertEquals(takerFeeCurrencyCode, parser.getTakerFeeCurrencyCode());
assertEquals(amount, parser.getAmount());
}
}