diff --git a/core/src/main/java/io/bitsquare/payment/PaymentMethod.java b/core/src/main/java/io/bitsquare/payment/PaymentMethod.java index 7bee4bbbf6..dd3bb59df5 100644 --- a/core/src/main/java/io/bitsquare/payment/PaymentMethod.java +++ b/core/src/main/java/io/bitsquare/payment/PaymentMethod.java @@ -37,7 +37,7 @@ public final class PaymentMethod implements Persistable, Comparable { protected final Logger log = LoggerFactory.getLogger(this.getClass()); // time in blocks (average 10 min for one block confirmation - private static final long HOUR = 3600; + private static final long HOUR = 3600 * 1000; private static final long DAY = HOUR * 24; public static final String OK_PAY_ID = "OK_PAY"; @@ -89,12 +89,12 @@ public final class PaymentMethod implements Persistable, Comparable { /** * @param id - * @param lockTime lock time when seller release BTC until the payout tx gets valid (bitcoin tx lockTime). Serves as protection - * against charge back risk. If Bank do the charge back quickly the Arbitrator and the seller can push another - * double spend tx to invalidate the time locked payout tx. For the moment we set all to 0 but will have it in - * place when needed. - * @param maxTradePeriod The min. period a trader need to wait until he gets displayed the contact form for opening a dispute. - * @param maxTradeLimit The max. allowed trade amount in Bitcoin for that payment method (depending on charge back risk) + * @param lockTime lock time when seller release BTC until the payout tx gets valid (bitcoin tx lockTime). Serves as protection + * against charge back risk. If Bank do the charge back quickly the Arbitrator and the seller can push another + * double spend tx to invalidate the time locked payout tx. For the moment we set all to 0 but will have it in + * place when needed. + * @param maxTradePeriod The min. period a trader need to wait until he gets displayed the contact form for opening a dispute. + * @param maxTradeLimit The max. allowed trade amount in Bitcoin for that payment method (depending on charge back risk) */ public PaymentMethod(String id, long lockTime, long maxTradePeriod, Coin maxTradeLimit) { this.id = id; diff --git a/core/src/main/java/io/bitsquare/trade/Trade.java b/core/src/main/java/io/bitsquare/trade/Trade.java index 1b80d0c4d9..68849b3836 100644 --- a/core/src/main/java/io/bitsquare/trade/Trade.java +++ b/core/src/main/java/io/bitsquare/trade/Trade.java @@ -160,8 +160,6 @@ public abstract class Trade implements Tradable, Model { private String offererContractSignature; private Transaction payoutTx; private long lockTimeAsBlockHeight; - private int openDisputeTimeAsBlockHeight; - private int checkPaymentTimeAsBlockHeight; private NodeAddress arbitratorNodeAddress; private String takerPaymentAccountId; private String errorMessage; @@ -176,6 +174,7 @@ public abstract class Trade implements Tradable, Model { // Constructor, initialization /////////////////////////////////////////////////////////////////////////////////////////// + // offerer protected Trade(Offer offer, Storage storage) { this.offer = offer; this.storage = storage; @@ -464,22 +463,6 @@ public abstract class Trade implements Tradable, Model { return lockTimeAsBlockHeight; } - public int getOpenDisputeTimeAsBlockHeight() { - return openDisputeTimeAsBlockHeight; - } - - public void setOpenDisputeTimeAsBlockHeight(int openDisputeTimeAsBlockHeight) { - this.openDisputeTimeAsBlockHeight = openDisputeTimeAsBlockHeight; - } - - public int getCheckPaymentTimeAsBlockHeight() { - return checkPaymentTimeAsBlockHeight; - } - - public void setCheckPaymentTimeAsBlockHeight(int checkPaymentTimeAsBlockHeight) { - this.checkPaymentTimeAsBlockHeight = checkPaymentTimeAsBlockHeight; - } - public void setTakerContractSignature(String takerSignature) { this.takerContractSignature = takerSignature; } @@ -633,8 +616,6 @@ public abstract class Trade implements Tradable, Model { "\n\toffererContractSignature.hashCode()='" + (offererContractSignature != null ? offererContractSignature.hashCode() : "") + '\'' + "\n\tpayoutTx=" + payoutTx + "\n\tlockTimeAsBlockHeight=" + lockTimeAsBlockHeight + - "\n\topenDisputeTimeAsBlockHeight=" + openDisputeTimeAsBlockHeight + - "\n\tcheckPaymentTimeAsBlockHeight=" + checkPaymentTimeAsBlockHeight + "\n\tarbitratorNodeAddress=" + arbitratorNodeAddress + "\n\ttakerPaymentAccountId='" + takerPaymentAccountId + '\'' + "\n\terrorMessage='" + errorMessage + '\'' + diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/BuyerAsOffererProtocol.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/BuyerAsOffererProtocol.java index 4362f26c93..d56373e87e 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/BuyerAsOffererProtocol.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/BuyerAsOffererProtocol.java @@ -31,7 +31,6 @@ import io.bitsquare.trade.protocol.trade.messages.TradeMessage; import io.bitsquare.trade.protocol.trade.tasks.buyer.*; import io.bitsquare.trade.protocol.trade.tasks.offerer.*; import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime; -import io.bitsquare.trade.protocol.trade.tasks.shared.InitWaitPeriodForOpenDispute; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -111,7 +110,6 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc LoadTakeOfferFeeTx.class, CreateAndSignContract.class, OffererCreatesAndSignsDepositTxAsBuyer.class, - InitWaitPeriodForOpenDispute.class, SetupDepositBalanceListener.class, SendPublishDepositTxRequest.class ); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java index 700d5231f6..c2768af9a2 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java @@ -28,6 +28,7 @@ import io.bitsquare.common.crypto.PubKeyRing; import io.bitsquare.common.taskrunner.Model; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.P2PService; +import io.bitsquare.payment.PaymentAccount; import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.trade.OffererTrade; import io.bitsquare.trade.Trade; @@ -181,11 +182,14 @@ public class ProcessModel implements Model, Serializable { return tradeMessage; } + @Nullable public PaymentAccountContractData getPaymentAccountContractData(Trade trade) { + PaymentAccount paymentAccount; if (trade instanceof OffererTrade) - return user.getPaymentAccount(offer.getOffererPaymentAccountId()).getContractData(); + paymentAccount = user.getPaymentAccount(offer.getOffererPaymentAccountId()); else - return user.getPaymentAccount(trade.getTakerPaymentAccountId()).getContractData(); + paymentAccount = user.getPaymentAccount(trade.getTakerPaymentAccountId()); + return paymentAccount != null ? paymentAccount.getContractData() : null; } public String getAccountId() { diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/SellerAsOffererProtocol.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/SellerAsOffererProtocol.java index 178fa5d564..d545eb371c 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/SellerAsOffererProtocol.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/SellerAsOffererProtocol.java @@ -29,7 +29,6 @@ import io.bitsquare.trade.protocol.trade.messages.*; import io.bitsquare.trade.protocol.trade.tasks.offerer.*; import io.bitsquare.trade.protocol.trade.tasks.seller.*; import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime; -import io.bitsquare.trade.protocol.trade.tasks.shared.InitWaitPeriodForOpenDispute; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -109,7 +108,6 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt VerifyArbitrationSelection.class, VerifyTakerAccount.class, LoadTakeOfferFeeTx.class, - InitWaitPeriodForOpenDispute.class, CreateAndSignContract.class, OffererCreatesAndSignsDepositTxAsSeller.class, SetupDepositBalanceListener.class, diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java index 633d26ba6d..6c7cf72840 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java @@ -43,8 +43,6 @@ public final class PublishDepositTxRequest extends TradeMessage { public final String offererPayoutAddressString; public final byte[] preparedDepositTx; public final ArrayList offererInputs; - public final int openDisputeTimeAsBlockHeight; - public final int checkPaymentTimeAsBlockHeight; public final byte[] offererTradeWalletPubKey; public PublishDepositTxRequest(String tradeId, @@ -55,9 +53,7 @@ public final class PublishDepositTxRequest extends TradeMessage { String offererContractSignature, String offererPayoutAddressString, byte[] preparedDepositTx, - ArrayList offererInputs, - int openDisputeTimeAsBlockHeight, - int checkPaymentTimeAsBlockHeight) { + ArrayList offererInputs) { super(tradeId); this.offererPaymentAccountContractData = offererPaymentAccountContractData; this.offererAccountId = offererAccountId; @@ -67,8 +63,6 @@ public final class PublishDepositTxRequest extends TradeMessage { this.offererPayoutAddressString = offererPayoutAddressString; this.preparedDepositTx = preparedDepositTx; this.offererInputs = offererInputs; - this.openDisputeTimeAsBlockHeight = openDisputeTimeAsBlockHeight; - this.checkPaymentTimeAsBlockHeight = checkPaymentTimeAsBlockHeight; log.trace("offererPaymentAccount size " + Utilities.serialize(offererPaymentAccountContractData).length); log.trace("offererTradeWalletPubKey size " + offererTradeWalletPubKey.length); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/CreateAndSignContract.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/CreateAndSignContract.java index a07b7e6cb7..ed8fa00cbd 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/CreateAndSignContract.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/CreateAndSignContract.java @@ -47,6 +47,7 @@ public class CreateAndSignContract extends TradeTask { TradingPeer taker = processModel.tradingPeer; PaymentAccountContractData offererPaymentAccountContractData = processModel.getPaymentAccountContractData(trade); + checkNotNull(offererPaymentAccountContractData, "offererPaymentAccountContractData must not be null"); PaymentAccountContractData takerPaymentAccountContractData = taker.getPaymentAccountContractData(); boolean isBuyerOffererAndSellerTaker = trade instanceof BuyerAsOffererTrade; diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SendPublishDepositTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SendPublishDepositTxRequest.java index 3dd0b4668c..24b64dfe65 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SendPublishDepositTxRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SendPublishDepositTxRequest.java @@ -45,9 +45,7 @@ public class SendPublishDepositTxRequest extends TradeTask { trade.getOffererContractSignature(), processModel.getAddressEntry().getAddressString(), processModel.getPreparedDepositTx(), - processModel.getRawTransactionInputs(), - trade.getOpenDisputeTimeAsBlockHeight(), - trade.getCheckPaymentTimeAsBlockHeight() + processModel.getRawTransactionInputs() ); processModel.getP2PService().sendEncryptedDirectMessage( diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/shared/InitWaitPeriodForOpenDispute.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/shared/InitWaitPeriodForOpenDispute.java deleted file mode 100644 index 15b130118c..0000000000 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/shared/InitWaitPeriodForOpenDispute.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of Bitsquare. - * - * Bitsquare 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. - * - * Bitsquare 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 Bitsquare. If not, see . - */ - -package io.bitsquare.trade.protocol.trade.tasks.shared; - -import io.bitsquare.common.taskrunner.TaskRunner; -import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.trade.tasks.TradeTask; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class InitWaitPeriodForOpenDispute extends TradeTask { - private static final Logger log = LoggerFactory.getLogger(InitWaitPeriodForOpenDispute.class); - - public InitWaitPeriodForOpenDispute(TaskRunner taskHandler, Trade trade) { - super(taskHandler, trade); - } - - @Override - protected void run() { - try { - runInterceptHook(); - int openDisputeTimeAsBlockHeight = processModel.getTradeWalletService().getLastBlockSeenHeight() - + trade.getOffer().getPaymentMethod().getMaxTradePeriod(); - trade.setOpenDisputeTimeAsBlockHeight(openDisputeTimeAsBlockHeight); - - int checkPaymentTimeAsBlockHeight = processModel.getTradeWalletService().getLastBlockSeenHeight() - + trade.getOffer().getPaymentMethod().getMaxTradePeriod() / 2; - trade.setCheckPaymentTimeAsBlockHeight(checkPaymentTimeAsBlockHeight); - - complete(); - } catch (Throwable t) { - failed(t); - } - } -} diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java index 76bb422257..816f31d1d3 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java @@ -66,7 +66,7 @@ public class ProcessPublishDepositTxRequest extends TradeTask { processModel.tradingPeer.setRawTransactionInputs(checkNotNull(publishDepositTxRequest.offererInputs)); processModel.setPreparedDepositTx(checkNotNull(publishDepositTxRequest.preparedDepositTx)); checkArgument(publishDepositTxRequest.offererInputs.size() > 0); - if (publishDepositTxRequest.openDisputeTimeAsBlockHeight != 0) { + /*if (publishDepositTxRequest.openDisputeTimeAsBlockHeight != 0) { trade.setOpenDisputeTimeAsBlockHeight(publishDepositTxRequest.openDisputeTimeAsBlockHeight); } else { failed("waitPeriodForOpenDisputeAsBlockHeight = 0"); @@ -76,7 +76,7 @@ public class ProcessPublishDepositTxRequest extends TradeTask { trade.setCheckPaymentTimeAsBlockHeight(publishDepositTxRequest.checkPaymentTimeAsBlockHeight); } else { failed("notificationTimeAsBlockHeight = 0"); - } + }*/ // update to the latest peer address of our peer if the message is correct trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); diff --git a/core/src/main/java/io/bitsquare/user/User.java b/core/src/main/java/io/bitsquare/user/User.java index b6f2f97fc5..a7c86c0c52 100644 --- a/core/src/main/java/io/bitsquare/user/User.java +++ b/core/src/main/java/io/bitsquare/user/User.java @@ -201,6 +201,7 @@ public final class User implements Persistable { // Getters /////////////////////////////////////////////////////////////////////////////////////////// + @Nullable public PaymentAccount getPaymentAccount(String paymentAccountId) { Optional optional = paymentAccounts.stream().filter(e -> e.getId().equals(paymentAccountId)).findAny(); if (optional.isPresent()) diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java index 736e5966d5..0e39139788 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java @@ -76,7 +76,7 @@ import static io.bitsquare.app.BitsquareEnvironment.APP_NAME_KEY; public class BitsquareApp extends Application { private static final Logger log = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(BitsquareApp.class); - public static final boolean DEV_MODE = false; + public static final boolean DEV_MODE = true; public static final boolean IS_RELEASE_VERSION = !DEV_MODE && true; private static Environment env; diff --git a/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/PaymentMethodForm.java b/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/PaymentMethodForm.java index 5c16942c8e..292b18ecf8 100644 --- a/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/PaymentMethodForm.java +++ b/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/PaymentMethodForm.java @@ -108,23 +108,12 @@ public abstract class PaymentMethodForm { public static void addAllowedPeriod(GridPane gridPane, int gridRow, @Nullable PaymentAccountContractData paymentAccountContractData, String dateFromBlocks) { if (paymentAccountContractData != null) { - long hours = paymentAccountContractData.getMaxTradePeriod() / 3600; - String displayText; - if (hours == 1) - displayText = hours + " hour"; - else - displayText = hours + " hours"; - if (hours == 24) - displayText = "1 day"; - if (hours > 24) - displayText = hours / 24 + " days"; - - addLabelTextField(gridPane, gridRow, "Max. allowed trade period / date:", displayText + " / " + dateFromBlocks); + long hours = paymentAccountContractData.getMaxTradePeriod() / 3600_000; + addLabelTextField(gridPane, gridRow, "Max. allowed trade period / date:", getTimeText(hours) + " / " + dateFromBlocks); } } - protected void addAllowedPeriod() { - long hours = paymentAccount.getPaymentMethod().getMaxTradePeriod() / 6; + protected static String getTimeText(long hours) { String time = hours + " hours"; if (hours == 1) time = "1 hour"; @@ -133,7 +122,12 @@ public abstract class PaymentMethodForm { else if (hours > 24) time = hours / 24 + " days"; - String displayText = "Max. trade duration: " + time + " / Max. trade limit: " + + return time; + } + + protected void addAllowedPeriod() { + long hours = paymentAccount.getPaymentMethod().getMaxTradePeriod() / 3600_000; + String displayText = "Max. trade duration: " + getTimeText(hours) + " / Max. trade limit: " + formatter.formatCoinWithCode(paymentAccount.getPaymentMethod().getMaxTradeLimit()); addLabelTextField(gridPane, ++gridRow, "Limitations:", displayText); diff --git a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java index 93b3a38511..d469c348fd 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java @@ -66,7 +66,8 @@ import io.bitsquare.user.Preferences; import io.bitsquare.user.User; import javafx.beans.property.*; import javafx.collections.ListChangeListener; -import org.bitcoinj.core.*; +import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Transaction; import org.bitcoinj.store.BlockStoreException; import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.Subscription; @@ -75,10 +76,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; @@ -529,75 +527,66 @@ public class MainViewModel implements ViewModel { private void applyTradePeriodState() { updateTradePeriodState(); - tradeWalletService.addBlockChainListener(new BlockChainListener() { + clock.addListener(new Clock.Listener() { @Override - public void notifyNewBestBlock(StoredBlock block) throws VerificationException { + public void onSecondTick() { updateTradePeriodState(); } @Override - public void reorganize(StoredBlock splitPoint, List oldBlocks, List newBlocks) - throws VerificationException { + public void onMinuteTick() { + updateTradePeriodState(); } @Override - public boolean isTransactionRelevant(Transaction tx) throws ScriptException { - return false; - } - - @Override - public void receiveFromBlock(Transaction tx, StoredBlock block, AbstractBlockChain.NewBlockType blockType, int relativityOffset) - throws VerificationException { - - } - - @Override - public boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, AbstractBlockChain.NewBlockType blockType, - int relativityOffset) throws VerificationException { - return false; + public void onMissedSecondTick(long missed) { } }); } private void updateTradePeriodState() { tradeManager.getTrades().stream().forEach(trade -> { - int bestChainHeight = tradeWalletService.getBestChainHeight(); + if (trade.getState().getPhase().ordinal() < Trade.Phase.PAYOUT_PAID.ordinal()) { + long maxTradePeriod = trade.getOffer().getPaymentMethod().getMaxTradePeriod(); + Date maxTradePeriodDate = new Date(trade.getDate().getTime() + maxTradePeriod); + Date halfTradePeriodDate = new Date(trade.getDate().getTime() + maxTradePeriod / 2); + Date now = new Date(); - if (trade.getOpenDisputeTimeAsBlockHeight() > 0 && bestChainHeight >= trade.getOpenDisputeTimeAsBlockHeight()) - trade.setTradePeriodState(Trade.TradePeriodState.TRADE_PERIOD_OVER); - else if (trade.getCheckPaymentTimeAsBlockHeight() > 0 && bestChainHeight >= trade.getCheckPaymentTimeAsBlockHeight()) - trade.setTradePeriodState(Trade.TradePeriodState.HALF_REACHED); + if (now.after(maxTradePeriodDate)) + trade.setTradePeriodState(Trade.TradePeriodState.TRADE_PERIOD_OVER); + else if (now.after(halfTradePeriodDate)) + trade.setTradePeriodState(Trade.TradePeriodState.HALF_REACHED); - String key; - String limitDate = formatter.addBlocksToNowDateFormatted(trade.getOpenDisputeTimeAsBlockHeight() - tradeWalletService.getBestChainHeight()); - switch (trade.getTradePeriodState()) { - case NORMAL: - break; - case HALF_REACHED: - key = "displayHalfTradePeriodOver" + trade.getId(); - if (preferences.showAgain(key)) { - preferences.dontShowAgain(key, true); - new Popup().warning("Your trade with ID " + trade.getShortId() + - " has reached the half of the max. allowed trading period and " + - "is still not completed.\n\n" + - "The trade period ends on " + limitDate + "\n\n" + - "Please check your trade state at \"Portfolio/Open trades\" for further information.") - .show(); - } - break; - case TRADE_PERIOD_OVER: - key = "displayTradePeriodOver" + trade.getId(); - if (preferences.showAgain(key)) { - preferences.dontShowAgain(key, true); - new Popup().warning("Your trade with ID " + trade.getShortId() + - " has reached the max. allowed trading period and is " + - "not completed.\n\n" + - "The trade period ended on " + limitDate + "\n\n" + - "Please check your trade at \"Portfolio/Open trades\" for contacting " + - "the arbitrator.") - .show(); - } - break; + String key; + switch (trade.getTradePeriodState()) { + case NORMAL: + break; + case HALF_REACHED: + key = "displayHalfTradePeriodOver" + trade.getId(); + if (preferences.showAgain(key)) { + preferences.dontShowAgain(key, true); + new Popup().warning("Your trade with ID " + trade.getShortId() + + " has reached the half of the max. allowed trading period and " + + "is still not completed.\n\n" + + "The trade period ends on " + formatter.formatDateTime(maxTradePeriodDate) + "\n\n" + + "Please check your trade state at \"Portfolio/Open trades\" for further information.") + .show(); + } + break; + case TRADE_PERIOD_OVER: + key = "displayTradePeriodOver" + trade.getId(); + if (preferences.showAgain(key)) { + preferences.dontShowAgain(key, true); + new Popup().warning("Your trade with ID " + trade.getShortId() + + " has reached the max. allowed trading period and is " + + "not completed.\n\n" + + "The trade period ended on " + formatter.formatDateTime(maxTradePeriodDate) + "\n\n" + + "Please check your trade at \"Portfolio/Open trades\" for contacting " + + "the arbitrator.") + .show(); + } + break; + } } }); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java b/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java index 7cd0242523..abb9e781d9 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java @@ -18,7 +18,6 @@ package io.bitsquare.gui.main.account.arbitratorregistration; -import io.bitsquare.app.BitsquareApp; import io.bitsquare.arbitration.Arbitrator; import io.bitsquare.common.UserThread; import io.bitsquare.common.util.Tuple2; @@ -131,9 +130,6 @@ public class ArbitratorRegistrationView extends ActivatableViewAndModel tuple = addLabelListView(gridPane, ++gridRow, "Your languages:"); diff --git a/gui/src/main/java/io/bitsquare/gui/main/debug/DebugView.java b/gui/src/main/java/io/bitsquare/gui/main/debug/DebugView.java index bed1c609c5..c43c716791 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/debug/DebugView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/debug/DebugView.java @@ -36,7 +36,6 @@ import io.bitsquare.trade.protocol.trade.tasks.buyer.*; import io.bitsquare.trade.protocol.trade.tasks.offerer.*; import io.bitsquare.trade.protocol.trade.tasks.seller.*; import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime; -import io.bitsquare.trade.protocol.trade.tasks.shared.InitWaitPeriodForOpenDispute; import io.bitsquare.trade.protocol.trade.tasks.taker.*; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -85,7 +84,6 @@ public class DebugView extends InitializableView { CreateAndSignContract.class, OffererCreatesAndSignsDepositTxAsBuyer.class, LoadTakeOfferFeeTx.class, - InitWaitPeriodForOpenDispute.class, SetupDepositBalanceListener.class, SendPublishDepositTxRequest.class, @@ -157,7 +155,6 @@ public class DebugView extends InitializableView { ProcessPayDepositRequest.class, VerifyArbitrationSelection.class, VerifyTakerAccount.class, - InitWaitPeriodForOpenDispute.class, CreateAndSignContract.class, OffererCreatesAndSignsDepositTxAsBuyer.class, SetupDepositBalanceListener.class, diff --git a/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java b/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java index 43c3f2888e..6c9b5ac9c1 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java @@ -145,6 +145,7 @@ public class TraderDisputeView extends ActivatableView { tableView.setPlaceholder(placeholder); tableView.getSelectionModel().clearSelection(); + tableView.getColumns().add(getSelectColumn()); TableColumn tradeIdColumn = getTradeIdColumn(); tableView.getColumns().add(tradeIdColumn); TableColumn roleColumn = getRoleColumn(); @@ -714,6 +715,49 @@ public class TraderDisputeView extends ActivatableView { // Table /////////////////////////////////////////////////////////////////////////////////////////// + private TableColumn getSelectColumn() { + TableColumn column = new TableColumn("Select") { + { + setMinWidth(110); + setMaxWidth(110); + } + }; + column.setCellValueFactory((addressListItem) -> + new ReadOnlyObjectWrapper<>(addressListItem.getValue())); + column.setCellFactory( + new Callback, TableCell>() { + + @Override + public TableCell call(TableColumn column) { + return new TableCell() { + + Button button; + + @Override + public void updateItem(final Dispute item, boolean empty) { + super.updateItem(item, empty); + if (item != null && !empty) { + if (button == null) { + button = new Button("Select"); + button.setOnAction(e -> tableView.getSelectionModel().select(item)); + setGraphic(button); + } + } else { + setGraphic(null); + if (button != null) { + button.setOnAction(null); + button = null; + } + } + } + }; + } + }); + return column; + } + private TableColumn getTradeIdColumn() { TableColumn column = new TableColumn("Trade ID") { { diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java index 1989cb4bc7..1973e303ac 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java @@ -804,7 +804,7 @@ public class CreateOfferView extends ActivatableViewAndModel model.fundFromSavingsWallet()); Label label = new Label("OR"); label.setPadding(new Insets(5, 0, 0, 0)); - fundFromExternalWalletButton = new Button("Pay in funds from external wallet"); + fundFromExternalWalletButton = new Button("Open your external wallet for funding"); fundFromExternalWalletButton.setDefaultButton(false); fundFromExternalWalletButton.setOnAction(e -> { try { diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java index dbef5b0bb2..28c4a77805 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java @@ -727,7 +727,7 @@ public class TakeOfferView extends ActivatableViewAndModel model.fundFromSavingsWallet()); Label label = new Label("OR"); label.setPadding(new Insets(5, 0, 0, 0)); - fundFromExternalWalletButton = new Button("Pay in funds from external wallet"); + fundFromExternalWalletButton = new Button("Open your external wallet for funding"); fundFromExternalWalletButton.setDefaultButton(false); fundFromExternalWalletButton.setOnAction(e -> { try { diff --git a/gui/src/main/java/io/bitsquare/gui/main/overlays/windows/EnterPrivKeyWindow.java b/gui/src/main/java/io/bitsquare/gui/main/overlays/windows/EnterPrivKeyWindow.java index 1b95ac3c05..db605cfb1f 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/overlays/windows/EnterPrivKeyWindow.java +++ b/gui/src/main/java/io/bitsquare/gui/main/overlays/windows/EnterPrivKeyWindow.java @@ -17,7 +17,6 @@ package io.bitsquare.gui.main.overlays.windows; -import io.bitsquare.app.BitsquareApp; import io.bitsquare.gui.components.InputTextField; import io.bitsquare.gui.main.overlays.Overlay; import io.bitsquare.gui.main.overlays.popups.Popup; @@ -94,8 +93,6 @@ public class EnterPrivKeyWindow extends Overlay { GridPane.setRowIndex(label, ++rowIndex); keyInputTextField = new InputTextField(); - if (BitsquareApp.DEV_MODE) - keyInputTextField.setText("6ac43ea1df2a290c1c8391736aa42e4339c5cb4f110ff0257a13b63211977b7a"); GridPane.setMargin(keyInputTextField, new Insets(3, 0, 0, 0)); GridPane.setRowIndex(keyInputTextField, rowIndex); GridPane.setColumnIndex(keyInputTextField, 1); diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java index 4f86acfc05..7214577e5a 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -220,10 +220,6 @@ public class PendingTradesDataModel extends ActivatableDataModel { return getTrade() != null ? getTrade().getLockTimeAsBlockHeight() : 0; } - public long getOpenDisputeTimeAsBlockHeight() { - return getTrade() != null ? getTrade().getOpenDisputeTimeAsBlockHeight() : 0; - } - public int getBestChainHeight() { return tradeWalletService.getBestChainHeight(); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.fxml b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.fxml index 2da9860fc3..d99ef5296a 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.fxml @@ -28,6 +28,7 @@ + diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java index 6c85ae632e..c2ec3176ca 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java @@ -52,7 +52,7 @@ public class PendingTradesView extends ActivatableViewAndModel tableView; @FXML - TableColumn priceColumn, tradeVolumeColumn, tradeAmountColumn, avatarColumn, roleColumn, paymentMethodColumn, idColumn, dateColumn; + TableColumn selectColumn, priceColumn, tradeVolumeColumn, tradeAmountColumn, avatarColumn, roleColumn, paymentMethodColumn, idColumn, dateColumn; @FXML private SortedList sortedList; @@ -77,6 +77,7 @@ public class PendingTradesView extends ActivatableViewAndModel new ReadOnlyObjectWrapper<>(pendingTradesListItem.getValue())); + selectColumn.setCellFactory( + new Callback, TableCell>() { + + @Override + public TableCell call(TableColumn column) { + return new TableCell() { + Button button; + + @Override + public void updateItem(final PendingTradesListItem item, boolean empty) { + super.updateItem(item, empty); + if (item != null && !empty) { + if (button == null) { + button = new Button("Select"); + button.setOnAction(e -> tableView.getSelectionModel().select(item)); + setGraphic(button); + } + } else { + setGraphic(null); + if (button != null) { + button.setOnAction(null); + button = null; + } + } + } + }; + } + }); + } + private void setTradeIdColumnCellFactory() { idColumn.setCellValueFactory((pendingTradesListItem) -> new ReadOnlyObjectWrapper<>(pendingTradesListItem.getValue())); idColumn.setCellFactory( diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesViewModel.java index ca9dfa1c10..dbb264256b 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesViewModel.java @@ -39,6 +39,7 @@ import org.bitcoinj.core.BlockChainListener; import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.Subscription; +import java.util.Date; import java.util.stream.Collectors; import static io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel.SellerState.*; @@ -148,36 +149,60 @@ public class PendingTradesViewModel extends ActivatableWithDataModel= trade.getCheckPaymentTimeAsBlockHeight(); + public String getDateForOpenDispute() { + return formatter.formatDateTime(new Date(new Date().getTime() + getRemainingTradeDuration())); } - public boolean showDispute(Trade trade) { - return getBestChainHeight() >= trade.getOpenDisputeTimeAsBlockHeight(); + public boolean showWarning() { + return new Date().after(getDateWhenHalfPeriodReached()); } + public boolean showDispute() { + return new Date().after(getDateWhenDisputeOpens()); + } + + // + String getMyRole(PendingTradesListItem item) { Trade trade = item.getTrade(); Contract contract = trade.getContract(); @@ -214,22 +239,10 @@ public class PendingTradesViewModel extends ActivatableWithDataModel