diff --git a/cli/src/main/java/bisq/cli/opts/TakeBsqSwapOfferOptionParser.java b/cli/src/main/java/bisq/cli/opts/TakeBsqSwapOfferOptionParser.java index e3301b88b3..be9df70ecc 100644 --- a/cli/src/main/java/bisq/cli/opts/TakeBsqSwapOfferOptionParser.java +++ b/cli/src/main/java/bisq/cli/opts/TakeBsqSwapOfferOptionParser.java @@ -31,6 +31,14 @@ public class TakeBsqSwapOfferOptionParser extends OfferIdOptionParser implements .withRequiredArg() .defaultsTo("0"); + final OptionSpec paymentAccountIdOpt = parser.accepts(OPT_PAYMENT_ACCOUNT_ID, "not used when taking bsq swaps") + .withRequiredArg() + .defaultsTo("invalid param"); + + final OptionSpec takerFeeCurrencyCodeOpt = parser.accepts(OPT_FEE_CURRENCY, "not used when taking bsq swaps") + .withOptionalArg() + .defaultsTo("invalid param"); + public TakeBsqSwapOfferOptionParser(String[] args) { super(args, true); } @@ -40,6 +48,16 @@ public class TakeBsqSwapOfferOptionParser extends OfferIdOptionParser implements // Super class will short-circuit parsing if help option is present. + if (options.has(paymentAccountIdOpt)) { + throw new IllegalArgumentException("the " + OPT_PAYMENT_ACCOUNT_ID + + " param is not used for swaps; the internal default swap account is always used"); + } + + if (options.has(takerFeeCurrencyCodeOpt)) { + throw new IllegalArgumentException("the " + OPT_FEE_CURRENCY + + " param is not used for swaps; fees are always paid in bsq"); + } + if (options.has(amountOpt)) { if (options.valueOf(amountOpt).isEmpty()) throw new IllegalArgumentException("no intended btc trade amount specified"); diff --git a/cli/src/test/java/bisq/cli/opts/OptionParsersTest.java b/cli/src/test/java/bisq/cli/opts/OptionParsersTest.java index 04c479889d..a026f2df73 100644 --- a/cli/src/test/java/bisq/cli/opts/OptionParsersTest.java +++ b/cli/src/test/java/bisq/cli/opts/OptionParsersTest.java @@ -3,7 +3,6 @@ package bisq.cli.opts; import org.junit.jupiter.api.Test; 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; @@ -444,4 +443,54 @@ public class OptionParsersTest { assertEquals(takerFeeCurrencyCode, parser.getTakerFeeCurrencyCode()); assertEquals(amount, parser.getAmount()); } + + @Test + public void testTakeBsqSwapOfferWithInvalidFeeCurrencyParam() { + var offerId = "ABC-OFFER-ID"; + var takerFeeCurrencyCode = "BSQ"; + var amount = "0.05"; + String[] args = new String[]{ + PASSWORD_OPT, + takeoffer.name(), + "--" + OPT_OFFER_ID + "=" + offerId, + "--" + OPT_FEE_CURRENCY + "=" + takerFeeCurrencyCode, + "--" + OPT_AMOUNT + "=" + amount + }; + Throwable exception = assertThrows(RuntimeException.class, () -> + new TakeBsqSwapOfferOptionParser(args).parse()); + assertEquals("the fee-currency param is not used for swaps; fees are always paid in bsq", exception.getMessage()); + } + + @Test + public void testTakeBsqSwapOfferWithInvalidPaymentAccountIdParam() { + var offerId = "ABC-OFFER-ID"; + var paymentAccountId = "ABC-ACCT-ID"; + var amount = "0.05"; + String[] args = new String[]{ + PASSWORD_OPT, + takeoffer.name(), + "--" + OPT_OFFER_ID + "=" + offerId, + "--" + OPT_PAYMENT_ACCOUNT_ID + "=" + paymentAccountId, + "--" + OPT_AMOUNT + "=" + amount + }; + Throwable exception = assertThrows(RuntimeException.class, () -> + new TakeBsqSwapOfferOptionParser(args).parse()); + assertEquals("the payment-account-id param is not used for swaps; the internal default swap account is always used", + exception.getMessage()); + } + + @Test + public void testTakeBsqSwapOffer() { + var offerId = "ABC-OFFER-ID"; + var amount = "0.05"; + String[] args = new String[]{ + PASSWORD_OPT, + takeoffer.name(), + "--" + OPT_OFFER_ID + "=" + offerId, + "--" + OPT_AMOUNT + "=" + amount + }; + var parser = new TakeBsqSwapOfferOptionParser(args).parse(); + assertEquals(offerId, parser.getOfferId()); + assertEquals(amount, parser.getAmount()); + } } diff --git a/core/src/main/java/bisq/core/api/model/BsqSwapTradeInfo.java b/core/src/main/java/bisq/core/api/model/BsqSwapTradeInfo.java index 6780d9e289..70f5835de3 100644 --- a/core/src/main/java/bisq/core/api/model/BsqSwapTradeInfo.java +++ b/core/src/main/java/bisq/core/api/model/BsqSwapTradeInfo.java @@ -25,9 +25,6 @@ import bisq.common.Payload; import lombok.EqualsAndHashCode; import lombok.Getter; -import static bisq.core.offer.OfferDirection.BUY; -import static bisq.core.offer.OfferDirection.SELL; - @EqualsAndHashCode @Getter public class BsqSwapTradeInfo implements Payload { @@ -73,20 +70,12 @@ public class BsqSwapTradeInfo implements Payload { var makerBtcAddress = wasMyOffer ? protocolModel.getBtcAddress() : swapPeer.getBtcAddress(); var takerBsqAddress = wasMyOffer ? swapPeer.getBsqAddress() : protocolModel.getBsqAddress(); var takerBtcAddress = wasMyOffer ? swapPeer.getBtcAddress() : protocolModel.getBtcAddress(); - // A BSQ Swap trade fee is paid in full by the BTC buyer (selling BSQ). - // The transferred BSQ (payout) is reduced by the fee of the peer. - var makerTradeFee = wasMyOffer && trade.getOffer().getDirection().equals(BUY) - ? trade.getMakerFeeAsLong() - : 0L; - var takerTradeFee = !wasMyOffer && trade.getOffer().getDirection().equals(SELL) - ? trade.getTakerFeeAsLong() - : 0L; return new BsqSwapTradeInfoBuilder() .withTxId(trade.getTxId()) .withBsqTradeAmount(trade.getBsqTradeAmount()) .withBtcTradeAmount(trade.getAmountAsLong()) - .withBsqMakerTradeFee(makerTradeFee) - .withBsqTakerTradeFee(takerTradeFee) + .withBsqMakerTradeFee(trade.getMakerFeeAsLong()) + .withBsqTakerTradeFee(trade.getTakerFeeAsLong()) .withTxFeePerVbyte(trade.getTxFeePerVbyte()) .withMakerBsqAddress(makerBsqAddress) .withMakerBtcAddress(makerBtcAddress) diff --git a/core/src/main/resources/help/takeoffer-help.txt b/core/src/main/resources/help/takeoffer-help.txt index 1ad5a2ff9a..35893ac173 100644 --- a/core/src/main/resources/help/takeoffer-help.txt +++ b/core/src/main/resources/help/takeoffer-help.txt @@ -6,21 +6,28 @@ takeoffer - take an offer to buy or sell BTC SYNOPSIS -------- -takeoffer +takeoffer (Bisq v1 Protocol) --offer-id= --payment-account= [--fee-currency=] [--amount== amount <= offer.btc-amount>] +takeoffer (BSQ Swap) + --offer-id= + [--amount== amount <= offer.btc-amount>] + DESCRIPTION ----------- Take an existing offer. There are currently two types offers and trade protocols. BSQ swap offers - The takeoffer command only requires an offer-id parameter, and sufficient BSQ and BTC - to cover the trade amount and the taker fee. The amount parameter is optional. - The trade (swap) will be executed immediately after being successfully taken. + The takeoffer command only requires an offer-id parameter, and sufficient BSQ and/or BTC + to cover the trade amount and the taker fee. + The amount parameter is optional. + The payment-account parameter is invalid; BSQ Swap transactions use the default BsqSwapAccount. + The fee-currency parameter is invalid; BSQ is always used to pay BSQ swap trade fees. + The swap will be executed immediately after being successfully taken. Version 1 protocol fiat and BSQ offers @@ -33,11 +40,15 @@ OPTIONS The ID of the buy or sell offer to take. --payment-account - The ID of the fiat payment account used to send or receive funds during the trade. + The ID of the fiat payment account used to send or receive funds during the Bisq v1 protocol trade. The payment account's payment method must match that of the offer. + This parameter is not valid for taking BSQ Swaps, due to swaps' different transaction structure, + where the default BsqSwapAccount is used. --fee-currency - The wallet currency used to pay the Bisq trade taker fee (BSQ|BTC). Default is BTC + The wallet currency used to pay a Bisq v1 protocol trade's taker fee (BSQ|BTC). Default is BTC. + This parameter is not valid for taking BSQ Swaps, due to swaps' different transaction structure, + where BSQ is always used to BSQ swap trade fees. --amount The trade's intended btc amount. The amount must be within the offer's min-amount and (max) amount range. @@ -56,5 +67,5 @@ To take an offer with ID 83e8b2e2-51b6-4f39-a748-3ebd29c22aea and setting the trade amount = the offer's min-amount (0.025 BTC): $ ./bisq-cli --password=xyz --port=9998 takeoffer --offer-id=83e8b2e2-51b6-4f39-a748-3ebd29c22aea \ --payment-account=fe20cdbd-22be-4b8a-a4b6-d2608ff09d6e \ - -fee-currency=bsq \ + --fee-currency=bsq \ --amount=0.025 diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 1246b9fd5a..708168654f 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -514,8 +514,14 @@ service Trades { message TakeOfferRequest { string offer_id = 1; // The unique identifier of the offer being taken. - string payment_account_id = 2; // The unique identifier of the payment account used to take offer. - string taker_fee_currency_code = 3; // The code of the currency (BSQ or BTC) used to pay the taker's Bisq trade fee. + // The unique identifier of the payment account used to take a Bisq v1 protocol offer. + // This payment_account_id request param is not used when taking a BSQ Swap offer; + // all BSQ Swap transactions use the daemon's default BsqSwapAccount. + string payment_account_id = 2; + // The code of the currency (BSQ or BTC) used to pay the taker's Bisq v1 protocol trade fee. + // This taker_fee_currency_code request param is not used when taking a BSQ Swap offer; + // all BSQ Swap trade fees are paid in BSQ. + string taker_fee_currency_code = 3; // The trade's intended BTC amount in satoshis. Ten million satoshis is represented as 10000000. // If set, the takeoffer amount value must be >= offer.min_amount and <= offer.amount. // If not set (0 default), the taken offer's (max) amount becomes the intended trade amount.