mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-20 07:46:05 -04:00
Changed trade period to time based instead of block based
This commit is contained in:
parent
86405a4b88
commit
a78163c735
@ -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;
|
||||
|
@ -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<? extends TradableList> 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 + '\'' +
|
||||
|
@ -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
|
||||
);
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
|
@ -43,8 +43,6 @@ public final class PublishDepositTxRequest extends TradeMessage {
|
||||
public final String offererPayoutAddressString;
|
||||
public final byte[] preparedDepositTx;
|
||||
public final ArrayList<RawTransactionInput> 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<RawTransactionInput> offererInputs,
|
||||
int openDisputeTimeAsBlockHeight,
|
||||
int checkPaymentTimeAsBlockHeight) {
|
||||
ArrayList<RawTransactionInput> 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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
|
@ -201,6 +201,7 @@ public final class User implements Persistable {
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Nullable
|
||||
public PaymentAccount getPaymentAccount(String paymentAccountId) {
|
||||
Optional<PaymentAccount> optional = paymentAccounts.stream().filter(e -> e.getId().equals(paymentAccountId)).findAny();
|
||||
if (optional.isPresent())
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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<StoredBlock> oldBlocks, List<StoredBlock> 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;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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<VBox, Ar
|
||||
pubKeyTextField = FormBuilder.addLabelTextField(gridPane, gridRow, "Public key:",
|
||||
model.registrationPubKeyAsHex.get(), Layout.FIRST_ROW_DISTANCE).second;
|
||||
|
||||
if (BitsquareApp.DEV_MODE)
|
||||
pubKeyTextField.setText("6ac43ea1df2a290c1c8391736aa42e4339c5cb4f110ff0257a13b63211977b7a");
|
||||
|
||||
pubKeyTextField.textProperty().bind(model.registrationPubKeyAsHex);
|
||||
|
||||
Tuple2<Label, ListView> tuple = addLabelListView(gridPane, ++gridRow, "Your languages:");
|
||||
|
@ -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,
|
||||
|
@ -145,6 +145,7 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||
tableView.setPlaceholder(placeholder);
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
|
||||
tableView.getColumns().add(getSelectColumn());
|
||||
TableColumn<Dispute, Dispute> tradeIdColumn = getTradeIdColumn();
|
||||
tableView.getColumns().add(tradeIdColumn);
|
||||
TableColumn<Dispute, Dispute> roleColumn = getRoleColumn();
|
||||
@ -714,6 +715,49 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||
// Table
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private TableColumn<Dispute, Dispute> getSelectColumn() {
|
||||
TableColumn<Dispute, Dispute> column = new TableColumn<Dispute, Dispute>("Select") {
|
||||
{
|
||||
setMinWidth(110);
|
||||
setMaxWidth(110);
|
||||
}
|
||||
};
|
||||
column.setCellValueFactory((addressListItem) ->
|
||||
new ReadOnlyObjectWrapper<>(addressListItem.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<Dispute, Dispute>, TableCell<Dispute,
|
||||
Dispute>>() {
|
||||
|
||||
@Override
|
||||
public TableCell<Dispute, Dispute> call(TableColumn<Dispute,
|
||||
Dispute> column) {
|
||||
return new TableCell<Dispute, Dispute>() {
|
||||
|
||||
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<Dispute, Dispute> getTradeIdColumn() {
|
||||
TableColumn<Dispute, Dispute> column = new TableColumn<Dispute, Dispute>("Trade ID") {
|
||||
{
|
||||
|
@ -804,7 +804,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
fundFromSavingsWalletButton.setOnAction(e -> 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 {
|
||||
|
@ -727,7 +727,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
fundFromSavingsWalletButton.setOnAction(e -> 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 {
|
||||
|
@ -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<EnterPrivKeyWindow> {
|
||||
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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
<TableView fx:id="tableView" VBox.vgrow="SOMETIMES">
|
||||
<columns>
|
||||
<TableColumn text="Select" fx:id="selectColumn" minWidth="70" maxWidth="70" sortable="false"/>
|
||||
<TableColumn text="Trade ID" fx:id="idColumn" minWidth="100"/>
|
||||
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="130"/>
|
||||
<TableColumn text="Trade amount in BTC" fx:id="tradeAmountColumn" minWidth="130"/>
|
||||
|
@ -52,7 +52,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||
@FXML
|
||||
TableView<PendingTradesListItem> tableView;
|
||||
@FXML
|
||||
TableColumn<PendingTradesListItem, PendingTradesListItem> priceColumn, tradeVolumeColumn, tradeAmountColumn, avatarColumn, roleColumn, paymentMethodColumn, idColumn, dateColumn;
|
||||
TableColumn<PendingTradesListItem, PendingTradesListItem> selectColumn, priceColumn, tradeVolumeColumn, tradeAmountColumn, avatarColumn, roleColumn, paymentMethodColumn, idColumn, dateColumn;
|
||||
@FXML
|
||||
|
||||
private SortedList<PendingTradesListItem> sortedList;
|
||||
@ -77,6 +77,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
setSelectColumnCellFactory();
|
||||
setTradeIdColumnCellFactory();
|
||||
setDateColumnCellFactory();
|
||||
setAmountColumnCellFactory();
|
||||
@ -228,6 +229,39 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||
// CellFactories
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void setSelectColumnCellFactory() {
|
||||
selectColumn.setCellValueFactory((pendingTradesListItem) -> new ReadOnlyObjectWrapper<>(pendingTradesListItem.getValue()));
|
||||
selectColumn.setCellFactory(
|
||||
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem, PendingTradesListItem>>() {
|
||||
|
||||
@Override
|
||||
public TableCell<PendingTradesListItem, PendingTradesListItem> call(TableColumn<PendingTradesListItem,
|
||||
PendingTradesListItem> column) {
|
||||
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
|
||||
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(
|
||||
|
@ -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<PendingTrad
|
||||
return dataModel.getTrade() != null ? formatter.formatCoinWithCode(dataModel.getTrade().getPayoutAmount()) : "";
|
||||
}
|
||||
|
||||
// columns
|
||||
public String getRemainingTime() {
|
||||
if (dataModel.getTrade() != null)
|
||||
return formatter.getPeriodBetweenBlockHeights(getBestChainHeight(),
|
||||
dataModel.getTrade().getOpenDisputeTimeAsBlockHeight());
|
||||
else
|
||||
return "";
|
||||
// trade period
|
||||
|
||||
private long getMaxTradePeriod() {
|
||||
return dataModel.getOffer() != null ? dataModel.getOffer().getPaymentMethod().getMaxTradePeriod() : 0;
|
||||
}
|
||||
|
||||
public double getRemainingTimeAsPercentage() {
|
||||
if (dataModel.getTrade() != null && dataModel.getOffer() != null) {
|
||||
double remainingBlocks = dataModel.getTrade().getOpenDisputeTimeAsBlockHeight() - getBestChainHeight();
|
||||
double maxPeriod = dataModel.getOffer().getPaymentMethod().getMaxTradePeriod();
|
||||
if (maxPeriod != 0)
|
||||
return 1 - remainingBlocks / maxPeriod;
|
||||
else
|
||||
return 0;
|
||||
} else {
|
||||
private long getTimeWhenDisputeOpens() {
|
||||
return dataModel.getTrade() != null ? dataModel.getTrade().getDate().getTime() + getMaxTradePeriod() : 0;
|
||||
}
|
||||
|
||||
private long getTimeWhenHalfPeriodReached() {
|
||||
return dataModel.getTrade() != null ? dataModel.getTrade().getDate().getTime() + getMaxTradePeriod() / 2 : 0;
|
||||
}
|
||||
|
||||
private Date getDateWhenDisputeOpens() {
|
||||
return new Date(getTimeWhenDisputeOpens());
|
||||
}
|
||||
|
||||
private Date getDateWhenHalfPeriodReached() {
|
||||
return new Date(getTimeWhenHalfPeriodReached());
|
||||
}
|
||||
|
||||
private long getRemainingTradeDuration() {
|
||||
return getDateWhenDisputeOpens().getTime() - new Date().getTime();
|
||||
}
|
||||
|
||||
public String getRemainingTradeDurationAsWords() {
|
||||
return formatter.getDurationAsWords(Math.max(0, getRemainingTradeDuration()));
|
||||
}
|
||||
|
||||
public double getRemainingTradeDurationAsPercentage() {
|
||||
long maxPeriod = getMaxTradePeriod();
|
||||
long remaining = getRemainingTradeDuration();
|
||||
if (maxPeriod != 0) {
|
||||
double v = 1 - (double) remaining / (double) maxPeriod;
|
||||
return v;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean showWarning(Trade trade) {
|
||||
return getBestChainHeight() >= 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<PendingTrad
|
||||
return dataModel.getLockTime();
|
||||
}
|
||||
|
||||
private long getOpenDisputeTimeAsBlockHeight() {
|
||||
return dataModel.getOpenDisputeTimeAsBlockHeight();
|
||||
}
|
||||
|
||||
public int getBestChainHeight() {
|
||||
return dataModel.getBestChainHeight();
|
||||
}
|
||||
|
||||
public String getOpenDisputeTimeAsFormattedDate() {
|
||||
if (dataModel.getOffer() != null)
|
||||
return formatter.addBlocksToNowDateFormatted(getOpenDisputeTimeAsBlockHeight() - getBestChainHeight() +
|
||||
(dataModel.getOffer().getPaymentMethod().getLockTime()));
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getPaymentMethod() {
|
||||
if (dataModel.getTrade() != null && dataModel.getTrade().getContract() != null)
|
||||
return BSResources.get(dataModel.getTrade().getContract().getPaymentMethodName());
|
||||
|
@ -113,6 +113,7 @@ public abstract class TradeStepView extends AnchorPane {
|
||||
clockListener = new Clock.Listener() {
|
||||
@Override
|
||||
public void onSecondTick() {
|
||||
updateTimeLeft();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -165,7 +166,7 @@ public abstract class TradeStepView extends AnchorPane {
|
||||
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
|
||||
|
||||
PaymentMethodForm.addAllowedPeriod(gridPane, ++gridRow, model.dataModel.getSellersPaymentAccountContractData(),
|
||||
model.getOpenDisputeTimeAsFormattedDate());
|
||||
model.getDateForOpenDispute());
|
||||
|
||||
timeLeftTextField = addLabelTextField(gridPane, ++gridRow, "Remaining time:").second;
|
||||
|
||||
@ -198,16 +199,16 @@ public abstract class TradeStepView extends AnchorPane {
|
||||
|
||||
private void updateTimeLeft() {
|
||||
if (timeLeftTextField != null) {
|
||||
String remainingTime = model.getRemainingTime();
|
||||
timeLeftProgressBar.setProgress(model.getRemainingTimeAsPercentage());
|
||||
String remainingTime = model.getRemainingTradeDurationAsWords();
|
||||
timeLeftProgressBar.setProgress(model.getRemainingTradeDurationAsPercentage());
|
||||
if (remainingTime != null) {
|
||||
timeLeftTextField.setText(remainingTime);
|
||||
if (model.showWarning(trade) || model.showDispute(trade)) {
|
||||
if (model.showWarning() || model.showDispute()) {
|
||||
timeLeftTextField.setStyle("-fx-text-fill: -bs-error-red");
|
||||
timeLeftProgressBar.setStyle("-fx-accent: -bs-error-red;");
|
||||
}
|
||||
} else {
|
||||
timeLeftTextField.setText("Trade not completed in time (" + model.getOpenDisputeTimeAsFormattedDate() + ")");
|
||||
timeLeftTextField.setText("Trade not completed in time (" + model.getDateForOpenDispute() + ")");
|
||||
timeLeftTextField.setStyle("-fx-text-fill: -bs-error-red");
|
||||
timeLeftProgressBar.setStyle("-fx-accent: -bs-error-red;");
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ public class BuyerStep2View extends TradeStepView {
|
||||
setWarningHeadline();
|
||||
return "You still have not done your " + model.dataModel.getCurrencyCode() + " payment!\n" +
|
||||
"Please note that the trade has to be completed until " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
model.getDateForOpenDispute() +
|
||||
" otherwise the trade will be investigated by the arbitrator.";
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ public class BuyerStep3View extends TradeStepView {
|
||||
return "The seller still has not confirmed your payment!\n" +
|
||||
"Please check " + substitute + " if the payment sending was successful.\n" +
|
||||
"If the seller does not confirm the receipt of your payment until " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
model.getDateForOpenDispute() +
|
||||
" the trade will be investigated by the arbitrator.";
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ public class BuyerStep4View extends TradeStepView {
|
||||
setInformationHeadline();
|
||||
return "The payout transaction is still blocked by the lock time!\n" +
|
||||
"If the trade has not been completed on " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
model.getDateForOpenDispute() +
|
||||
" the arbitrator will investigate.";
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ public class BuyerStep4View extends TradeStepView {
|
||||
long missingBlocks = model.getLockTime() - bestBlocKHeight;
|
||||
|
||||
blockTextField.setText(String.valueOf(missingBlocks));
|
||||
timeTextField.setText(model.getOpenDisputeTimeAsFormattedDate());
|
||||
timeTextField.setText(model.getDateForOpenDispute());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ public class SellerStep2View extends TradeStepView {
|
||||
return "The buyer still has not done the " + model.dataModel.getCurrencyCode() + " payment.\n" +
|
||||
"You need to wait until he starts the payment.\n" +
|
||||
"If the trade has not been completed on " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
model.getDateForOpenDispute() +
|
||||
" the arbitrator will investigate.";
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,7 @@ public class SellerStep3View extends TradeStepView {
|
||||
return "You still have not confirmed the receipt of the payment!\n" +
|
||||
"Please check " + substitute + " if you have received the payment.\n" +
|
||||
"If you do not confirm receipt until " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
model.getDateForOpenDispute() +
|
||||
" the trade will be investigated by the arbitrator.";
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ public class SellerStep3bView extends TradeStepView {
|
||||
return "The trading peer has not finalized the payout transaction!\n" +
|
||||
"He might be offline. You need to wait until he finalizes the payout transaction.\n" +
|
||||
"If the trade has not been completed on " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
model.getDateForOpenDispute() +
|
||||
" the arbitrator will investigate.";
|
||||
}
|
||||
|
||||
|
@ -356,15 +356,8 @@ public class BSFormatter {
|
||||
return new Date(new Date().getTime() + blocks * TimeUnit.MINUTES.toMillis(10));
|
||||
}
|
||||
|
||||
public String addBlocksToNowDateFormatted(long blocks) {
|
||||
DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
|
||||
DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, locale);
|
||||
Date date = addBlocksToNowDate(blocks);
|
||||
return dateFormatter.format(date) + " " + timeFormatter.format(date);
|
||||
}
|
||||
|
||||
public String getPeriodBetweenBlockHeights(long startBlockHeight, long endBlockHeight) {
|
||||
return getDaysHoursMinutes(addBlocksToNowDate(startBlockHeight), addBlocksToNowDate(endBlockHeight));
|
||||
public String getDurationAsWords(long duration) {
|
||||
return DurationFormatUtils.formatDurationWords(duration, true, true);
|
||||
}
|
||||
|
||||
public String getDaysHoursMinutes(Date startDate, Date endDate) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user