From a3631a022f477cd2e9a00134be978c75a0ce3ec4 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Mon, 26 Oct 2020 20:44:39 -0300 Subject: [PATCH 01/20] Implement api methods 'keepfunds', 'withdrawfunds' The CoreTradesService was refactored to work for newly added api methods: - keepfunds -- close trade, keep funds in bisq wallet - withdrawfunds -- close trade, withdraw funds to external btc wallet A getKey accessor was added to CoreWalletsService (needed by withdrawfunds impl). --- .../java/bisq/core/api/CoreTradesService.java | 120 ++++++++++++++++-- .../bisq/core/api/CoreWalletsService.java | 6 + 2 files changed, 118 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/bisq/core/api/CoreTradesService.java b/core/src/main/java/bisq/core/api/CoreTradesService.java index 88ab0128cd2..1b58334466b 100644 --- a/core/src/main/java/bisq/core/api/CoreTradesService.java +++ b/core/src/main/java/bisq/core/api/CoreTradesService.java @@ -17,36 +17,57 @@ package bisq.core.api; +import bisq.core.btc.model.AddressEntry; +import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; import bisq.core.offer.takeoffer.TakeOfferModel; import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.trade.TradeUtil; +import bisq.core.trade.closed.ClosedTradableManager; import bisq.core.trade.protocol.BuyerProtocol; import bisq.core.trade.protocol.SellerProtocol; import bisq.core.user.User; +import bisq.core.util.validation.BtcAddressValidator; + +import org.bitcoinj.core.Coin; import javax.inject.Inject; +import java.util.Optional; import java.util.function.Consumer; import lombok.extern.slf4j.Slf4j; +import static bisq.core.btc.model.AddressEntry.Context.TRADE_PAYOUT; import static java.lang.String.format; @Slf4j class CoreTradesService { + // Dependencies on core api services in this package must be kept to an absolute + // minimum, but some trading functions require an unlocked wallet's key, so an + // exception is made in this case. + private final CoreWalletsService coreWalletsService; + + private final BtcWalletService btcWalletService; + private final ClosedTradableManager closedTradableManager; private final TakeOfferModel takeOfferModel; private final TradeManager tradeManager; private final TradeUtil tradeUtil; private final User user; @Inject - public CoreTradesService(TakeOfferModel takeOfferModel, + public CoreTradesService(CoreWalletsService coreWalletsService, + BtcWalletService btcWalletService, + ClosedTradableManager closedTradableManager, + TakeOfferModel takeOfferModel, TradeManager tradeManager, TradeUtil tradeUtil, User user) { + this.coreWalletsService = coreWalletsService; + this.btcWalletService = btcWalletService; + this.closedTradableManager = closedTradableManager; this.takeOfferModel = takeOfferModel; this.tradeManager = tradeManager; this.tradeUtil = tradeUtil; @@ -116,14 +137,50 @@ void confirmPaymentReceived(String tradeId) { } } - @SuppressWarnings("unused") void keepFunds(String tradeId) { - log.info("TODO"); + verifyTradeIsNotClosed(tradeId); + var trade = getOpenTrade(tradeId).orElseThrow(() -> + new IllegalArgumentException(format("trade with id '%s' not found", tradeId))); + log.info("Keeping funds received from trade {}", tradeId); + tradeManager.onTradeCompleted(trade); } - @SuppressWarnings("unused") - void withdrawFunds(String tradeId, String address) { - log.info("TODO"); + void withdrawFunds(String tradeId, String toAddress) { + // An encrypted wallet must be unlocked for this operation. + verifyTradeIsNotClosed(tradeId); + var trade = getOpenTrade(tradeId).orElseThrow(() -> + new IllegalArgumentException(format("trade with id '%s' not found", tradeId))); + + verifyIsValidBTCAddress(toAddress); + + var fromAddressEntry = btcWalletService.getOrCreateAddressEntry(trade.getId(), TRADE_PAYOUT); + verifyFundsNotWithdrawn(fromAddressEntry); + + var amount = trade.getPayoutAmount(); + var fee = getEstimatedTxFee(fromAddressEntry.getAddressString(), toAddress, amount); + var receiverAmount = amount.subtract(fee); + + log.info(format("Withdrawing funds received from trade %s:" + + "%n From %s%n To %s%n Amt %s%n Tx Fee %s%n Receiver Amt %s", + tradeId, + fromAddressEntry.getAddressString(), + toAddress, + amount.toFriendlyString(), + fee.toFriendlyString(), + receiverAmount.toFriendlyString())); + + tradeManager.onWithdrawRequest( + toAddress, + amount, + fee, + coreWalletsService.getKey(), + trade, + () -> { + }, + (errorMessage, throwable) -> { + log.error(errorMessage, throwable); + throw new IllegalStateException(errorMessage, throwable); + }); } String getTradeRole(String tradeId) { @@ -131,11 +188,58 @@ String getTradeRole(String tradeId) { } Trade getTrade(String tradeId) { - return tradeManager.getTradeById(tradeId).orElseThrow(() -> - new IllegalArgumentException(format("trade with id '%s' not found", tradeId))); + return getOpenTrade(tradeId).orElseGet(() -> + getClosedTrade(tradeId).orElseThrow(() -> + new IllegalArgumentException(format("trade with id '%s' not found", tradeId)) + )); + } + + private Optional getOpenTrade(String tradeId) { + return tradeManager.getTradeById(tradeId); + } + + private Optional getClosedTrade(String tradeId) { + return closedTradableManager.getTradableById(tradeId).map(value -> (Trade) value); } private boolean isFollowingBuyerProtocol(Trade trade) { return tradeManager.getTradeProtocol(trade) instanceof BuyerProtocol; } + + private Coin getEstimatedTxFee(String fromAddress, String toAddress, Coin amount) { + // TODO This and identical logic should be refactored into TradeUtil. + try { + return btcWalletService.getFeeEstimationTransaction(fromAddress, + toAddress, + amount, + TRADE_PAYOUT).getFee(); + } catch (Exception ex) { + log.error("", ex); + throw new IllegalStateException(format("could not estimate tx fee: %s", ex.getMessage())); + } + } + + // Throws a RuntimeException trade is already closed. + private void verifyTradeIsNotClosed(String tradeId) { + if (getClosedTrade(tradeId).isPresent()) + throw new IllegalArgumentException(format("trade '%s' is already closed", tradeId)); + } + + // Throws a RuntimeException if address is not valid. + private void verifyIsValidBTCAddress(String address) { + try { + new BtcAddressValidator().validate(address); + } catch (Throwable t) { + log.error("", t); + throw new IllegalArgumentException(format("'%s' is not a valid btc address", address)); + } + } + + // Throws a RuntimeException if address has a zero balance. + private void verifyFundsNotWithdrawn(AddressEntry fromAddressEntry) { + Coin fromAddressBalance = btcWalletService.getBalanceForAddress(fromAddressEntry.getAddress()); + if (fromAddressBalance.isZero()) + throw new IllegalStateException(format("funds already withdrawn from address '%s'", + fromAddressEntry.getAddressString())); + } } diff --git a/core/src/main/java/bisq/core/api/CoreWalletsService.java b/core/src/main/java/bisq/core/api/CoreWalletsService.java index 0f1e1db0844..29394aad8ac 100644 --- a/core/src/main/java/bisq/core/api/CoreWalletsService.java +++ b/core/src/main/java/bisq/core/api/CoreWalletsService.java @@ -71,6 +71,12 @@ public CoreWalletsService(Balances balances, this.btcWalletService = btcWalletService; } + @Nullable + KeyParameter getKey() { + verifyEncryptedWalletIsUnlocked(); + return tempAesKey; + } + long getAvailableBalance() { verifyWalletsAreAvailable(); verifyEncryptedWalletIsUnlocked(); From f1db254073577ac656a0bbd59cdc6246502d4bfa Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Tue, 27 Oct 2020 13:01:33 -0300 Subject: [PATCH 02/20] Make formatSatoshis visible for testing --- cli/src/main/java/bisq/cli/CurrencyFormat.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cli/src/main/java/bisq/cli/CurrencyFormat.java b/cli/src/main/java/bisq/cli/CurrencyFormat.java index 798af169d40..e4d8f89c6c7 100644 --- a/cli/src/main/java/bisq/cli/CurrencyFormat.java +++ b/cli/src/main/java/bisq/cli/CurrencyFormat.java @@ -17,6 +17,8 @@ package bisq.cli; +import com.google.common.annotations.VisibleForTesting; + import java.text.DecimalFormat; import java.text.NumberFormat; @@ -27,15 +29,17 @@ import static java.lang.String.format; -class CurrencyFormat { +@VisibleForTesting +public class CurrencyFormat { private static final NumberFormat NUMBER_FORMAT = NumberFormat.getInstance(Locale.US); static final BigDecimal SATOSHI_DIVISOR = new BigDecimal(100000000); static final DecimalFormat BTC_FORMAT = new DecimalFormat("###,##0.00000000"); + @VisibleForTesting @SuppressWarnings("BigDecimalMethodWithoutRoundingCalled") - static String formatSatoshis(long sats) { + public static String formatSatoshis(long sats) { return BTC_FORMAT.format(BigDecimal.valueOf(sats).divide(SATOSHI_DIVISOR)); } From b8ae566b69578405cc87b8c08c362c98abb3ac99 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Tue, 27 Oct 2020 13:03:48 -0300 Subject: [PATCH 03/20] Add method for printing current jupiter test name --- apitest/src/test/java/bisq/apitest/ApiTestCase.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apitest/src/test/java/bisq/apitest/ApiTestCase.java b/apitest/src/test/java/bisq/apitest/ApiTestCase.java index 854ce4c59bc..7f84772f543 100644 --- a/apitest/src/test/java/bisq/apitest/ApiTestCase.java +++ b/apitest/src/test/java/bisq/apitest/ApiTestCase.java @@ -26,6 +26,8 @@ import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; +import org.junit.jupiter.api.TestInfo; + import static java.util.Arrays.stream; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -117,4 +119,10 @@ protected static void sleep(long ms) { // empty } } + + protected final String testName(TestInfo testInfo) { + return testInfo.getTestMethod().isPresent() + ? testInfo.getTestMethod().get().getName() + : "unknown test name"; + } } From 1e25be5bdc40073921de795191b8f7327f494e5e Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Tue, 27 Oct 2020 13:04:53 -0300 Subject: [PATCH 04/20] Test trade closing api methods 'keepfunds' withdrawfunds' Some refactoring of the api test case hierarchy is included in this commit. --- .../java/bisq/apitest/method/MethodTest.java | 45 ++++++++ .../method/offer/AbstractOfferTest.java | 3 - .../method/trade/AbstractTradeTest.java | 107 +++++++++++++++++- .../method/trade/TakeBuyBTCOfferTest.java | 93 ++++++++------- .../method/trade/TakeSellBTCOfferTest.java | 103 ++++++++++------- 5 files changed, 261 insertions(+), 90 deletions(-) diff --git a/apitest/src/test/java/bisq/apitest/method/MethodTest.java b/apitest/src/test/java/bisq/apitest/method/MethodTest.java index 6a175d118ce..64f6710c7e2 100644 --- a/apitest/src/test/java/bisq/apitest/method/MethodTest.java +++ b/apitest/src/test/java/bisq/apitest/method/MethodTest.java @@ -25,6 +25,7 @@ import bisq.proto.grpc.GetOfferRequest; import bisq.proto.grpc.GetPaymentAccountsRequest; import bisq.proto.grpc.GetTradeRequest; +import bisq.proto.grpc.KeepFundsRequest; import bisq.proto.grpc.LockWalletRequest; import bisq.proto.grpc.MarketPriceRequest; import bisq.proto.grpc.OfferInfo; @@ -34,11 +35,16 @@ import bisq.proto.grpc.TakeOfferRequest; import bisq.proto.grpc.TradeInfo; import bisq.proto.grpc.UnlockWalletRequest; +import bisq.proto.grpc.WithdrawFundsRequest; import protobuf.PaymentAccount; import java.util.stream.Collectors; +import org.junit.jupiter.api.BeforeEach; + +import static bisq.apitest.config.BisqAppConfig.alicedaemon; +import static bisq.apitest.config.BisqAppConfig.bobdaemon; import static bisq.common.app.DevEnv.DEV_PRIVILEGE_PRIV_KEY; import static bisq.core.payment.payload.PaymentMethod.PERFECT_MONEY; import static java.util.Comparator.comparing; @@ -48,6 +54,7 @@ import bisq.apitest.ApiTestCase; import bisq.apitest.config.BisqAppConfig; +import bisq.cli.GrpcStubs; public class MethodTest extends ApiTestCase { @@ -55,6 +62,18 @@ public class MethodTest extends ApiTestCase { protected static final String MEDIATOR = "mediator"; protected static final String REFUND_AGENT = "refundagent"; + protected static GrpcStubs aliceStubs; + protected static GrpcStubs bobStubs; + + protected PaymentAccount alicesDummyAcct; + protected PaymentAccount bobsDummyAcct; + + @BeforeEach + public void initDummyPaymentAccounts() { + alicesDummyAcct = getDefaultPerfectDummyPaymentAccount(alicedaemon); + bobsDummyAcct = getDefaultPerfectDummyPaymentAccount(bobdaemon); + } + // Convenience methods for building gRPC request objects protected final GetBalanceRequest createBalanceRequest() { @@ -109,6 +128,19 @@ protected final ConfirmPaymentReceivedRequest createConfirmPaymentReceivedReques return ConfirmPaymentReceivedRequest.newBuilder().setTradeId(tradeId).build(); } + protected final KeepFundsRequest createKeepFundsRequest(String tradeId) { + return KeepFundsRequest.newBuilder() + .setTradeId(tradeId) + .build(); + } + + protected final WithdrawFundsRequest createWithdrawFundsRequest(String tradeId, String address) { + return WithdrawFundsRequest.newBuilder() + .setTradeId(tradeId) + .setAddress(address) + .build(); + } + // Convenience methods for calling frequently used & thoroughly tested gRPC services. protected final long getBalance(BisqAppConfig bisqAppConfig) { @@ -175,16 +207,29 @@ protected final TradeInfo getTrade(BisqAppConfig bisqAppConfig, String tradeId) return grpcStubs(bisqAppConfig).tradesService.getTrade(req).getTrade(); } + @SuppressWarnings("ResultOfMethodCallIgnored") protected final void confirmPaymentStarted(BisqAppConfig bisqAppConfig, String tradeId) { var req = createConfirmPaymentStartedRequest(tradeId); grpcStubs(bisqAppConfig).tradesService.confirmPaymentStarted(req); } + @SuppressWarnings("ResultOfMethodCallIgnored") protected final void confirmPaymentReceived(BisqAppConfig bisqAppConfig, String tradeId) { var req = createConfirmPaymentReceivedRequest(tradeId); grpcStubs(bisqAppConfig).tradesService.confirmPaymentReceived(req); } + @SuppressWarnings("ResultOfMethodCallIgnored") + protected final void keepFunds(BisqAppConfig bisqAppConfig, String tradeId) { + var req = createKeepFundsRequest(tradeId); + grpcStubs(bisqAppConfig).tradesService.keepFunds(req); + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + protected final void withdrawFunds(BisqAppConfig bisqAppConfig, String tradeId, String address) { + var req = createWithdrawFundsRequest(tradeId, address); + grpcStubs(bisqAppConfig).tradesService.withdrawFunds(req); + } // Static conveniences for test methods and test case fixture setups. protected static RegisterDisputeAgentRequest createRegisterDisputeAgentRequest(String disputeAgentType) { diff --git a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java index 979d7a33e6a..bc233721d0f 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java @@ -59,9 +59,6 @@ @Slf4j public abstract class AbstractOfferTest extends MethodTest { - protected static GrpcStubs aliceStubs; - protected static GrpcStubs bobStubs; - @BeforeAll public static void setUp() { startSupportingApps(); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java index 094007abd40..7e4c22e9689 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java @@ -4,6 +4,12 @@ import bisq.proto.grpc.TradeInfo; +import org.slf4j.Logger; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInfo; + +import static bisq.cli.TradeFormat.format; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -13,19 +19,110 @@ public class AbstractTradeTest extends AbstractOfferTest { + // A test fixture encapsulating expected trade protocol status. + // ExpectedProtocolStatus.init should be called before any @Test begins. + protected static final ExpectedProtocolStatus EXPECTED_PROTOCOL_STATUS = new ExpectedProtocolStatus(); + + // A Trade ID cache for use in @Test sequences. + protected static String tradeId; + + @BeforeAll + public static void clearExpectedPaymentStatusFlags() { + EXPECTED_PROTOCOL_STATUS.init(); + } + protected final TradeInfo takeAlicesOffer(String offerId, String paymentAccountId) { return bobStubs.tradesService.takeOffer(createTakeOfferRequest(offerId, paymentAccountId)).getTrade(); } + @SuppressWarnings("unused") protected final TradeInfo takeBobsOffer(String offerId, String paymentAccountId) { return aliceStubs.tradesService.takeOffer(createTakeOfferRequest(offerId, paymentAccountId)).getTrade(); } - protected final void verifyExpectedTradeStateAndPhase(TradeInfo trade, - Trade.State expectedState, - Trade.Phase expectedPhase) { + protected final void verifyExpectedProtocolStatus(TradeInfo trade) { assertNotNull(trade); - assertEquals(expectedState.name(), trade.getState()); - assertEquals(expectedPhase.name(), trade.getPhase()); + assertEquals(EXPECTED_PROTOCOL_STATUS.state.name(), trade.getState()); + assertEquals(EXPECTED_PROTOCOL_STATUS.phase.name(), trade.getPhase()); + assertEquals(EXPECTED_PROTOCOL_STATUS.isDepositPublished, trade.getIsDepositPublished()); + assertEquals(EXPECTED_PROTOCOL_STATUS.isDepositConfirmed, trade.getIsDepositConfirmed()); + assertEquals(EXPECTED_PROTOCOL_STATUS.isFiatSent, trade.getIsFiatSent()); + assertEquals(EXPECTED_PROTOCOL_STATUS.isFiatReceived, trade.getIsFiatReceived()); + assertEquals(EXPECTED_PROTOCOL_STATUS.isPayoutPublished, trade.getIsPayoutPublished()); + assertEquals(EXPECTED_PROTOCOL_STATUS.isWithdrawn, trade.getIsWithdrawn()); + } + + protected final void logTrade(Logger log, + TestInfo testInfo, + String description, + TradeInfo trade) { + log.info(String.format("%s %s%n%s", + testName(testInfo), + description.toUpperCase(), + format(trade))); + } + + @SuppressWarnings("UnusedReturnValue") + static class ExpectedProtocolStatus { + Trade.State state; + Trade.Phase phase; + boolean isDepositPublished; + boolean isDepositConfirmed; + boolean isFiatSent; + boolean isFiatReceived; + boolean isPayoutPublished; + boolean isWithdrawn; + + ExpectedProtocolStatus setState(Trade.State state) { + this.state = state; + return this; + } + + ExpectedProtocolStatus setPhase(Trade.Phase phase) { + this.phase = phase; + return this; + } + + ExpectedProtocolStatus setDepositPublished(boolean depositPublished) { + isDepositPublished = depositPublished; + return this; + } + + ExpectedProtocolStatus setDepositConfirmed(boolean depositConfirmed) { + isDepositConfirmed = depositConfirmed; + return this; + } + + ExpectedProtocolStatus setFiatSent(boolean fiatSent) { + isFiatSent = fiatSent; + return this; + } + + ExpectedProtocolStatus setFiatReceived(boolean fiatReceived) { + isFiatReceived = fiatReceived; + return this; + } + + ExpectedProtocolStatus setPayoutPublished(boolean payoutPublished) { + isPayoutPublished = payoutPublished; + return this; + } + + ExpectedProtocolStatus setWithdrawn(boolean withdrawn) { + isWithdrawn = withdrawn; + return this; + } + + @SuppressWarnings("unused") + void init() { + state = null; + phase = null; + isDepositPublished = false; + isDepositConfirmed = false; + isFiatSent = false; + isFiatReceived = false; + isPayoutPublished = false; + isWithdrawn = false; + } } } diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java index 4aba67fc715..bb7d8ea8239 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java @@ -17,30 +17,24 @@ package bisq.apitest.method.trade; -import protobuf.PaymentAccount; - import io.grpc.StatusRuntimeException; import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestMethodOrder; import static bisq.apitest.config.BisqAppConfig.alicedaemon; import static bisq.apitest.config.BisqAppConfig.bobdaemon; -import static bisq.cli.TradeFormat.format; +import static bisq.cli.CurrencyFormat.formatSatoshis; import static bisq.core.trade.Trade.Phase.DEPOSIT_CONFIRMED; import static bisq.core.trade.Trade.Phase.DEPOSIT_PUBLISHED; import static bisq.core.trade.Trade.Phase.FIAT_SENT; import static bisq.core.trade.Trade.Phase.PAYOUT_PUBLISHED; -import static bisq.core.trade.Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG; -import static bisq.core.trade.Trade.State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN; -import static bisq.core.trade.Trade.State.SELLER_PUBLISHED_DEPOSIT_TX; -import static bisq.core.trade.Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG; -import static java.lang.System.out; +import static bisq.core.trade.Trade.State.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.fail; @@ -53,22 +47,14 @@ public class TakeBuyBTCOfferTest extends AbstractTradeTest { // Alice is buyer, Bob is seller. - private static String tradeId; - - private PaymentAccount alicesAccount; - private PaymentAccount bobsAccount; - - @BeforeEach - public void init() { - alicesAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon); - bobsAccount = getDefaultPerfectDummyPaymentAccount(bobdaemon); - } - @Test @Order(1) - public void testTakeAlicesBuyOffer() { + public void testTakeAlicesBuyOffer(final TestInfo testInfo) { try { - var alicesOffer = createAliceOffer(alicesAccount, "buy", "usd", 12500000); + var alicesOffer = createAliceOffer(alicesDummyAcct, + "buy", + "usd", + 12500000); var offerId = alicesOffer.getId(); // Wait for Alice's AddToOfferBook task. @@ -76,7 +62,7 @@ public void testTakeAlicesBuyOffer() { sleep(3000); assertEquals(1, getOpenOffersCount(aliceStubs, "buy", "usd")); - var trade = takeAlicesOffer(offerId, bobsAccount.getId()); + var trade = takeAlicesOffer(offerId, bobsDummyAcct.getId()); assertNotNull(trade); assertEquals(offerId, trade.getTradeId()); // Cache the trade id for the other tests. @@ -86,13 +72,19 @@ public void testTakeAlicesBuyOffer() { assertEquals(0, getOpenOffersCount(aliceStubs, "buy", "usd")); trade = getTrade(bobdaemon, trade.getTradeId()); - verifyExpectedTradeStateAndPhase(trade, SELLER_PUBLISHED_DEPOSIT_TX, DEPOSIT_PUBLISHED); - out.println(format(trade)); + EXPECTED_PROTOCOL_STATUS.setState(SELLER_PUBLISHED_DEPOSIT_TX) + .setPhase(DEPOSIT_PUBLISHED) + .setDepositPublished(true); + verifyExpectedProtocolStatus(trade); + logTrade(log, testInfo, "Bob's view after taking offer and sending deposit", trade); genBtcBlocksThenWait(1, 2250); trade = getTrade(bobdaemon, trade.getTradeId()); - verifyExpectedTradeStateAndPhase(trade, DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN, DEPOSIT_CONFIRMED); - out.println(format(trade)); + EXPECTED_PROTOCOL_STATUS.setState(DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN) + .setPhase(DEPOSIT_CONFIRMED) + .setDepositConfirmed(true); + verifyExpectedProtocolStatus(trade); + logTrade(log, testInfo, "Bob's view after deposit is confirmed", trade); } catch (StatusRuntimeException e) { fail(e); } @@ -100,18 +92,19 @@ public void testTakeAlicesBuyOffer() { @Test @Order(2) - public void testAlicesConfirmPaymentStarted() { + public void testAlicesConfirmPaymentStarted(final TestInfo testInfo) { try { var trade = getTrade(alicedaemon, tradeId); - assertNotNull(trade); - confirmPaymentStarted(alicedaemon, trade.getTradeId()); sleep(3000); trade = getTrade(alicedaemon, tradeId); assertEquals(OFFER_FEE_PAID.name(), trade.getOffer().getState()); - verifyExpectedTradeStateAndPhase(trade, BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG, FIAT_SENT); - out.println(format(trade)); + EXPECTED_PROTOCOL_STATUS.setState(BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG) + .setPhase(FIAT_SENT) + .setFiatSent(true); + verifyExpectedProtocolStatus(trade); + logTrade(log, testInfo, "Alice's view after confirming fiat payment sent", trade); } catch (StatusRuntimeException e) { fail(e); } @@ -119,17 +112,41 @@ public void testAlicesConfirmPaymentStarted() { @Test @Order(3) - public void testBobsConfirmPaymentReceived() { + public void testBobsConfirmPaymentReceived(final TestInfo testInfo) { var trade = getTrade(bobdaemon, tradeId); - assertNotNull(trade); - confirmPaymentReceived(bobdaemon, trade.getTradeId()); sleep(3000); trade = getTrade(bobdaemon, tradeId); - // TODO is this a bug? Why is offer.state == available? + // Note: offer.state == available assertEquals(AVAILABLE.name(), trade.getOffer().getState()); - verifyExpectedTradeStateAndPhase(trade, SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG, PAYOUT_PUBLISHED); - out.println(format(trade)); + EXPECTED_PROTOCOL_STATUS.setState(SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG) + .setPhase(PAYOUT_PUBLISHED) + .setPayoutPublished(true) + .setFiatReceived(true); + verifyExpectedProtocolStatus(trade); + logTrade(log, testInfo, "Bob's view after confirming fiat payment received", trade); + } + + @Test + @Order(4) + public void testAlicesKeepFunds(final TestInfo testInfo) { + genBtcBlocksThenWait(1, 2250); + + var trade = getTrade(alicedaemon, tradeId); + logTrade(log, testInfo, "Alice's view before keeping funds", trade); + + keepFunds(alicedaemon, tradeId); + + genBtcBlocksThenWait(1, 2250); + + trade = getTrade(alicedaemon, tradeId); + EXPECTED_PROTOCOL_STATUS.setState(BUYER_RECEIVED_PAYOUT_TX_PUBLISHED_MSG) + .setPhase(PAYOUT_PUBLISHED); + verifyExpectedProtocolStatus(trade); + logTrade(log, testInfo, "Alice's view after keeping funds", trade); + log.info("{} Alice's current available balance: {} BTC", + testName(testInfo), + formatSatoshis(getBalance(alicedaemon))); } } diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java index 658b4083231..c1786082ba8 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java @@ -17,30 +17,21 @@ package bisq.apitest.method.trade; -import protobuf.PaymentAccount; - import io.grpc.StatusRuntimeException; import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestMethodOrder; import static bisq.apitest.config.BisqAppConfig.alicedaemon; import static bisq.apitest.config.BisqAppConfig.bobdaemon; -import static bisq.cli.TradeFormat.format; -import static bisq.core.trade.Trade.Phase.DEPOSIT_CONFIRMED; -import static bisq.core.trade.Trade.Phase.DEPOSIT_PUBLISHED; -import static bisq.core.trade.Trade.Phase.FIAT_SENT; -import static bisq.core.trade.Trade.Phase.PAYOUT_PUBLISHED; -import static bisq.core.trade.Trade.State.BUYER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG; -import static bisq.core.trade.Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG; -import static bisq.core.trade.Trade.State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN; -import static bisq.core.trade.Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG; -import static java.lang.System.out; +import static bisq.cli.CurrencyFormat.formatSatoshis; +import static bisq.core.trade.Trade.Phase.*; +import static bisq.core.trade.Trade.State.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.fail; @@ -53,22 +44,14 @@ public class TakeSellBTCOfferTest extends AbstractTradeTest { // Alice is seller, Bob is buyer. - private static String tradeId; - - private PaymentAccount alicesAccount; - private PaymentAccount bobsAccount; - - @BeforeEach - public void init() { - alicesAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon); - bobsAccount = getDefaultPerfectDummyPaymentAccount(bobdaemon); - } - @Test @Order(1) - public void testTakeAlicesSellOffer() { + public void testTakeAlicesSellOffer(final TestInfo testInfo) { try { - var alicesOffer = createAliceOffer(alicesAccount, "sell", "usd", 12500000); + var alicesOffer = createAliceOffer(alicesDummyAcct, + "sell", + "usd", + 12500000); var offerId = alicesOffer.getId(); // Wait for Alice's AddToOfferBook task. @@ -77,7 +60,7 @@ public void testTakeAlicesSellOffer() { sleep(3000); assertEquals(1, getOpenOffersCount(bobStubs, "sell", "usd")); - var trade = takeAlicesOffer(offerId, bobsAccount.getId()); + var trade = takeAlicesOffer(offerId, bobsDummyAcct.getId()); assertNotNull(trade); assertEquals(offerId, trade.getTradeId()); // Cache the trade id for the other tests. @@ -87,14 +70,20 @@ public void testTakeAlicesSellOffer() { assertEquals(0, getOpenOffersCount(bobStubs, "sell", "usd")); trade = getTrade(bobdaemon, trade.getTradeId()); - verifyExpectedTradeStateAndPhase(trade, BUYER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG, DEPOSIT_PUBLISHED); - out.println(format(trade)); + EXPECTED_PROTOCOL_STATUS.setState(BUYER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) + .setPhase(DEPOSIT_PUBLISHED) + .setDepositPublished(true); + verifyExpectedProtocolStatus(trade); + + logTrade(log, testInfo, "Bob's view after taking offer and sending deposit", trade); genBtcBlocksThenWait(1, 2250); trade = getTrade(bobdaemon, trade.getTradeId()); - verifyExpectedTradeStateAndPhase(trade, DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN, DEPOSIT_CONFIRMED); - out.println(format(trade)); - + EXPECTED_PROTOCOL_STATUS.setState(DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN) + .setPhase(DEPOSIT_CONFIRMED) + .setDepositConfirmed(true); + verifyExpectedProtocolStatus(trade); + logTrade(log, testInfo, "Bob's view after deposit is confirmed", trade); } catch (StatusRuntimeException e) { fail(e); } @@ -102,20 +91,20 @@ public void testTakeAlicesSellOffer() { @Test @Order(2) - public void testBobsConfirmPaymentStarted() { + public void testBobsConfirmPaymentStarted(final TestInfo testInfo) { try { var trade = getTrade(bobdaemon, tradeId); - assertNotNull(trade); - confirmPaymentStarted(bobdaemon, trade.getTradeId()); sleep(3000); trade = getTrade(bobdaemon, tradeId); - // TODO is this a bug? Why is offer.state == available? + // Note: offer.state == available assertEquals(AVAILABLE.name(), trade.getOffer().getState()); - verifyExpectedTradeStateAndPhase(trade, BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG, FIAT_SENT); - - out.println(format(trade)); + EXPECTED_PROTOCOL_STATUS.setState(BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG) + .setPhase(FIAT_SENT) + .setFiatSent(true); + verifyExpectedProtocolStatus(trade); + logTrade(log, testInfo, "Bob's view after confirming fiat payment sent", trade); } catch (StatusRuntimeException e) { fail(e); } @@ -123,16 +112,42 @@ public void testBobsConfirmPaymentStarted() { @Test @Order(3) - public void testAlicesConfirmPaymentReceived() { + public void testAlicesConfirmPaymentReceived(final TestInfo testInfo) { var trade = getTrade(alicedaemon, tradeId); - assertNotNull(trade); - confirmPaymentReceived(alicedaemon, trade.getTradeId()); sleep(3000); trade = getTrade(alicedaemon, tradeId); assertEquals(OFFER_FEE_PAID.name(), trade.getOffer().getState()); - verifyExpectedTradeStateAndPhase(trade, SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG, PAYOUT_PUBLISHED); - out.println(format(trade)); + EXPECTED_PROTOCOL_STATUS.setState(SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG) + .setPhase(PAYOUT_PUBLISHED) + .setPayoutPublished(true) + .setFiatReceived(true); + verifyExpectedProtocolStatus(trade); + logTrade(log, testInfo, "Alice's view after confirming fiat payment received", trade); + } + + @Test + @Order(4) + public void testBobsBtcWithdrawalToExternalAddress(final TestInfo testInfo) { + genBtcBlocksThenWait(1, 2250); + + var trade = getTrade(bobdaemon, tradeId); + logTrade(log, testInfo, "Bob's view before withdrawing funds to external wallet", trade); + + String toAddress = bitcoinCli.getNewBtcAddress(); + withdrawFunds(bobdaemon, tradeId, toAddress); + + genBtcBlocksThenWait(1, 2250); + + trade = getTrade(bobdaemon, tradeId); + EXPECTED_PROTOCOL_STATUS.setState(WITHDRAW_COMPLETED) + .setPhase(WITHDRAWN) + .setWithdrawn(true); + verifyExpectedProtocolStatus(trade); + logTrade(log, testInfo, "Bob's view after withdrawing funds to external wallet", trade); + log.info("{} Bob's current available balance: {} BTC", + testName(testInfo), + formatSatoshis(getBalance(bobdaemon))); } } From 2746b276744a6c282d96170326146ed298f1df97 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Tue, 27 Oct 2020 13:47:23 -0300 Subject: [PATCH 05/20] Fix apitest dummy payment acct init bug This commit fixes non-trade tests broken by the last refactoring. --- .../java/bisq/apitest/method/MethodTest.java | 8 ++--- .../method/RegisterDisputeAgentsTest.java | 12 +++----- .../method/offer/AbstractOfferTest.java | 6 ++++ .../offer/CreateOfferUsingFixedPriceTest.java | 23 +++++++-------- ...CreateOfferUsingMarketPriceMarginTest.java | 29 ++++++++----------- .../method/offer/ValidateCreateOfferTest.java | 4 +-- .../method/trade/AbstractTradeTest.java | 7 +++++ 7 files changed, 44 insertions(+), 45 deletions(-) diff --git a/apitest/src/test/java/bisq/apitest/method/MethodTest.java b/apitest/src/test/java/bisq/apitest/method/MethodTest.java index 64f6710c7e2..cf5b74c750c 100644 --- a/apitest/src/test/java/bisq/apitest/method/MethodTest.java +++ b/apitest/src/test/java/bisq/apitest/method/MethodTest.java @@ -41,8 +41,6 @@ import java.util.stream.Collectors; -import org.junit.jupiter.api.BeforeEach; - import static bisq.apitest.config.BisqAppConfig.alicedaemon; import static bisq.apitest.config.BisqAppConfig.bobdaemon; import static bisq.common.app.DevEnv.DEV_PRIVILEGE_PRIV_KEY; @@ -68,9 +66,11 @@ public class MethodTest extends ApiTestCase { protected PaymentAccount alicesDummyAcct; protected PaymentAccount bobsDummyAcct; - @BeforeEach - public void initDummyPaymentAccounts() { + protected final void initAlicesDummyPaymentAccount() { alicesDummyAcct = getDefaultPerfectDummyPaymentAccount(alicedaemon); + } + + protected final void initBobsDummyPaymentAccount() { bobsDummyAcct = getDefaultPerfectDummyPaymentAccount(bobdaemon); } diff --git a/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java b/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java index 9c875012080..379fbc3a004 100644 --- a/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java +++ b/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java @@ -56,8 +56,7 @@ public static void setUp() { @Test @Order(1) public void testRegisterArbitratorShouldThrowException() { - var req = - createRegisterDisputeAgentRequest(ARBITRATOR); + var req = createRegisterDisputeAgentRequest(ARBITRATOR); Throwable exception = assertThrows(StatusRuntimeException.class, () -> grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req)); assertEquals("INVALID_ARGUMENT: arbitrators must be registered in a Bisq UI", @@ -67,8 +66,7 @@ public void testRegisterArbitratorShouldThrowException() { @Test @Order(2) public void testInvalidDisputeAgentTypeArgShouldThrowException() { - var req = - createRegisterDisputeAgentRequest("badagent"); + var req = createRegisterDisputeAgentRequest("badagent"); Throwable exception = assertThrows(StatusRuntimeException.class, () -> grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req)); assertEquals("INVALID_ARGUMENT: unknown dispute agent type 'badagent'", @@ -90,16 +88,14 @@ public void testInvalidRegistrationKeyArgShouldThrowException() { @Test @Order(4) public void testRegisterMediator() { - var req = - createRegisterDisputeAgentRequest(MEDIATOR); + var req = createRegisterDisputeAgentRequest(MEDIATOR); grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req); } @Test @Order(5) public void testRegisterRefundAgent() { - var req = - createRegisterDisputeAgentRequest(REFUND_AGENT); + var req = createRegisterDisputeAgentRequest(REFUND_AGENT); grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req); } diff --git a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java index bc233721d0f..a08e08d0bc3 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java @@ -36,6 +36,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind; import static bisq.apitest.config.BisqAppConfig.alicedaemon; @@ -64,6 +65,11 @@ public static void setUp() { startSupportingApps(); } + @BeforeEach + public void initDummyPaymentAccount() { + super.initAlicesDummyPaymentAccount(); + } + static void startSupportingApps() { try { // setUpScaffold(new String[]{"--supportingApps", "bitcoind,seednode,arbdaemon,alicedaemon,bobdaemon", "--enableBisqDebugging", "true"}); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java index 739faf71e96..10ca6c9e4cb 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java @@ -28,7 +28,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; -import static bisq.apitest.config.BisqAppConfig.alicedaemon; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -37,12 +36,12 @@ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class CreateOfferUsingFixedPriceTest extends AbstractOfferTest { + @Test @Order(1) public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { - var paymentAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon); var req = CreateOfferRequest.newBuilder() - .setPaymentAccountId(paymentAccount.getId()) + .setPaymentAccountId(alicesDummyAcct.getId()) .setDirection("buy") .setCurrencyCode("aud") .setAmount(10000000) @@ -61,7 +60,7 @@ public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("AUD", newOffer.getCounterCurrencyCode()); @@ -73,7 +72,7 @@ public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("AUD", newOffer.getCounterCurrencyCode()); } @@ -81,9 +80,8 @@ public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { @Test @Order(2) public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { - var paymentAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon); var req = CreateOfferRequest.newBuilder() - .setPaymentAccountId(paymentAccount.getId()) + .setPaymentAccountId(alicesDummyAcct.getId()) .setDirection("buy") .setCurrencyCode("usd") .setAmount(10000000) @@ -102,7 +100,7 @@ public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("USD", newOffer.getCounterCurrencyCode()); @@ -114,7 +112,7 @@ public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("USD", newOffer.getCounterCurrencyCode()); } @@ -122,9 +120,8 @@ public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { @Test @Order(3) public void testCreateEURBTCSellOfferUsingFixedPrice95001234() { - var paymentAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon); var req = CreateOfferRequest.newBuilder() - .setPaymentAccountId(paymentAccount.getId()) + .setPaymentAccountId(alicesDummyAcct.getId()) .setDirection("sell") .setCurrencyCode("eur") .setAmount(10000000) @@ -143,7 +140,7 @@ public void testCreateEURBTCSellOfferUsingFixedPrice95001234() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("EUR", newOffer.getCounterCurrencyCode()); @@ -155,7 +152,7 @@ public void testCreateEURBTCSellOfferUsingFixedPrice95001234() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("EUR", newOffer.getCounterCurrencyCode()); } diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java index f9d379131bb..b0c017baff0 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java @@ -31,7 +31,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; -import static bisq.apitest.config.BisqAppConfig.alicedaemon; import static bisq.common.util.MathUtils.scaleDownByPowerOf10; import static bisq.common.util.MathUtils.scaleUpByPowerOf10; import static java.lang.Math.abs; @@ -52,10 +51,9 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest { @Test @Order(1) public void testCreateUSDBTCBuyOffer5PctPriceMargin() { - var paymentAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon); double priceMarginPctInput = 5.00; var req = CreateOfferRequest.newBuilder() - .setPaymentAccountId(paymentAccount.getId()) + .setPaymentAccountId(alicesDummyAcct.getId()) .setDirection("buy") .setCurrencyCode("usd") .setAmount(10000000) @@ -73,7 +71,7 @@ public void testCreateUSDBTCBuyOffer5PctPriceMargin() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("USD", newOffer.getCounterCurrencyCode()); @@ -84,7 +82,7 @@ public void testCreateUSDBTCBuyOffer5PctPriceMargin() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("USD", newOffer.getCounterCurrencyCode()); @@ -94,10 +92,9 @@ public void testCreateUSDBTCBuyOffer5PctPriceMargin() { @Test @Order(2) public void testCreateNZDBTCBuyOfferMinus2PctPriceMargin() { - var paymentAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon); double priceMarginPctInput = -2.00; var req = CreateOfferRequest.newBuilder() - .setPaymentAccountId(paymentAccount.getId()) + .setPaymentAccountId(alicesDummyAcct.getId()) .setDirection("buy") .setCurrencyCode("nzd") .setAmount(10000000) @@ -115,7 +112,7 @@ public void testCreateNZDBTCBuyOfferMinus2PctPriceMargin() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("NZD", newOffer.getCounterCurrencyCode()); @@ -126,7 +123,7 @@ public void testCreateNZDBTCBuyOfferMinus2PctPriceMargin() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("NZD", newOffer.getCounterCurrencyCode()); @@ -136,10 +133,9 @@ public void testCreateNZDBTCBuyOfferMinus2PctPriceMargin() { @Test @Order(3) public void testCreateGBPBTCSellOfferMinus1Point5PctPriceMargin() { - var paymentAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon); double priceMarginPctInput = -1.5; var req = CreateOfferRequest.newBuilder() - .setPaymentAccountId(paymentAccount.getId()) + .setPaymentAccountId(alicesDummyAcct.getId()) .setDirection("sell") .setCurrencyCode("gbp") .setAmount(10000000) @@ -158,7 +154,7 @@ public void testCreateGBPBTCSellOfferMinus1Point5PctPriceMargin() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("GBP", newOffer.getCounterCurrencyCode()); @@ -169,7 +165,7 @@ public void testCreateGBPBTCSellOfferMinus1Point5PctPriceMargin() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("GBP", newOffer.getCounterCurrencyCode()); @@ -179,10 +175,9 @@ public void testCreateGBPBTCSellOfferMinus1Point5PctPriceMargin() { @Test @Order(4) public void testCreateBRLBTCSellOffer6Point55PctPriceMargin() { - var paymentAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon); double priceMarginPctInput = 6.55; var req = CreateOfferRequest.newBuilder() - .setPaymentAccountId(paymentAccount.getId()) + .setPaymentAccountId(alicesDummyAcct.getId()) .setDirection("sell") .setCurrencyCode("brl") .setAmount(10000000) @@ -201,7 +196,7 @@ public void testCreateBRLBTCSellOffer6Point55PctPriceMargin() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("BRL", newOffer.getCounterCurrencyCode()); @@ -212,7 +207,7 @@ public void testCreateBRLBTCSellOffer6Point55PctPriceMargin() { assertEquals(10000000, newOffer.getAmount()); assertEquals(10000000, newOffer.getMinAmount()); assertEquals(1500000, newOffer.getBuyerSecurityDeposit()); - assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId()); + assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId()); assertEquals("BTC", newOffer.getBaseCurrencyCode()); assertEquals("BRL", newOffer.getCounterCurrencyCode()); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/ValidateCreateOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/ValidateCreateOfferTest.java index 785dc97fdcb..ecf09b1e421 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/ValidateCreateOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/ValidateCreateOfferTest.java @@ -30,7 +30,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; -import static bisq.apitest.config.BisqAppConfig.alicedaemon; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -41,9 +40,8 @@ public class ValidateCreateOfferTest extends AbstractOfferTest { @Test @Order(1) public void testAmtTooLargeShouldThrowException() { - var paymentAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon); var req = CreateOfferRequest.newBuilder() - .setPaymentAccountId(paymentAccount.getId()) + .setPaymentAccountId(alicesDummyAcct.getId()) .setDirection("buy") .setCurrencyCode("usd") .setAmount(100000000000L) diff --git a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java index 7e4c22e9689..22aee1d70dd 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java @@ -7,6 +7,7 @@ import org.slf4j.Logger; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.TestInfo; import static bisq.cli.TradeFormat.format; @@ -31,6 +32,12 @@ public static void clearExpectedPaymentStatusFlags() { EXPECTED_PROTOCOL_STATUS.init(); } + @BeforeEach + public void initDummyPaymentAccounts() { + super.initAlicesDummyPaymentAccount(); + super.initBobsDummyPaymentAccount(); + } + protected final TradeInfo takeAlicesOffer(String offerId, String paymentAccountId) { return bobStubs.tradesService.takeOffer(createTakeOfferRequest(offerId, paymentAccountId)).getTrade(); } From 027a7d5cd3bfaf4afefbd92612c67356a43d6353 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Tue, 27 Oct 2020 14:54:50 -0300 Subject: [PATCH 06/20] Stub out canceloffer api method The implementation will be added to CoreOffersService in the next PR. --- cli/src/main/java/bisq/cli/CliMain.java | 17 ++++++++++++++++- core/src/main/java/bisq/core/api/CoreApi.java | 4 ++++ .../java/bisq/core/api/CoreOffersService.java | 4 ++++ .../bisq/daemon/grpc/GrpcOffersService.java | 17 +++++++++++++++++ proto/src/main/proto/grpc.proto | 9 +++++++++ 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/cli/src/main/java/bisq/cli/CliMain.java b/cli/src/main/java/bisq/cli/CliMain.java index cecaadf0d56..8639c95602f 100644 --- a/cli/src/main/java/bisq/cli/CliMain.java +++ b/cli/src/main/java/bisq/cli/CliMain.java @@ -17,6 +17,7 @@ package bisq.cli; +import bisq.proto.grpc.CancelOfferRequest; import bisq.proto.grpc.ConfirmPaymentReceivedRequest; import bisq.proto.grpc.ConfirmPaymentStartedRequest; import bisq.proto.grpc.CreateOfferRequest; @@ -74,6 +75,7 @@ public class CliMain { private enum Method { createoffer, + canceloffer, getoffer, getoffers, takeoffer, @@ -238,6 +240,18 @@ public static void run(String[] args) { out.println(formatOfferTable(singletonList(reply.getOffer()), currencyCode)); return; } + case canceloffer: { + if (nonOptionArgs.size() < 2) + throw new IllegalArgumentException("incorrect parameter count, expecting offer id"); + + var offerId = nonOptionArgs.get(1); + var request = CancelOfferRequest.newBuilder() + .setId(offerId) + .build(); + offersService.cancelOffer(request); + out.println("offer canceled and removed from offer book"); + return; + } case getoffer: { if (nonOptionArgs.size() < 2) throw new IllegalArgumentException("incorrect parameter count, expecting offer id"); @@ -246,7 +260,7 @@ public static void run(String[] args) { var request = GetOfferRequest.newBuilder() .setId(offerId) .build(); - var reply = offersService.getOffer(request); + var reply =offersService.getOffer(request); out.println(formatOfferTable(singletonList(reply.getOffer()), reply.getOffer().getCounterCurrencyCode())); return; @@ -475,6 +489,7 @@ private static void printHelp(OptionParser parser, PrintStream stream) { stream.format(rowFormat, "", "amount (btc), min amount, use mkt based price, \\", ""); stream.format(rowFormat, "", "fixed price (btc) | mkt price margin (%), \\", ""); stream.format(rowFormat, "", "security deposit (%)", ""); + stream.format(rowFormat, "canceloffer", "offer id", "Cancel offer with id"); stream.format(rowFormat, "getoffer", "offer id", "Get current offer with id"); stream.format(rowFormat, "getoffers", "buy | sell, currency code", "Get current offers"); stream.format(rowFormat, "takeoffer", "offer id", "Take offer with id"); diff --git a/core/src/main/java/bisq/core/api/CoreApi.java b/core/src/main/java/bisq/core/api/CoreApi.java index 001bf4773bc..7cfcc5ce152 100644 --- a/core/src/main/java/bisq/core/api/CoreApi.java +++ b/core/src/main/java/bisq/core/api/CoreApi.java @@ -142,6 +142,10 @@ public Offer editOffer(String offerId, paymentAccount); } + public void cancelOffer(String id) { + coreOffersService.cancelOffer(id); + } + /////////////////////////////////////////////////////////////////////////////////////////// // PaymentAccounts /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/bisq/core/api/CoreOffersService.java b/core/src/main/java/bisq/core/api/CoreOffersService.java index da07677f1b2..1a35af4ea2e 100644 --- a/core/src/main/java/bisq/core/api/CoreOffersService.java +++ b/core/src/main/java/bisq/core/api/CoreOffersService.java @@ -160,6 +160,10 @@ Offer editOffer(String offerId, paymentAccount); } + void cancelOffer(String id) { + log.info("TODO"); + } + private void placeOffer(Offer offer, double buyerSecurityDeposit, boolean useSavingsWallet, diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java index d7785935563..f03155d2f8d 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java @@ -21,6 +21,8 @@ import bisq.core.api.model.OfferInfo; import bisq.core.offer.Offer; +import bisq.proto.grpc.CancelOfferReply; +import bisq.proto.grpc.CancelOfferRequest; import bisq.proto.grpc.CreateOfferReply; import bisq.proto.grpc.CreateOfferRequest; import bisq.proto.grpc.GetOfferReply; @@ -114,4 +116,19 @@ public void createOffer(CreateOfferRequest req, throw ex; } } + + @Override + public void cancelOffer(CancelOfferRequest req, + StreamObserver responseObserver) { + try { + coreApi.cancelOffer(req.getId()); + var reply = CancelOfferReply.newBuilder().build(); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + } catch (IllegalStateException | IllegalArgumentException cause) { + var ex = new StatusRuntimeException(Status.UNKNOWN.withDescription(cause.getMessage())); + responseObserver.onError(ex); + throw ex; + } + } } diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 006c6a6f111..d9e0a3973d8 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -51,6 +51,8 @@ service Offers { } rpc CreateOffer (CreateOfferRequest) returns (CreateOfferReply) { } + rpc CancelOffer (CancelOfferRequest) returns (CancelOfferReply) { + } } message GetOfferRequest { @@ -85,6 +87,13 @@ message CreateOfferReply { OfferInfo offer = 1; } +message CancelOfferRequest { + string id = 1; +} + +message CancelOfferReply { +} + message OfferInfo { string id = 1; string direction = 2; From 0f1d4f8ac38d0591c2e4c1b10608938b36c8619a Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Tue, 27 Oct 2020 15:03:36 -0300 Subject: [PATCH 07/20] Fix typo --- cli/src/main/java/bisq/cli/CliMain.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/main/java/bisq/cli/CliMain.java b/cli/src/main/java/bisq/cli/CliMain.java index 8639c95602f..ec0e5e71bb6 100644 --- a/cli/src/main/java/bisq/cli/CliMain.java +++ b/cli/src/main/java/bisq/cli/CliMain.java @@ -260,7 +260,7 @@ public static void run(String[] args) { var request = GetOfferRequest.newBuilder() .setId(offerId) .build(); - var reply =offersService.getOffer(request); + var reply = offersService.getOffer(request); out.println(formatOfferTable(singletonList(reply.getOffer()), reply.getOffer().getCounterCurrencyCode())); return; From b38507c6e68aca9176da48515633dcc613e80ddc Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Tue, 27 Oct 2020 15:31:57 -0300 Subject: [PATCH 08/20] Implement api method 'canceloffer' --- core/src/main/java/bisq/core/api/CoreOffersService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/bisq/core/api/CoreOffersService.java b/core/src/main/java/bisq/core/api/CoreOffersService.java index 1a35af4ea2e..6d8641c0579 100644 --- a/core/src/main/java/bisq/core/api/CoreOffersService.java +++ b/core/src/main/java/bisq/core/api/CoreOffersService.java @@ -161,7 +161,13 @@ Offer editOffer(String offerId, } void cancelOffer(String id) { - log.info("TODO"); + Offer offer = getOffer(id); + openOfferManager.removeOffer(offer, + () -> { + }, + errorMessage -> { + throw new IllegalStateException(errorMessage); + }); } private void placeOffer(Offer offer, From 91a2e2ce1ff0e900ac0ad91b92da1de420dc3171 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Tue, 27 Oct 2020 19:06:59 -0300 Subject: [PATCH 09/20] Add canceloffer test --- .../java/bisq/apitest/method/MethodTest.java | 11 +++ .../method/offer/AbstractOfferTest.java | 5 ++ .../apitest/method/offer/CancelOfferTest.java | 81 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 apitest/src/test/java/bisq/apitest/method/offer/CancelOfferTest.java diff --git a/apitest/src/test/java/bisq/apitest/method/MethodTest.java b/apitest/src/test/java/bisq/apitest/method/MethodTest.java index cf5b74c750c..dcf438f245e 100644 --- a/apitest/src/test/java/bisq/apitest/method/MethodTest.java +++ b/apitest/src/test/java/bisq/apitest/method/MethodTest.java @@ -17,6 +17,7 @@ package bisq.apitest.method; +import bisq.proto.grpc.CancelOfferRequest; import bisq.proto.grpc.ConfirmPaymentReceivedRequest; import bisq.proto.grpc.ConfirmPaymentStartedRequest; import bisq.proto.grpc.CreatePaymentAccountRequest; @@ -112,6 +113,10 @@ protected final GetOfferRequest createGetOfferRequest(String offerId) { return GetOfferRequest.newBuilder().setId(offerId).build(); } + protected final CancelOfferRequest createCancelOfferRequest(String offerId) { + return CancelOfferRequest.newBuilder().setId(offerId).build(); + } + protected final TakeOfferRequest createTakeOfferRequest(String offerId, String paymentAccountId) { return TakeOfferRequest.newBuilder().setOfferId(offerId).setPaymentAccountId(paymentAccountId).build(); } @@ -202,6 +207,12 @@ protected final OfferInfo getOffer(BisqAppConfig bisqAppConfig, String offerId) return grpcStubs(bisqAppConfig).offersService.getOffer(req).getOffer(); } + @SuppressWarnings("ResultOfMethodCallIgnored") + protected final void cancelOffer(BisqAppConfig bisqAppConfig, String offerId) { + var req = createCancelOfferRequest(offerId); + grpcStubs(bisqAppConfig).offersService.cancelOffer(req); + } + protected final TradeInfo getTrade(BisqAppConfig bisqAppConfig, String tradeId) { var req = createGetTradeRequest(tradeId); return grpcStubs(bisqAppConfig).tradesService.getTrade(req).getTrade(); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java index a08e08d0bc3..b1bae6fbd86 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java @@ -123,6 +123,11 @@ protected final OfferInfo getOffer(String offerId) { return aliceStubs.offersService.getOffer(createGetOfferRequest(offerId)).getOffer(); } + @SuppressWarnings("ResultOfMethodCallIgnored") + protected final void cancelOffer(GrpcStubs grpcStubs, String offerId) { + grpcStubs.offersService.cancelOffer(createCancelOfferRequest(offerId)); + } + protected final OfferInfo getMostRecentOffer(GrpcStubs grpcStubs, String direction, String currencyCode) { List offerInfoList = getOffersSortedByDate(grpcStubs, direction, currencyCode); if (offerInfoList.isEmpty()) diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CancelOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CancelOfferTest.java new file mode 100644 index 00000000000..6affb9ac38a --- /dev/null +++ b/apitest/src/test/java/bisq/apitest/method/offer/CancelOfferTest.java @@ -0,0 +1,81 @@ +/* + * 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 . + */ + +package bisq.apitest.method.offer; + +import bisq.core.btc.wallet.Restrictions; + +import bisq.proto.grpc.CreateOfferRequest; +import bisq.proto.grpc.OfferInfo; + +import java.util.List; + +import lombok.extern.slf4j.Slf4j; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + + +@Slf4j +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class CancelOfferTest extends AbstractOfferTest { + + private static final int MAX_OFFERS = 3; + + @Test + @Order(1) + public void testCancelOffer() { + var req = CreateOfferRequest.newBuilder() + .setPaymentAccountId(alicesDummyAcct.getId()) + .setDirection("buy") + .setCurrencyCode("cad") + .setAmount(10000000) + .setMinAmount(10000000) + .setUseMarketBasedPrice(true) + .setMarketPriceMargin(0.00) + .setPrice("0") + .setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent()) + .build(); + + // Create some offers. + for (int i = 1; i <= MAX_OFFERS; i++) { + //noinspection ResultOfMethodCallIgnored + aliceStubs.offersService.createOffer(req); + // Wait for Alice's AddToOfferBook task. + // Wait times vary; my logs show >= 2 second delay. + sleep(2500); + } + + List offers = getOffersSortedByDate(aliceStubs, "buy", "cad"); + assertEquals(MAX_OFFERS, offers.size()); + + // Cancel the offers, checking the open offer count after each offer removal. + for (int i = 1; i <= MAX_OFFERS; i++) { + cancelOffer(aliceStubs, offers.remove(0).getId()); + assertEquals(MAX_OFFERS - i, getOpenOffersCount(aliceStubs, "buy", "cad")); + } + + sleep(1000); // wait for offer removal + + offers = getOffersSortedByDate(aliceStubs, "buy", "cad"); + assertEquals(0, offers.size()); + } +} From 8e51e1e495d79470defae2c9877f3a8d43cb095f Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Wed, 28 Oct 2020 17:21:04 -0300 Subject: [PATCH 10/20] Upgrade jupiterVersion = '5.7.0' This upgrades jupiter for all subprojects using this library, but it does not affect released code. --- build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 6007dd14475..57624f26fe5 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ configure(subprojects) { joptVersion = '5.0.4' jsonsimpleVersion = '1.1.1' junitVersion = '4.12' - jupiterVersion = '5.3.2' + jupiterVersion = '5.7.0' kotlinVersion = '1.3.41' knowmXchangeVersion = '4.4.2' langVersion = '3.8' @@ -658,12 +658,12 @@ configure(project(':apitest')) { compileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion" - testCompile "org.junit.jupiter:junit-jupiter-api:5.6.2" - testCompile "org.junit.jupiter:junit-jupiter-params:5.6.2" + testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion" + testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion" + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion") testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion" testCompileOnly "org.projectlombok:lombok:$lombokVersion" testRuntime "javax.annotation:javax.annotation-api:$javaxAnnotationVersion" - testRuntime("org.junit.jupiter:junit-jupiter-engine:5.6.2") } } From d6524bf46d5e8a9960c1c992a12a106be8877401 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Wed, 28 Oct 2020 17:39:50 -0300 Subject: [PATCH 11/20] Improve apitest cmd line console logging - Show full stack traces in console - Do use previously cached test outputs - Do not show skipped test name in console (too noisy) - Show test run summary, including number of skipped tests - Show note about skipped test info in the html report - Show link to html report on test SUCCESS --- build.gradle | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 57624f26fe5..56ede17a7b1 100644 --- a/build.gradle +++ b/build.gradle @@ -627,8 +627,31 @@ configure(project(':apitest')) { test { useJUnitPlatform() + outputs.upToDateWhen { false } // Don't use previously cached test outputs. testLogging { - events "passed", "skipped", "failed" + showStackTraces = true // Show full stack traces in the console. + exceptionFormat = "full" + // Show passed & failed tests, and anything printed to stderr by the tests in the console. + // Do not show skipped tests in the console; they are shown in the html report. + events "passed", "failed", "standardError" + } + + afterSuite { desc, result -> + if (!desc.parent) { + println("${result.resultType} " + + "[${result.testCount} tests, " + + "${result.successfulTestCount} passed, " + + "${result.failedTestCount} failed, " + + "${result.skippedTestCount} skipped] html report contains skipped test info") + + // Show report link if all tests passed in case you want to see more detail, stdout, skipped, etc. + if(result.resultType == TestResult.ResultType.SUCCESS) { + DirectoryReport htmlReport = getReports().getHtml() + String reportUrl = new org.gradle.internal.logging.ConsoleRenderer() + .asClickableFileUrl(htmlReport.getEntryPoint()) + println("REPORT " + reportUrl) + } + } } } From 2a052035190081c51d561e4e431ffca2b68987ec Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Wed, 28 Oct 2020 17:46:30 -0300 Subject: [PATCH 12/20] Remove dead code --- .../src/main/java/bisq/apitest/linux/AbstractLinuxProcess.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/apitest/src/main/java/bisq/apitest/linux/AbstractLinuxProcess.java b/apitest/src/main/java/bisq/apitest/linux/AbstractLinuxProcess.java index 4687477e956..770df37ede2 100644 --- a/apitest/src/main/java/bisq/apitest/linux/AbstractLinuxProcess.java +++ b/apitest/src/main/java/bisq/apitest/linux/AbstractLinuxProcess.java @@ -70,10 +70,8 @@ public boolean hasShutdownExceptions() { @Override public void logExceptions(List exceptions, org.slf4j.Logger log) { - StringBuilder errorBuilder = new StringBuilder(); for (Throwable t : exceptions) { log.error("", t); - errorBuilder.append(t.getMessage()).append("\n"); } } From f61f148db194f38b16b299027a82289eea6d78ca Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Wed, 28 Oct 2020 17:59:15 -0300 Subject: [PATCH 13/20] Refactor api test fixture setup - Remove dead code from AbstractLinuxProcess. - Make default dummy accts static in MethodTest. - Simplify gRPC stub creation, btc block generation, dispute agent registration, and dummy acct initialization in test case startup. - Make ExpectedProtocolStatus visible to scenario test pkg. --- .../java/bisq/apitest/method/MethodTest.java | 47 ++++++++--- .../method/offer/AbstractOfferTest.java | 30 ++----- .../method/trade/AbstractTradeTest.java | 79 +------------------ .../method/trade/ExpectedProtocolStatus.java | 69 ++++++++++++++++ 4 files changed, 115 insertions(+), 110 deletions(-) create mode 100644 apitest/src/test/java/bisq/apitest/method/trade/ExpectedProtocolStatus.java diff --git a/apitest/src/test/java/bisq/apitest/method/MethodTest.java b/apitest/src/test/java/bisq/apitest/method/MethodTest.java index dcf438f245e..6b21d76fb4a 100644 --- a/apitest/src/test/java/bisq/apitest/method/MethodTest.java +++ b/apitest/src/test/java/bisq/apitest/method/MethodTest.java @@ -43,11 +43,14 @@ import java.util.stream.Collectors; import static bisq.apitest.config.BisqAppConfig.alicedaemon; +import static bisq.apitest.config.BisqAppConfig.arbdaemon; import static bisq.apitest.config.BisqAppConfig.bobdaemon; import static bisq.common.app.DevEnv.DEV_PRIVILEGE_PRIV_KEY; import static bisq.core.payment.payload.PaymentMethod.PERFECT_MONEY; +import static java.util.Arrays.stream; import static java.util.Comparator.comparing; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; @@ -64,15 +67,39 @@ public class MethodTest extends ApiTestCase { protected static GrpcStubs aliceStubs; protected static GrpcStubs bobStubs; - protected PaymentAccount alicesDummyAcct; - protected PaymentAccount bobsDummyAcct; - - protected final void initAlicesDummyPaymentAccount() { - alicesDummyAcct = getDefaultPerfectDummyPaymentAccount(alicedaemon); - } - - protected final void initBobsDummyPaymentAccount() { - bobsDummyAcct = getDefaultPerfectDummyPaymentAccount(bobdaemon); + protected static PaymentAccount alicesDummyAcct; + protected static PaymentAccount bobsDummyAcct; + + public static void startSupportingApps(boolean registerDisputeAgents, + boolean generateBtcBlock, + Enum... supportingApps) { + try { + // To run Bisq apps in debug mode, use the other setUpScaffold method: + // setUpScaffold(new String[]{"--supportingApps", "bitcoind,seednode,arbdaemon,alicedaemon,bobdaemon", + // "--enableBisqDebugging", "true"}); + setUpScaffold(supportingApps); + if (registerDisputeAgents) { + registerDisputeAgents(arbdaemon); + } + + if (stream(supportingApps).map(Enum::name).anyMatch(name -> name.equals(alicedaemon.name()))) { + aliceStubs = grpcStubs(alicedaemon); + alicesDummyAcct = getDefaultPerfectDummyPaymentAccount(alicedaemon); + } + + if (stream(supportingApps).map(Enum::name).anyMatch(name -> name.equals(bobdaemon.name()))) { + bobStubs = grpcStubs(bobdaemon); + bobsDummyAcct = getDefaultPerfectDummyPaymentAccount(bobdaemon); + } + + // Generate 1 regtest block for alice's and/or bob's wallet to + // show 10 BTC balance, and allow time for daemons parse the new block. + if (generateBtcBlock) + genBtcBlocksThenWait(1, 1500); + + } catch (Exception ex) { + fail(ex); + } } // Convenience methods for building gRPC request objects @@ -185,7 +212,7 @@ protected final CreatePaymentAccountRequest createCreatePerfectMoneyPaymentAccou .build(); } - protected final PaymentAccount getDefaultPerfectDummyPaymentAccount(BisqAppConfig bisqAppConfig) { + protected static PaymentAccount getDefaultPerfectDummyPaymentAccount(BisqAppConfig bisqAppConfig) { var req = GetPaymentAccountsRequest.newBuilder().build(); var paymentAccountsService = grpcStubs(bisqAppConfig).paymentAccountsService; PaymentAccount paymentAccount = paymentAccountsService.getPaymentAccounts(req) diff --git a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java index b1bae6fbd86..fe9a98aaaae 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java @@ -36,7 +36,6 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind; import static bisq.apitest.config.BisqAppConfig.alicedaemon; @@ -62,28 +61,13 @@ public abstract class AbstractOfferTest extends MethodTest { @BeforeAll public static void setUp() { - startSupportingApps(); - } - - @BeforeEach - public void initDummyPaymentAccount() { - super.initAlicesDummyPaymentAccount(); - } - - static void startSupportingApps() { - try { - // setUpScaffold(new String[]{"--supportingApps", "bitcoind,seednode,arbdaemon,alicedaemon,bobdaemon", "--enableBisqDebugging", "true"}); - setUpScaffold(bitcoind, seednode, arbdaemon, alicedaemon, bobdaemon); - registerDisputeAgents(arbdaemon); - aliceStubs = grpcStubs(alicedaemon); - bobStubs = grpcStubs(bobdaemon); - - // Generate 1 regtest block for alice's wallet to show 10 BTC balance, - // and give alicedaemon time to parse the new block. - genBtcBlocksThenWait(1, 1500); - } catch (Exception ex) { - fail(ex); - } + startSupportingApps(true, + true, + bitcoind, + seednode, + arbdaemon, + alicedaemon, + bobdaemon); } protected final OfferInfo createAliceOffer(PaymentAccount paymentAccount, diff --git a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java index 22aee1d70dd..e8537206dbf 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java @@ -1,13 +1,10 @@ package bisq.apitest.method.trade; -import bisq.core.trade.Trade; - import bisq.proto.grpc.TradeInfo; import org.slf4j.Logger; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.TestInfo; import static bisq.cli.TradeFormat.format; @@ -20,24 +17,16 @@ public class AbstractTradeTest extends AbstractOfferTest { - // A test fixture encapsulating expected trade protocol status. - // ExpectedProtocolStatus.init should be called before any @Test begins. - protected static final ExpectedProtocolStatus EXPECTED_PROTOCOL_STATUS = new ExpectedProtocolStatus(); + public static final ExpectedProtocolStatus EXPECTED_PROTOCOL_STATUS = new ExpectedProtocolStatus(); // A Trade ID cache for use in @Test sequences. protected static String tradeId; @BeforeAll - public static void clearExpectedPaymentStatusFlags() { + public static void initStaticFixtures() { EXPECTED_PROTOCOL_STATUS.init(); } - @BeforeEach - public void initDummyPaymentAccounts() { - super.initAlicesDummyPaymentAccount(); - super.initBobsDummyPaymentAccount(); - } - protected final TradeInfo takeAlicesOffer(String offerId, String paymentAccountId) { return bobStubs.tradesService.takeOffer(createTakeOfferRequest(offerId, paymentAccountId)).getTrade(); } @@ -68,68 +57,4 @@ protected final void logTrade(Logger log, description.toUpperCase(), format(trade))); } - - @SuppressWarnings("UnusedReturnValue") - static class ExpectedProtocolStatus { - Trade.State state; - Trade.Phase phase; - boolean isDepositPublished; - boolean isDepositConfirmed; - boolean isFiatSent; - boolean isFiatReceived; - boolean isPayoutPublished; - boolean isWithdrawn; - - ExpectedProtocolStatus setState(Trade.State state) { - this.state = state; - return this; - } - - ExpectedProtocolStatus setPhase(Trade.Phase phase) { - this.phase = phase; - return this; - } - - ExpectedProtocolStatus setDepositPublished(boolean depositPublished) { - isDepositPublished = depositPublished; - return this; - } - - ExpectedProtocolStatus setDepositConfirmed(boolean depositConfirmed) { - isDepositConfirmed = depositConfirmed; - return this; - } - - ExpectedProtocolStatus setFiatSent(boolean fiatSent) { - isFiatSent = fiatSent; - return this; - } - - ExpectedProtocolStatus setFiatReceived(boolean fiatReceived) { - isFiatReceived = fiatReceived; - return this; - } - - ExpectedProtocolStatus setPayoutPublished(boolean payoutPublished) { - isPayoutPublished = payoutPublished; - return this; - } - - ExpectedProtocolStatus setWithdrawn(boolean withdrawn) { - isWithdrawn = withdrawn; - return this; - } - - @SuppressWarnings("unused") - void init() { - state = null; - phase = null; - isDepositPublished = false; - isDepositConfirmed = false; - isFiatSent = false; - isFiatReceived = false; - isPayoutPublished = false; - isWithdrawn = false; - } - } } diff --git a/apitest/src/test/java/bisq/apitest/method/trade/ExpectedProtocolStatus.java b/apitest/src/test/java/bisq/apitest/method/trade/ExpectedProtocolStatus.java new file mode 100644 index 00000000000..63655585947 --- /dev/null +++ b/apitest/src/test/java/bisq/apitest/method/trade/ExpectedProtocolStatus.java @@ -0,0 +1,69 @@ +package bisq.apitest.method.trade; + +import bisq.core.trade.Trade; + +/** + * A test fixture encapsulating expected trade protocol status. + * Status flags should be cleared via init() before starting a new trade protocol. + */ +public class ExpectedProtocolStatus { + Trade.State state; + Trade.Phase phase; + boolean isDepositPublished; + boolean isDepositConfirmed; + boolean isFiatSent; + boolean isFiatReceived; + boolean isPayoutPublished; + boolean isWithdrawn; + + public ExpectedProtocolStatus setState(Trade.State state) { + this.state = state; + return this; + } + + public ExpectedProtocolStatus setPhase(Trade.Phase phase) { + this.phase = phase; + return this; + } + + public ExpectedProtocolStatus setDepositPublished(boolean depositPublished) { + isDepositPublished = depositPublished; + return this; + } + + public ExpectedProtocolStatus setDepositConfirmed(boolean depositConfirmed) { + isDepositConfirmed = depositConfirmed; + return this; + } + + public ExpectedProtocolStatus setFiatSent(boolean fiatSent) { + isFiatSent = fiatSent; + return this; + } + + public ExpectedProtocolStatus setFiatReceived(boolean fiatReceived) { + isFiatReceived = fiatReceived; + return this; + } + + public ExpectedProtocolStatus setPayoutPublished(boolean payoutPublished) { + isPayoutPublished = payoutPublished; + return this; + } + + public ExpectedProtocolStatus setWithdrawn(boolean withdrawn) { + isWithdrawn = withdrawn; + return this; + } + + public void init() { + state = null; + phase = null; + isDepositPublished = false; + isDepositConfirmed = false; + isFiatSent = false; + isFiatReceived = false; + isPayoutPublished = false; + isWithdrawn = false; + } +} From e8e55d2286ec8063361c3ece281883648e6c6ba9 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Wed, 28 Oct 2020 18:01:49 -0300 Subject: [PATCH 14/20] Remove redundant ScenarioTest superclass --- .../scenario/FundWalletScenarioTest.java | 6 +++- .../bisq/apitest/scenario/ScenarioTest.java | 28 ------------------- 2 files changed, 5 insertions(+), 29 deletions(-) delete mode 100644 apitest/src/test/java/bisq/apitest/scenario/ScenarioTest.java diff --git a/apitest/src/test/java/bisq/apitest/scenario/FundWalletScenarioTest.java b/apitest/src/test/java/bisq/apitest/scenario/FundWalletScenarioTest.java index 75977949c33..4b7d40f516c 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/FundWalletScenarioTest.java +++ b/apitest/src/test/java/bisq/apitest/scenario/FundWalletScenarioTest.java @@ -33,9 +33,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; + + +import bisq.apitest.method.MethodTest; + @Slf4j @TestMethodOrder(MethodOrderer.OrderAnnotation.class) -public class FundWalletScenarioTest extends ScenarioTest { +public class FundWalletScenarioTest extends MethodTest { @BeforeAll public static void setUp() { diff --git a/apitest/src/test/java/bisq/apitest/scenario/ScenarioTest.java b/apitest/src/test/java/bisq/apitest/scenario/ScenarioTest.java deleted file mode 100644 index 9750b2ed9d6..00000000000 --- a/apitest/src/test/java/bisq/apitest/scenario/ScenarioTest.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 . - */ - -package bisq.apitest.scenario; - -import lombok.extern.slf4j.Slf4j; - - - -import bisq.apitest.method.MethodTest; - -@Slf4j -public class ScenarioTest extends MethodTest { -} From c2f8db3c7dcd30d9af054d091c0fd8d304879f6b Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Wed, 28 Oct 2020 18:17:59 -0300 Subject: [PATCH 15/20] Reduce apitest case execution time Consolidated all method tests into fewer test cases by running them from new 'scenario' test cases. This cuts the current scaffold setup & teardown times by almost 1/2. No method tests were deleted or duplicated. (1) Disabled all method (unit) test cases at the class level. (2) Added new scenario test cases to run all disabled test cases (1). The method test cases can still be run by commenting out the @Disabled annotation. --- .../method/CreatePaymentAccountTest.java | 3 +- .../bisq/apitest/method/GetBalanceTest.java | 3 +- .../bisq/apitest/method/GetVersionTest.java | 3 +- .../java/bisq/apitest/method/MethodTest.java | 1 - .../method/RegisterDisputeAgentsTest.java | 2 + .../apitest/method/WalletProtectionTest.java | 2 + .../apitest/method/offer/CancelOfferTest.java | 3 +- .../offer/CreateOfferUsingFixedPriceTest.java | 3 +- ...CreateOfferUsingMarketPriceMarginTest.java | 2 + .../method/offer/ValidateCreateOfferTest.java | 2 + .../method/trade/TakeBuyBTCOfferTest.java | 2 + .../method/trade/TakeSellBTCOfferTest.java | 2 + .../java/bisq/apitest/scenario/OfferTest.java | 72 ++++++++++++++ .../bisq/apitest/scenario/StartupTest.java | 85 ++++++++++++++++ .../java/bisq/apitest/scenario/TradeTest.java | 64 ++++++++++++ .../bisq/apitest/scenario/WalletTest.java | 99 +++++++++++++++++++ 16 files changed, 342 insertions(+), 6 deletions(-) create mode 100644 apitest/src/test/java/bisq/apitest/scenario/OfferTest.java create mode 100644 apitest/src/test/java/bisq/apitest/scenario/StartupTest.java create mode 100644 apitest/src/test/java/bisq/apitest/scenario/TradeTest.java create mode 100644 apitest/src/test/java/bisq/apitest/scenario/WalletTest.java diff --git a/apitest/src/test/java/bisq/apitest/method/CreatePaymentAccountTest.java b/apitest/src/test/java/bisq/apitest/method/CreatePaymentAccountTest.java index 661205c74d3..9e8b0af878a 100644 --- a/apitest/src/test/java/bisq/apitest/method/CreatePaymentAccountTest.java +++ b/apitest/src/test/java/bisq/apitest/method/CreatePaymentAccountTest.java @@ -29,6 +29,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; @@ -40,7 +41,7 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation; - +@Disabled @Slf4j @TestMethodOrder(OrderAnnotation.class) public class CreatePaymentAccountTest extends MethodTest { diff --git a/apitest/src/test/java/bisq/apitest/method/GetBalanceTest.java b/apitest/src/test/java/bisq/apitest/method/GetBalanceTest.java index abce9a78a66..1d44590837b 100644 --- a/apitest/src/test/java/bisq/apitest/method/GetBalanceTest.java +++ b/apitest/src/test/java/bisq/apitest/method/GetBalanceTest.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; @@ -35,7 +36,7 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation; - +@Disabled @Slf4j @TestMethodOrder(OrderAnnotation.class) public class GetBalanceTest extends MethodTest { diff --git a/apitest/src/test/java/bisq/apitest/method/GetVersionTest.java b/apitest/src/test/java/bisq/apitest/method/GetVersionTest.java index 82780340ee8..212eb5ca438 100644 --- a/apitest/src/test/java/bisq/apitest/method/GetVersionTest.java +++ b/apitest/src/test/java/bisq/apitest/method/GetVersionTest.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; @@ -33,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation; - +@Disabled @Slf4j @TestMethodOrder(OrderAnnotation.class) public class GetVersionTest extends MethodTest { diff --git a/apitest/src/test/java/bisq/apitest/method/MethodTest.java b/apitest/src/test/java/bisq/apitest/method/MethodTest.java index 6b21d76fb4a..43073ba995b 100644 --- a/apitest/src/test/java/bisq/apitest/method/MethodTest.java +++ b/apitest/src/test/java/bisq/apitest/method/MethodTest.java @@ -96,7 +96,6 @@ public static void startSupportingApps(boolean registerDisputeAgents, // show 10 BTC balance, and allow time for daemons parse the new block. if (generateBtcBlock) genBtcBlocksThenWait(1, 1500); - } catch (Exception ex) { fail(ex); } diff --git a/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java b/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java index 379fbc3a004..746c851b4d5 100644 --- a/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java +++ b/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; @@ -40,6 +41,7 @@ @SuppressWarnings("ResultOfMethodCallIgnored") +@Disabled @Slf4j @TestMethodOrder(OrderAnnotation.class) public class RegisterDisputeAgentsTest extends MethodTest { diff --git a/apitest/src/test/java/bisq/apitest/method/WalletProtectionTest.java b/apitest/src/test/java/bisq/apitest/method/WalletProtectionTest.java index 61f3c27e4a1..08547e9ebb9 100644 --- a/apitest/src/test/java/bisq/apitest/method/WalletProtectionTest.java +++ b/apitest/src/test/java/bisq/apitest/method/WalletProtectionTest.java @@ -6,6 +6,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; @@ -18,6 +19,7 @@ import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation; @SuppressWarnings("ResultOfMethodCallIgnored") +@Disabled @Slf4j @TestMethodOrder(OrderAnnotation.class) public class WalletProtectionTest extends MethodTest { diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CancelOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CancelOfferTest.java index 6affb9ac38a..334fb022bb3 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CancelOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CancelOfferTest.java @@ -26,6 +26,7 @@ import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -33,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; - +@Disabled @Slf4j @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class CancelOfferTest extends AbstractOfferTest { diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java index 10ca6c9e4cb..72ff91f3115 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java @@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -32,11 +33,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; +@Disabled @Slf4j @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class CreateOfferUsingFixedPriceTest extends AbstractOfferTest { - @Test @Order(1) public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java index b0c017baff0..345bd130d71 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java @@ -26,6 +26,7 @@ import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -40,6 +41,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static protobuf.OfferPayload.Direction.BUY; +@Disabled @Slf4j @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest { diff --git a/apitest/src/test/java/bisq/apitest/method/offer/ValidateCreateOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/ValidateCreateOfferTest.java index ecf09b1e421..3ddd8cb3030 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/ValidateCreateOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/ValidateCreateOfferTest.java @@ -25,6 +25,7 @@ import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -33,6 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +@Disabled @Slf4j @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class ValidateCreateOfferTest extends AbstractOfferTest { diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java index bb7d8ea8239..3561787c454 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java @@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -41,6 +42,7 @@ import static protobuf.Offer.State.OFFER_FEE_PAID; import static protobuf.OpenOffer.State.AVAILABLE; +@Disabled @Slf4j @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class TakeBuyBTCOfferTest extends AbstractTradeTest { diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java index c1786082ba8..35e13c002fa 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java @@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -38,6 +39,7 @@ import static protobuf.Offer.State.OFFER_FEE_PAID; import static protobuf.OpenOffer.State.AVAILABLE; +@Disabled @Slf4j @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class TakeSellBTCOfferTest extends AbstractTradeTest { diff --git a/apitest/src/test/java/bisq/apitest/scenario/OfferTest.java b/apitest/src/test/java/bisq/apitest/scenario/OfferTest.java new file mode 100644 index 00000000000..b01a9486ea5 --- /dev/null +++ b/apitest/src/test/java/bisq/apitest/scenario/OfferTest.java @@ -0,0 +1,72 @@ +/* + * 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 . + */ + +package bisq.apitest.scenario; + + +import lombok.extern.slf4j.Slf4j; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + + + +import bisq.apitest.method.offer.AbstractOfferTest; +import bisq.apitest.method.offer.CancelOfferTest; +import bisq.apitest.method.offer.CreateOfferUsingFixedPriceTest; +import bisq.apitest.method.offer.CreateOfferUsingMarketPriceMarginTest; +import bisq.apitest.method.offer.ValidateCreateOfferTest; + +@Slf4j +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class OfferTest extends AbstractOfferTest { + + @Test + @Order(1) + public void testAmtTooLargeShouldThrowException() { + ValidateCreateOfferTest test = new ValidateCreateOfferTest(); + test.testAmtTooLargeShouldThrowException(); + } + + @Test + @Order(2) + public void testCancelOffer() { + CancelOfferTest test = new CancelOfferTest(); + test.testCancelOffer(); + } + + @Test + @Order(3) + public void testCreateOfferUsingFixedPrice() { + CreateOfferUsingFixedPriceTest test = new CreateOfferUsingFixedPriceTest(); + test.testCreateAUDBTCBuyOfferUsingFixedPrice16000(); + test.testCreateUSDBTCBuyOfferUsingFixedPrice100001234(); + test.testCreateEURBTCSellOfferUsingFixedPrice95001234(); + } + + @Test + @Order(4) + public void testCreateOfferUsingMarketPriceMargin() { + CreateOfferUsingMarketPriceMarginTest test = new CreateOfferUsingMarketPriceMarginTest(); + test.testCreateUSDBTCBuyOffer5PctPriceMargin(); + test.testCreateNZDBTCBuyOfferMinus2PctPriceMargin(); + test.testCreateGBPBTCSellOfferMinus1Point5PctPriceMargin(); + test.testCreateBRLBTCSellOffer6Point55PctPriceMargin(); + } +} diff --git a/apitest/src/test/java/bisq/apitest/scenario/StartupTest.java b/apitest/src/test/java/bisq/apitest/scenario/StartupTest.java new file mode 100644 index 00000000000..fa81ddff6b9 --- /dev/null +++ b/apitest/src/test/java/bisq/apitest/scenario/StartupTest.java @@ -0,0 +1,85 @@ +/* + * 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 . + */ + +package bisq.apitest.scenario; + +import lombok.extern.slf4j.Slf4j; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind; +import static bisq.apitest.config.BisqAppConfig.alicedaemon; +import static bisq.apitest.config.BisqAppConfig.arbdaemon; +import static bisq.apitest.config.BisqAppConfig.seednode; +import static org.junit.jupiter.api.Assertions.fail; + + + +import bisq.apitest.method.CreatePaymentAccountTest; +import bisq.apitest.method.GetVersionTest; +import bisq.apitest.method.MethodTest; +import bisq.apitest.method.RegisterDisputeAgentsTest; + + +@Slf4j +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class StartupTest extends MethodTest { + + @BeforeAll + public static void setUp() { + try { + setUpScaffold(bitcoind, seednode, arbdaemon, alicedaemon); + } catch (Exception ex) { + fail(ex); + } + } + + @Test + @Order(1) + public void testGetVersion() { + GetVersionTest test = new GetVersionTest(); + test.testGetVersion(); + } + + @Test + @Order(2) + public void testRegisterDisputeAgents() { + RegisterDisputeAgentsTest test = new RegisterDisputeAgentsTest(); + test.testRegisterArbitratorShouldThrowException(); + test.testInvalidDisputeAgentTypeArgShouldThrowException(); + test.testInvalidRegistrationKeyArgShouldThrowException(); + test.testRegisterMediator(); + test.testRegisterRefundAgent(); + } + + @Test + @Order(3) + public void testCreatePaymentAccount() { + CreatePaymentAccountTest test = new CreatePaymentAccountTest(); + test.testCreatePerfectMoneyUSDPaymentAccount(); + } + + @AfterAll + public static void tearDown() { + tearDownScaffold(); + } +} diff --git a/apitest/src/test/java/bisq/apitest/scenario/TradeTest.java b/apitest/src/test/java/bisq/apitest/scenario/TradeTest.java new file mode 100644 index 00000000000..4c07452abc6 --- /dev/null +++ b/apitest/src/test/java/bisq/apitest/scenario/TradeTest.java @@ -0,0 +1,64 @@ +/* + * 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 . + */ + +package bisq.apitest.scenario; + +import lombok.extern.slf4j.Slf4j; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.TestMethodOrder; + + + +import bisq.apitest.method.trade.AbstractTradeTest; +import bisq.apitest.method.trade.TakeBuyBTCOfferTest; +import bisq.apitest.method.trade.TakeSellBTCOfferTest; + + +@Slf4j +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class TradeTest extends AbstractTradeTest { + + @BeforeEach + public void init() { + EXPECTED_PROTOCOL_STATUS.init(); + } + + @Test + @Order(1) + public void testTakeBuyBTCOffer(final TestInfo testInfo) { + TakeBuyBTCOfferTest test = new TakeBuyBTCOfferTest(); + test.testTakeAlicesBuyOffer(testInfo); + test.testAlicesConfirmPaymentStarted(testInfo); + test.testBobsConfirmPaymentReceived(testInfo); + test.testAlicesKeepFunds(testInfo); + } + + @Test + @Order(2) + public void testTakeSellBTCOffer(final TestInfo testInfo) { + TakeSellBTCOfferTest test = new TakeSellBTCOfferTest(); + test.testTakeAlicesSellOffer(testInfo); + test.testBobsConfirmPaymentStarted(testInfo); + test.testAlicesConfirmPaymentReceived(testInfo); + test.testBobsBtcWithdrawalToExternalAddress(testInfo); + } +} diff --git a/apitest/src/test/java/bisq/apitest/scenario/WalletTest.java b/apitest/src/test/java/bisq/apitest/scenario/WalletTest.java new file mode 100644 index 00000000000..ecd38dc2295 --- /dev/null +++ b/apitest/src/test/java/bisq/apitest/scenario/WalletTest.java @@ -0,0 +1,99 @@ +/* + * 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 . + */ + +package bisq.apitest.scenario; + +import lombok.extern.slf4j.Slf4j; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind; +import static bisq.apitest.config.BisqAppConfig.alicedaemon; +import static bisq.apitest.config.BisqAppConfig.seednode; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + + + +import bisq.apitest.method.MethodTest; +import bisq.apitest.method.WalletProtectionTest; + +@Slf4j +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class WalletTest extends MethodTest { + + // All tests depend on the DAO / regtest environment, and Alice's wallet is + // initialized with 10 BTC during the scaffolding setup. + + @BeforeAll + public static void setUp() { + try { + setUpScaffold(bitcoind, seednode, alicedaemon); + genBtcBlocksThenWait(1, 1500); + } catch (Exception ex) { + fail(ex); + } + } + + @Test + @Order(1) + public void testFundWallet() { + // The regtest Bisq wallet was initialized with 10 BTC. + long balance = getBalance(alicedaemon); + assertEquals(1000000000, balance); + + String unusedAddress = getUnusedBtcAddress(alicedaemon); + bitcoinCli.sendToAddress(unusedAddress, "2.5"); + + bitcoinCli.generateBlocks(1); + sleep(1500); + + balance = getBalance(alicedaemon); + assertEquals(1250000000L, balance); // new balance is 12.5 btc + } + + @Test + @Order(2) + public void testWalletProtection() { + // Batching all wallet tests in this test case reduces scaffold setup + // time. Here, we create a method WalletProtectionTest instance and run each + // test in declared order. + + WalletProtectionTest walletProtectionTest = new WalletProtectionTest(); + + walletProtectionTest.testSetWalletPassword(); + walletProtectionTest.testGetBalanceOnEncryptedWalletShouldThrowException(); + walletProtectionTest.testUnlockWalletFor4Seconds(); + walletProtectionTest.testGetBalanceAfterUnlockTimeExpiryShouldThrowException(); + walletProtectionTest.testLockWalletBeforeUnlockTimeoutExpiry(); + walletProtectionTest.testLockWalletWhenWalletAlreadyLockedShouldThrowException(); + walletProtectionTest.testUnlockWalletTimeoutOverride(); + walletProtectionTest.testSetNewWalletPassword(); + walletProtectionTest.testSetNewWalletPasswordWithIncorrectNewPasswordShouldThrowException(); + walletProtectionTest.testRemoveNewWalletPassword(); + } + + @AfterAll + public static void tearDown() { + tearDownScaffold(); + } +} From 0656c57d393e3313050a762effefa010347da970 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 30 Oct 2020 11:07:18 -0300 Subject: [PATCH 16/20] Add null checks in PendingTradesViewModel These changes were requested in review of PR https://github.com/bisq-network/bisq/pull/4699 --- .../main/portfolio/pendingtrades/PendingTradesViewModel.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java index 6a9b4dff06c..fc08e6bc233 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java @@ -215,18 +215,22 @@ String getMarketLabel(PendingTradesListItem item) { } public String getRemainingTradeDurationAsWords() { + checkNotNull(dataModel.getTrade(), "model's trade must not be null"); return tradeUtil.getRemainingTradeDurationAsWords(dataModel.getTrade()); } public double getRemainingTradeDurationAsPercentage() { + checkNotNull(dataModel.getTrade(), "model's trade must not be null"); return tradeUtil.getRemainingTradeDurationAsPercentage(dataModel.getTrade()); } public String getDateForOpenDispute() { + checkNotNull(dataModel.getTrade(), "model's trade must not be null"); return DisplayUtils.formatDateTime(tradeUtil.getDateForOpenDispute(dataModel.getTrade())); } public boolean showWarning() { + checkNotNull(dataModel.getTrade(), "model's trade must not be null"); Date halfTradePeriodDate = tradeUtil.getHalfTradePeriodDate(dataModel.getTrade()); return halfTradePeriodDate != null && new Date().after(halfTradePeriodDate); } From f764e9feb07f1cae45309b6271ef84862ee7d8b4 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 30 Oct 2020 11:15:39 -0300 Subject: [PATCH 17/20] Simplify TradeUtil#getPaymentMethodNameWithCountryCode These changes were requested in review of PR https://github.com/bisq-network/bisq/pull/4699 --- core/src/main/java/bisq/core/trade/TradeUtil.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeUtil.java b/core/src/main/java/bisq/core/trade/TradeUtil.java index cd4fd074aad..a026f6ab982 100644 --- a/core/src/main/java/bisq/core/trade/TradeUtil.java +++ b/core/src/main/java/bisq/core/trade/TradeUtil.java @@ -164,14 +164,13 @@ public String getMarketDescription(Trade trade) { } public String getPaymentMethodNameWithCountryCode(Trade trade) { - String paymentMethodDescription = ""; - if (trade != null) { - Offer offer = trade.getOffer(); - checkNotNull(offer); - checkNotNull(offer.getPaymentMethod()); - paymentMethodDescription = offer.getPaymentMethodNameWithCountryCode(); - } - return paymentMethodDescription; + if (trade == null) + return ""; + + Offer offer = trade.getOffer(); + checkNotNull(offer); + checkNotNull(offer.getPaymentMethod()); + return offer.getPaymentMethodNameWithCountryCode(); } /** From 3cd3bf0e3ed3aed626fe38ef1b1da29cbc761c61 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 30 Oct 2020 11:52:37 -0300 Subject: [PATCH 18/20] Fix grammar / typo This change resolves issue found in PR review. See https://github.com/bisq-network/bisq/pull/4703#discussion_r515076872 --- cli/src/main/java/bisq/cli/TableFormat.java | 4 ++-- cli/src/main/java/bisq/cli/TradeFormat.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/src/main/java/bisq/cli/TableFormat.java b/cli/src/main/java/bisq/cli/TableFormat.java index e9868f336e4..8336fff9ba1 100644 --- a/cli/src/main/java/bisq/cli/TableFormat.java +++ b/cli/src/main/java/bisq/cli/TableFormat.java @@ -63,7 +63,7 @@ static String formatAddressBalanceTbl(List addressBalanceInf static String formatOfferTable(List offerInfo, String fiatCurrency) { - // Some column values might be longer than header, so we need to calculated them. + // Some column values might be longer than header, so we need to calculate them. int paymentMethodColWidth = getLengthOfLongestColumn( COL_HEADER_PAYMENT_METHOD.length(), offerInfo.stream() @@ -100,7 +100,7 @@ static String formatOfferTable(List offerInfo, String fiatCurrency) { } static String formatPaymentAcctTbl(List paymentAccounts) { - // Some column values might be longer than header, so we need to calculated them. + // Some column values might be longer than header, so we need to calculate them. int nameColWidth = getLengthOfLongestColumn( COL_HEADER_NAME.length(), paymentAccounts.stream().map(PaymentAccount::getAccountName) diff --git a/cli/src/main/java/bisq/cli/TradeFormat.java b/cli/src/main/java/bisq/cli/TradeFormat.java index ab9075fe341..2a28c1dccc4 100644 --- a/cli/src/main/java/bisq/cli/TradeFormat.java +++ b/cli/src/main/java/bisq/cli/TradeFormat.java @@ -33,7 +33,7 @@ public class TradeFormat { @VisibleForTesting public static String format(TradeInfo tradeInfo) { - // Some column values might be longer than header, so we need to calculated them. + // Some column values might be longer than header, so we need to calculate them. int shortIdColWidth = Math.max(COL_HEADER_TRADE_SHORT_ID.length(), tradeInfo.getShortId().length()); int roleColWidth = Math.max(COL_HEADER_TRADE_ROLE.length(), tradeInfo.getRole().length()); From c27d5a6da87d05a0d1700c174929ad0a9af1b154 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sat, 31 Oct 2020 13:32:14 -0300 Subject: [PATCH 19/20] Use Bisq's timer in API's 'unlockwallet timeout(s)' This change was requested in https://github.com/chimp1984/bisq/commit/961703ecea62df62946ab001ec28205662688ccd This replaces and closes PR https://github.com/bisq-network/bisq/pull/4558 --- .../bisq/core/api/CoreWalletsService.java | 40 ++++++++----------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/bisq/core/api/CoreWalletsService.java b/core/src/main/java/bisq/core/api/CoreWalletsService.java index 29394aad8ac..fc15ec5062a 100644 --- a/core/src/main/java/bisq/core/api/CoreWalletsService.java +++ b/core/src/main/java/bisq/core/api/CoreWalletsService.java @@ -23,6 +23,9 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.btc.wallet.WalletsManager; +import bisq.common.Timer; +import bisq.common.UserThread; + import org.bitcoinj.core.Address; import org.bitcoinj.core.TransactionConfidence; import org.bitcoinj.crypto.KeyCrypterScrypt; @@ -37,8 +40,6 @@ import java.util.List; import java.util.Optional; -import java.util.Timer; -import java.util.TimerTask; import java.util.function.Function; import java.util.stream.Collectors; @@ -57,7 +58,7 @@ class CoreWalletsService { private final BtcWalletService btcWalletService; @Nullable - private TimerTask lockTask; + private Timer lockTimer; @Nullable private KeyParameter tempAesKey; @@ -190,29 +191,22 @@ void unlockWallet(String password, long timeout) { if (!walletsManager.checkAESKey(tempAesKey)) throw new IllegalStateException("incorrect password"); - if (lockTask != null) { - // The user is overriding a prior unlock timeout. Cancel the existing - // lock TimerTask to prevent it from calling lockWallet() before or after the - // new timer task does. - lockTask.cancel(); - // Avoid the synchronized(lock) overhead of an unnecessary lockTask.cancel() - // call the next time 'unlockwallet' is called. - lockTask = null; + if (lockTimer != null) { + // The user has called unlockwallet again, before the prior unlockwallet + // timeout has expired. He's overriding it with a new timeout value. + // Remove the existing lock timer to prevent it from calling lockwallet + // before or after the new one does. + lockTimer.stop(); + lockTimer = null; } - lockTask = new TimerTask() { - @Override - public void run() { - if (tempAesKey != null) { - // Do not try to lock wallet after timeout if the user has already - // done so via 'lockwallet' - log.info("Locking wallet after {} second timeout expired.", timeout); - tempAesKey = null; - } + lockTimer = UserThread.runAfter(() -> { + if (tempAesKey != null) { + // The unlockwallet timeout has expired; re-lock the wallet. + log.info("Locking wallet after {} second timeout expired.", timeout); + tempAesKey = null; } - }; - Timer timer = new Timer("Lock Wallet Timer"); - timer.schedule(lockTask, SECONDS.toMillis(timeout)); + }, timeout, SECONDS); } // Provided for automated wallet protection method testing, despite the From fcdfc687e45d1d613838d7189aa4e8edd41228e2 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sat, 31 Oct 2020 15:44:14 -0300 Subject: [PATCH 20/20] Verify closedTradableManager.getTradableById return value is a Trade instance This change requested at https://github.com/bisq-network/bisq/pull/4711#discussion_r515520278 --- core/src/main/java/bisq/core/api/CoreTradesService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/bisq/core/api/CoreTradesService.java b/core/src/main/java/bisq/core/api/CoreTradesService.java index 1b58334466b..dbc6927f452 100644 --- a/core/src/main/java/bisq/core/api/CoreTradesService.java +++ b/core/src/main/java/bisq/core/api/CoreTradesService.java @@ -21,6 +21,7 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; import bisq.core.offer.takeoffer.TakeOfferModel; +import bisq.core.trade.Tradable; import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.trade.TradeUtil; @@ -199,7 +200,8 @@ private Optional getOpenTrade(String tradeId) { } private Optional getClosedTrade(String tradeId) { - return closedTradableManager.getTradableById(tradeId).map(value -> (Trade) value); + Optional tradable = closedTradableManager.getTradableById(tradeId); + return tradable.filter((t) -> t instanceof Trade).map(value -> (Trade) value); } private boolean isFollowingBuyerProtocol(Trade trade) {