mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-21 14:18:50 -04:00
impl. feedback from aaron. improve popups, add warning for remove offer, deactivate mainnet,...
This commit is contained in:
parent
2950f6e347
commit
f9a31f4b8a
37 changed files with 425 additions and 281 deletions
|
@ -150,7 +150,7 @@ public class CountryUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getNamesByCodesString(List<String> countryCodes) {
|
public static String getNamesByCodesString(List<String> countryCodes) {
|
||||||
return getNamesByCodes(countryCodes).stream().collect(Collectors.joining(", "));
|
return getNamesByCodes(countryCodes).stream().collect(Collectors.joining(",\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String[] countryCodes = new String[]{"AE", "AL", "AR", "AT", "AU", "BA", "BE", "BG", "BH",
|
private static final String[] countryCodes = new String[]{"AE", "AL", "AR", "AT", "AU", "BA", "BE", "BG", "BH",
|
||||||
|
|
|
@ -37,11 +37,14 @@ public class SepaAccountContractData extends PaymentAccountContractData implemen
|
||||||
private String holderName;
|
private String holderName;
|
||||||
private String iban;
|
private String iban;
|
||||||
private String bic;
|
private String bic;
|
||||||
private Set<String> acceptedCountryCodes;
|
// Dont use a set here as we need a deterministic ordering, otherwise the contract hash does not match
|
||||||
|
private ArrayList<String> acceptedCountryCodes;
|
||||||
|
|
||||||
public SepaAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
|
public SepaAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
|
||||||
super(paymentMethod, id, maxTradePeriod);
|
super(paymentMethod, id, maxTradePeriod);
|
||||||
acceptedCountryCodes = CountryUtil.getAllSepaCountries().stream().map(e -> e.code).collect(Collectors.toSet());
|
Set<String> acceptedCountryCodesAsSet = CountryUtil.getAllSepaCountries().stream().map(e -> e.code).collect(Collectors.toSet());
|
||||||
|
acceptedCountryCodes = new ArrayList<>(acceptedCountryCodesAsSet);
|
||||||
|
acceptedCountryCodes.sort((a, b) -> a.compareTo(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHolderName(String holderName) {
|
public void setHolderName(String holderName) {
|
||||||
|
@ -69,17 +72,17 @@ public class SepaAccountContractData extends PaymentAccountContractData implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAcceptedCountry(String countryCode) {
|
public void addAcceptedCountry(String countryCode) {
|
||||||
|
if (!acceptedCountryCodes.contains(countryCode))
|
||||||
acceptedCountryCodes.add(countryCode);
|
acceptedCountryCodes.add(countryCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAcceptedCountry(String countryCode) {
|
public void removeAcceptedCountry(String countryCode) {
|
||||||
|
if (acceptedCountryCodes.contains(countryCode))
|
||||||
acceptedCountryCodes.remove(countryCode);
|
acceptedCountryCodes.remove(countryCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAcceptedCountryCodes() {
|
public List<String> getAcceptedCountryCodes() {
|
||||||
List<String> sortedList = new ArrayList<>(acceptedCountryCodes);
|
return acceptedCountryCodes;
|
||||||
sortedList.sort((a, b) -> a.compareTo(b));
|
|
||||||
return sortedList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -38,11 +38,13 @@ public class Contract implements Serializable {
|
||||||
@JsonExclude
|
@JsonExclude
|
||||||
public static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
public static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
|
public static final String TAC = "I commit to the trade conditions as defined above.";
|
||||||
|
|
||||||
public final Offer offer;
|
public final Offer offer;
|
||||||
private final long tradeAmount;
|
private final long tradeAmount;
|
||||||
public final String takeOfferFeeTxID;
|
public final String takeOfferFeeTxID;
|
||||||
public final Address arbitratorAddress;
|
public final Address arbitratorAddress;
|
||||||
private final boolean isBuyerOffererOrSellerTaker;
|
private final boolean isBuyerOffererAndSellerTaker;
|
||||||
private final String offererAccountId;
|
private final String offererAccountId;
|
||||||
private final String takerAccountId;
|
private final String takerAccountId;
|
||||||
private final PaymentAccountContractData offererPaymentAccountContractData;
|
private final PaymentAccountContractData offererPaymentAccountContractData;
|
||||||
|
@ -62,17 +64,13 @@ public class Contract implements Serializable {
|
||||||
@JsonExclude
|
@JsonExclude
|
||||||
private final byte[] takerBtcPubKey;
|
private final byte[] takerBtcPubKey;
|
||||||
|
|
||||||
// TODO some basic TAC
|
|
||||||
public final String tac = "With my signature I commit to the trading agreement of Bitsquare and to fulfill the trade as defined there.";
|
|
||||||
|
|
||||||
|
|
||||||
public Contract(Offer offer,
|
public Contract(Offer offer,
|
||||||
Coin tradeAmount,
|
Coin tradeAmount,
|
||||||
String takeOfferFeeTxID,
|
String takeOfferFeeTxID,
|
||||||
Address buyerAddress,
|
Address buyerAddress,
|
||||||
Address sellerAddress,
|
Address sellerAddress,
|
||||||
Address arbitratorAddress,
|
Address arbitratorAddress,
|
||||||
boolean isBuyerOffererOrSellerTaker,
|
boolean isBuyerOffererAndSellerTaker,
|
||||||
String offererAccountId,
|
String offererAccountId,
|
||||||
String takerAccountId,
|
String takerAccountId,
|
||||||
PaymentAccountContractData offererPaymentAccountContractData,
|
PaymentAccountContractData offererPaymentAccountContractData,
|
||||||
|
@ -89,7 +87,7 @@ public class Contract implements Serializable {
|
||||||
this.tradeAmount = tradeAmount.value;
|
this.tradeAmount = tradeAmount.value;
|
||||||
this.takeOfferFeeTxID = takeOfferFeeTxID;
|
this.takeOfferFeeTxID = takeOfferFeeTxID;
|
||||||
this.arbitratorAddress = arbitratorAddress;
|
this.arbitratorAddress = arbitratorAddress;
|
||||||
this.isBuyerOffererOrSellerTaker = isBuyerOffererOrSellerTaker;
|
this.isBuyerOffererAndSellerTaker = isBuyerOffererAndSellerTaker;
|
||||||
this.offererAccountId = offererAccountId;
|
this.offererAccountId = offererAccountId;
|
||||||
this.takerAccountId = takerAccountId;
|
this.takerAccountId = takerAccountId;
|
||||||
this.offererPaymentAccountContractData = offererPaymentAccountContractData;
|
this.offererPaymentAccountContractData = offererPaymentAccountContractData;
|
||||||
|
@ -103,44 +101,44 @@ public class Contract implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBuyerAccountId() {
|
public String getBuyerAccountId() {
|
||||||
return isBuyerOffererOrSellerTaker ? offererAccountId : takerAccountId;
|
return isBuyerOffererAndSellerTaker ? offererAccountId : takerAccountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSellerAccountId() {
|
public String getSellerAccountId() {
|
||||||
return isBuyerOffererOrSellerTaker ? takerAccountId : offererAccountId;
|
return isBuyerOffererAndSellerTaker ? takerAccountId : offererAccountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getBuyerPayoutAddressString() {
|
public String getBuyerPayoutAddressString() {
|
||||||
return isBuyerOffererOrSellerTaker ? offererPayoutAddressString : takerPayoutAddressString;
|
return isBuyerOffererAndSellerTaker ? offererPayoutAddressString : takerPayoutAddressString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSellerPayoutAddressString() {
|
public String getSellerPayoutAddressString() {
|
||||||
return isBuyerOffererOrSellerTaker ? takerPayoutAddressString : offererPayoutAddressString;
|
return isBuyerOffererAndSellerTaker ? takerPayoutAddressString : offererPayoutAddressString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PubKeyRing getBuyerPubKeyRing() {
|
public PubKeyRing getBuyerPubKeyRing() {
|
||||||
return isBuyerOffererOrSellerTaker ? offererPubKeyRing : takerPubKeyRing;
|
return isBuyerOffererAndSellerTaker ? offererPubKeyRing : takerPubKeyRing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PubKeyRing getSellerPubKeyRing() {
|
public PubKeyRing getSellerPubKeyRing() {
|
||||||
return isBuyerOffererOrSellerTaker ? takerPubKeyRing : offererPubKeyRing;
|
return isBuyerOffererAndSellerTaker ? takerPubKeyRing : offererPubKeyRing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBuyerBtcPubKey() {
|
public byte[] getBuyerBtcPubKey() {
|
||||||
return isBuyerOffererOrSellerTaker ? offererBtcPubKey : takerBtcPubKey;
|
return isBuyerOffererAndSellerTaker ? offererBtcPubKey : takerBtcPubKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getSellerBtcPubKey() {
|
public byte[] getSellerBtcPubKey() {
|
||||||
return isBuyerOffererOrSellerTaker ? takerBtcPubKey : offererBtcPubKey;
|
return isBuyerOffererAndSellerTaker ? takerBtcPubKey : offererBtcPubKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PaymentAccountContractData getBuyerPaymentAccountContractData() {
|
public PaymentAccountContractData getBuyerPaymentAccountContractData() {
|
||||||
return isBuyerOffererOrSellerTaker ? offererPaymentAccountContractData : takerPaymentAccountContractData;
|
return isBuyerOffererAndSellerTaker ? offererPaymentAccountContractData : takerPaymentAccountContractData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PaymentAccountContractData getSellerPaymentAccountContractData() {
|
public PaymentAccountContractData getSellerPaymentAccountContractData() {
|
||||||
return isBuyerOffererOrSellerTaker ? takerPaymentAccountContractData : offererPaymentAccountContractData;
|
return isBuyerOffererAndSellerTaker ? takerPaymentAccountContractData : offererPaymentAccountContractData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPaymentMethodName() {
|
public String getPaymentMethodName() {
|
||||||
|
@ -166,17 +164,19 @@ public class Contract implements Serializable {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Contract{" +
|
return "Contract{" +
|
||||||
"tac='" + tac + '\'' +
|
"offer=" + offer +
|
||||||
", offer=" + offer +
|
|
||||||
", tradeAmount=" + tradeAmount +
|
", tradeAmount=" + tradeAmount +
|
||||||
", isBuyerOffererOrSellerTaker=" + isBuyerOffererOrSellerTaker +
|
|
||||||
", takeOfferFeeTxID='" + takeOfferFeeTxID + '\'' +
|
", takeOfferFeeTxID='" + takeOfferFeeTxID + '\'' +
|
||||||
", offererAccountID='" + offererAccountId + '\'' +
|
", arbitratorAddress=" + arbitratorAddress +
|
||||||
", takerAccountID='" + takerAccountId + '\'' +
|
", isBuyerOffererAndSellerTaker=" + isBuyerOffererAndSellerTaker +
|
||||||
", offererPaymentAccount=" + offererPaymentAccountContractData +
|
", offererAccountId='" + offererAccountId + '\'' +
|
||||||
", takerPaymentAccount=" + takerPaymentAccountContractData +
|
", takerAccountId='" + takerAccountId + '\'' +
|
||||||
|
", offererPaymentAccountContractData=" + offererPaymentAccountContractData +
|
||||||
|
", takerPaymentAccountContractData=" + takerPaymentAccountContractData +
|
||||||
", offererPubKeyRing=" + offererPubKeyRing +
|
", offererPubKeyRing=" + offererPubKeyRing +
|
||||||
", takerPubKeyRing=" + takerPubKeyRing +
|
", takerPubKeyRing=" + takerPubKeyRing +
|
||||||
|
", buyerAddress=" + buyerAddress +
|
||||||
|
", sellerAddress=" + sellerAddress +
|
||||||
", offererPayoutAddressString='" + offererPayoutAddressString + '\'' +
|
", offererPayoutAddressString='" + offererPayoutAddressString + '\'' +
|
||||||
", takerPayoutAddressString='" + takerPayoutAddressString + '\'' +
|
", takerPayoutAddressString='" + takerPayoutAddressString + '\'' +
|
||||||
", offererBtcPubKey=" + Arrays.toString(offererBtcPubKey) +
|
", offererBtcPubKey=" + Arrays.toString(offererBtcPubKey) +
|
||||||
|
@ -192,7 +192,7 @@ public class Contract implements Serializable {
|
||||||
Contract contract = (Contract) o;
|
Contract contract = (Contract) o;
|
||||||
|
|
||||||
if (tradeAmount != contract.tradeAmount) return false;
|
if (tradeAmount != contract.tradeAmount) return false;
|
||||||
if (isBuyerOffererOrSellerTaker != contract.isBuyerOffererOrSellerTaker) return false;
|
if (isBuyerOffererAndSellerTaker != contract.isBuyerOffererAndSellerTaker) return false;
|
||||||
if (offer != null ? !offer.equals(contract.offer) : contract.offer != null) return false;
|
if (offer != null ? !offer.equals(contract.offer) : contract.offer != null) return false;
|
||||||
if (takeOfferFeeTxID != null ? !takeOfferFeeTxID.equals(contract.takeOfferFeeTxID) : contract.takeOfferFeeTxID != null)
|
if (takeOfferFeeTxID != null ? !takeOfferFeeTxID.equals(contract.takeOfferFeeTxID) : contract.takeOfferFeeTxID != null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -219,8 +219,7 @@ public class Contract implements Serializable {
|
||||||
if (takerPayoutAddressString != null ? !takerPayoutAddressString.equals(contract.takerPayoutAddressString) : contract.takerPayoutAddressString != null)
|
if (takerPayoutAddressString != null ? !takerPayoutAddressString.equals(contract.takerPayoutAddressString) : contract.takerPayoutAddressString != null)
|
||||||
return false;
|
return false;
|
||||||
if (!Arrays.equals(offererBtcPubKey, contract.offererBtcPubKey)) return false;
|
if (!Arrays.equals(offererBtcPubKey, contract.offererBtcPubKey)) return false;
|
||||||
if (!Arrays.equals(takerBtcPubKey, contract.takerBtcPubKey)) return false;
|
return Arrays.equals(takerBtcPubKey, contract.takerBtcPubKey);
|
||||||
return !(tac != null ? !tac.equals(contract.tac) : contract.tac != null);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +229,7 @@ public class Contract implements Serializable {
|
||||||
result = 31 * result + (int) (tradeAmount ^ (tradeAmount >>> 32));
|
result = 31 * result + (int) (tradeAmount ^ (tradeAmount >>> 32));
|
||||||
result = 31 * result + (takeOfferFeeTxID != null ? takeOfferFeeTxID.hashCode() : 0);
|
result = 31 * result + (takeOfferFeeTxID != null ? takeOfferFeeTxID.hashCode() : 0);
|
||||||
result = 31 * result + (arbitratorAddress != null ? arbitratorAddress.hashCode() : 0);
|
result = 31 * result + (arbitratorAddress != null ? arbitratorAddress.hashCode() : 0);
|
||||||
result = 31 * result + (isBuyerOffererOrSellerTaker ? 1 : 0);
|
result = 31 * result + (isBuyerOffererAndSellerTaker ? 1 : 0);
|
||||||
result = 31 * result + (offererAccountId != null ? offererAccountId.hashCode() : 0);
|
result = 31 * result + (offererAccountId != null ? offererAccountId.hashCode() : 0);
|
||||||
result = 31 * result + (takerAccountId != null ? takerAccountId.hashCode() : 0);
|
result = 31 * result + (takerAccountId != null ? takerAccountId.hashCode() : 0);
|
||||||
result = 31 * result + (offererPaymentAccountContractData != null ? offererPaymentAccountContractData.hashCode() : 0);
|
result = 31 * result + (offererPaymentAccountContractData != null ? offererPaymentAccountContractData.hashCode() : 0);
|
||||||
|
@ -243,7 +242,7 @@ public class Contract implements Serializable {
|
||||||
result = 31 * result + (takerPayoutAddressString != null ? takerPayoutAddressString.hashCode() : 0);
|
result = 31 * result + (takerPayoutAddressString != null ? takerPayoutAddressString.hashCode() : 0);
|
||||||
result = 31 * result + (offererBtcPubKey != null ? Arrays.hashCode(offererBtcPubKey) : 0);
|
result = 31 * result + (offererBtcPubKey != null ? Arrays.hashCode(offererBtcPubKey) : 0);
|
||||||
result = 31 * result + (takerBtcPubKey != null ? Arrays.hashCode(takerBtcPubKey) : 0);
|
result = 31 * result + (takerBtcPubKey != null ? Arrays.hashCode(takerBtcPubKey) : 0);
|
||||||
result = 31 * result + (tac != null ? tac.hashCode() : 0);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,10 @@ public final class Offer implements PubKeyProtectedExpirablePayload {
|
||||||
transient private static final Logger log = LoggerFactory.getLogger(Offer.class);
|
transient private static final Logger log = LoggerFactory.getLogger(Offer.class);
|
||||||
|
|
||||||
public static final long TTL = 10 * 60 * 1000; // 10 min.
|
public static final long TTL = 10 * 60 * 1000; // 10 min.
|
||||||
|
public final static String TAC_OFFERER = "When placing that offer I accept that anyone who fulfills my conditions can " +
|
||||||
|
"take that offer.";
|
||||||
|
public static final String TAC_TAKER = "With taking the offer I commit to the trade conditions as defined.";
|
||||||
|
|
||||||
|
|
||||||
public enum Direction {BUY, SELL}
|
public enum Direction {BUY, SELL}
|
||||||
|
|
||||||
|
@ -397,14 +401,21 @@ public final class Offer implements PubKeyProtectedExpirablePayload {
|
||||||
", fiatPrice=" + fiatPrice +
|
", fiatPrice=" + fiatPrice +
|
||||||
", amount=" + amount +
|
", amount=" + amount +
|
||||||
", minAmount=" + minAmount +
|
", minAmount=" + minAmount +
|
||||||
", address=" + offererAddress +
|
", offererAddress=" + offererAddress +
|
||||||
", pubKeyRing.hashCode()=" + pubKeyRing.hashCode() +
|
", pubKeyRing=" + pubKeyRing +
|
||||||
", paymentMethodName='" + paymentMethodName + '\'' +
|
", paymentMethodName='" + paymentMethodName + '\'' +
|
||||||
", paymentMethodCountryCode='" + paymentMethodCountryCode + '\'' +
|
", paymentMethodCountryCode='" + paymentMethodCountryCode + '\'' +
|
||||||
", offererPaymentAccountId='" + offererPaymentAccountId + '\'' +
|
", offererPaymentAccountId='" + offererPaymentAccountId + '\'' +
|
||||||
", acceptedCountryCodes=" + acceptedCountryCodes +
|
", acceptedCountryCodes=" + acceptedCountryCodes +
|
||||||
", arbitratorAddresses=" + arbitratorAddresses +
|
", arbitratorAddresses=" + arbitratorAddresses +
|
||||||
", offerFeePaymentTxID='" + offerFeePaymentTxID + '\'' +
|
", offerFeePaymentTxID='" + offerFeePaymentTxID + '\'' +
|
||||||
|
", state=" + state +
|
||||||
|
", stateProperty=" + stateProperty +
|
||||||
|
", availabilityProtocol=" + availabilityProtocol +
|
||||||
|
", errorMessageProperty=" + errorMessageProperty +
|
||||||
|
", TAC_OFFERER=" + TAC_OFFERER +
|
||||||
|
", TAC_TAKER=" + TAC_TAKER +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,10 +41,11 @@ public class SignAndPublishDepositTxAsBuyer extends TradeTask {
|
||||||
try {
|
try {
|
||||||
runInterceptHook();
|
runInterceptHook();
|
||||||
|
|
||||||
log.debug("getContractAsJson");
|
log.info("\n\n------------------------------------------------------------\n"
|
||||||
log.debug("----------");
|
+ "Contract as json\n"
|
||||||
log.debug(trade.getContractAsJson());
|
+ trade.getContractAsJson()
|
||||||
log.debug("----------");
|
+ "\n------------------------------------------------------------\n");
|
||||||
|
|
||||||
|
|
||||||
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
|
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
|
||||||
trade.setContractHash(contractHash);
|
trade.setContractHash(contractHash);
|
||||||
|
|
|
@ -48,11 +48,11 @@ public class CreateAndSignContract extends TradeTask {
|
||||||
TradingPeer taker = processModel.tradingPeer;
|
TradingPeer taker = processModel.tradingPeer;
|
||||||
PaymentAccountContractData offererPaymentAccountContractData = processModel.getPaymentAccountContractData(trade);
|
PaymentAccountContractData offererPaymentAccountContractData = processModel.getPaymentAccountContractData(trade);
|
||||||
PaymentAccountContractData takerPaymentAccountContractData = taker.getPaymentAccountContractData();
|
PaymentAccountContractData takerPaymentAccountContractData = taker.getPaymentAccountContractData();
|
||||||
boolean isBuyerOffererOrSellerTaker = trade instanceof BuyerAsOffererTrade;
|
boolean isBuyerOffererAndSellerTaker = trade instanceof BuyerAsOffererTrade;
|
||||||
|
|
||||||
Address buyerAddress = isBuyerOffererOrSellerTaker ? processModel.getMyAddress() : processModel.getTempTradingPeerAddress();
|
Address buyerAddress = isBuyerOffererAndSellerTaker ? processModel.getMyAddress() : processModel.getTempTradingPeerAddress();
|
||||||
Address sellerAddress = isBuyerOffererOrSellerTaker ? processModel.getTempTradingPeerAddress() : processModel.getMyAddress();
|
Address sellerAddress = isBuyerOffererAndSellerTaker ? processModel.getTempTradingPeerAddress() : processModel.getMyAddress();
|
||||||
log.debug("isBuyerOffererOrSellerTaker " + isBuyerOffererOrSellerTaker);
|
log.debug("isBuyerOffererAndSellerTaker " + isBuyerOffererAndSellerTaker);
|
||||||
log.debug("buyerAddress " + buyerAddress);
|
log.debug("buyerAddress " + buyerAddress);
|
||||||
log.debug("sellerAddress " + sellerAddress);
|
log.debug("sellerAddress " + sellerAddress);
|
||||||
Contract contract = new Contract(
|
Contract contract = new Contract(
|
||||||
|
@ -62,7 +62,7 @@ public class CreateAndSignContract extends TradeTask {
|
||||||
buyerAddress,
|
buyerAddress,
|
||||||
sellerAddress,
|
sellerAddress,
|
||||||
trade.getArbitratorAddress(),
|
trade.getArbitratorAddress(),
|
||||||
isBuyerOffererOrSellerTaker,
|
isBuyerOffererAndSellerTaker,
|
||||||
processModel.getAccountId(),
|
processModel.getAccountId(),
|
||||||
taker.getAccountId(),
|
taker.getAccountId(),
|
||||||
offererPaymentAccountContractData,
|
offererPaymentAccountContractData,
|
||||||
|
|
|
@ -44,6 +44,11 @@ public class CreateAndSignDepositTxAsSeller extends TradeTask {
|
||||||
Coin sellerInputAmount = FeePolicy.SECURITY_DEPOSIT.add(FeePolicy.TX_FEE).add(trade.getTradeAmount());
|
Coin sellerInputAmount = FeePolicy.SECURITY_DEPOSIT.add(FeePolicy.TX_FEE).add(trade.getTradeAmount());
|
||||||
Coin msOutputAmount = sellerInputAmount.add(FeePolicy.SECURITY_DEPOSIT);
|
Coin msOutputAmount = sellerInputAmount.add(FeePolicy.SECURITY_DEPOSIT);
|
||||||
|
|
||||||
|
log.info("\n\n------------------------------------------------------------\n"
|
||||||
|
+ "Contract as json\n"
|
||||||
|
+ trade.getContractAsJson()
|
||||||
|
+ "\n------------------------------------------------------------\n");
|
||||||
|
|
||||||
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
|
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
|
||||||
trade.setContractHash(contractHash);
|
trade.setContractHash(contractHash);
|
||||||
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(
|
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(
|
||||||
|
|
|
@ -40,10 +40,10 @@ public class SignAndPublishDepositTxAsSeller extends TradeTask {
|
||||||
protected void run() {
|
protected void run() {
|
||||||
try {
|
try {
|
||||||
runInterceptHook();
|
runInterceptHook();
|
||||||
log.debug("getContractAsJson");
|
log.info("\n\n------------------------------------------------------------\n"
|
||||||
log.debug("----------");
|
+ "Contract as json\n"
|
||||||
log.debug(trade.getContractAsJson());
|
+ trade.getContractAsJson()
|
||||||
log.debug("----------");
|
+ "\n------------------------------------------------------------\n");
|
||||||
|
|
||||||
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
|
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
|
||||||
trade.setContractHash(contractHash);
|
trade.setContractHash(contractHash);
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class BroadcastTakeOfferFeeTx extends TradeTask {
|
||||||
new FutureCallback<Transaction>() {
|
new FutureCallback<Transaction>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Transaction transaction) {
|
public void onSuccess(Transaction transaction) {
|
||||||
log.debug("Take offer fee published successfully. Transaction ID = " + transaction.getHashAsString());
|
log.debug("Trading fee published successfully. Transaction ID = " + transaction.getHashAsString());
|
||||||
|
|
||||||
trade.setState(Trade.State.TAKER_FEE_PAID);
|
trade.setState(Trade.State.TAKER_FEE_PAID);
|
||||||
complete();
|
complete();
|
||||||
|
@ -49,7 +49,7 @@ public class BroadcastTakeOfferFeeTx extends TradeTask {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(@NotNull Throwable t) {
|
public void onFailure(@NotNull Throwable t) {
|
||||||
appendToErrorMessage("Take offer fee payment failed. Maybe your network connection was lost. Please try again.");
|
appendToErrorMessage("Trading fee payment failed. Maybe your network connection was lost. Please try again.");
|
||||||
failed(t);
|
failed(t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -47,10 +47,10 @@ public class VerifyAndSignContract extends TradeTask {
|
||||||
PaymentAccountContractData offererPaymentAccountContractData = offerer.getPaymentAccountContractData();
|
PaymentAccountContractData offererPaymentAccountContractData = offerer.getPaymentAccountContractData();
|
||||||
PaymentAccountContractData takerPaymentAccountContractData = processModel.getPaymentAccountContractData(trade);
|
PaymentAccountContractData takerPaymentAccountContractData = processModel.getPaymentAccountContractData(trade);
|
||||||
|
|
||||||
boolean isBuyerOffererOrSellerTaker = trade instanceof SellerAsTakerTrade;
|
boolean isBuyerOffererAndSellerTaker = trade instanceof SellerAsTakerTrade;
|
||||||
Address buyerAddress = isBuyerOffererOrSellerTaker ? processModel.getTempTradingPeerAddress() : processModel.getMyAddress();
|
Address buyerAddress = isBuyerOffererAndSellerTaker ? processModel.getTempTradingPeerAddress() : processModel.getMyAddress();
|
||||||
Address sellerAddress = isBuyerOffererOrSellerTaker ? processModel.getMyAddress() : processModel.getTempTradingPeerAddress();
|
Address sellerAddress = isBuyerOffererAndSellerTaker ? processModel.getMyAddress() : processModel.getTempTradingPeerAddress();
|
||||||
log.debug("isBuyerOffererOrSellerTaker " + isBuyerOffererOrSellerTaker);
|
log.debug("isBuyerOffererAndSellerTaker " + isBuyerOffererAndSellerTaker);
|
||||||
log.debug("buyerAddress " + buyerAddress);
|
log.debug("buyerAddress " + buyerAddress);
|
||||||
log.debug("sellerAddress " + sellerAddress);
|
log.debug("sellerAddress " + sellerAddress);
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public class VerifyAndSignContract extends TradeTask {
|
||||||
buyerAddress,
|
buyerAddress,
|
||||||
sellerAddress,
|
sellerAddress,
|
||||||
trade.getArbitratorAddress(),
|
trade.getArbitratorAddress(),
|
||||||
isBuyerOffererOrSellerTaker,
|
isBuyerOffererAndSellerTaker,
|
||||||
offerer.getAccountId(),
|
offerer.getAccountId(),
|
||||||
processModel.getAccountId(),
|
processModel.getAccountId(),
|
||||||
offererPaymentAccountContractData,
|
offererPaymentAccountContractData,
|
||||||
|
|
|
@ -67,7 +67,6 @@ public class User implements Serializable {
|
||||||
private Alert displayedAlert;
|
private Alert displayedAlert;
|
||||||
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private List<Arbitrator> acceptedArbitrators = new ArrayList<>();
|
private List<Arbitrator> acceptedArbitrators = new ArrayList<>();
|
||||||
@Nullable
|
@Nullable
|
||||||
private Arbitrator registeredArbitrator;
|
private Arbitrator registeredArbitrator;
|
||||||
|
@ -244,7 +243,6 @@ public class User implements Serializable {
|
||||||
return registeredArbitrator;
|
return registeredArbitrator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public List<Arbitrator> getAcceptedArbitrators() {
|
public List<Arbitrator> getAcceptedArbitrators() {
|
||||||
return acceptedArbitrators;
|
return acceptedArbitrators;
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,7 @@ public class BitsquareApp extends Application {
|
||||||
showFPSWindow();
|
showFPSWindow();
|
||||||
else if (new KeyCodeCombination(KeyCode.E, KeyCombination.SHORTCUT_DOWN).match(keyEvent))
|
else if (new KeyCodeCombination(KeyCode.E, KeyCombination.SHORTCUT_DOWN).match(keyEvent))
|
||||||
showEmptyWalletPopup();
|
showEmptyWalletPopup();
|
||||||
else if (new KeyCodeCombination(KeyCode.A, KeyCombination.SHORTCUT_DOWN).match(keyEvent))
|
else if (new KeyCodeCombination(KeyCode.M, KeyCombination.SHORTCUT_DOWN).match(keyEvent))
|
||||||
showSendAlertMessagePopup();
|
showSendAlertMessagePopup();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -326,6 +326,7 @@ public class BitsquareApp extends Application {
|
||||||
|
|
||||||
private void restart() {
|
private void restart() {
|
||||||
//TODO
|
//TODO
|
||||||
|
stop();
|
||||||
//gracefulShutDown(UpdateFX::restartApp);
|
//gracefulShutDown(UpdateFX::restartApp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.bitcoinj.core.Coin;
|
||||||
public class BalanceTextField extends AnchorPane {
|
public class BalanceTextField extends AnchorPane {
|
||||||
|
|
||||||
private static WalletService walletService;
|
private static WalletService walletService;
|
||||||
|
private BalanceListener balanceListener;
|
||||||
|
|
||||||
public static void setWalletService(WalletService walletService) {
|
public static void setWalletService(WalletService walletService) {
|
||||||
BalanceTextField.walletService = walletService;
|
BalanceTextField.walletService = walletService;
|
||||||
|
@ -61,15 +62,20 @@ public class BalanceTextField extends AnchorPane {
|
||||||
public void setup(Address address, BSFormatter formatter) {
|
public void setup(Address address, BSFormatter formatter) {
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
|
|
||||||
walletService.addBalanceListener(new BalanceListener(address) {
|
balanceListener = new BalanceListener(address) {
|
||||||
@Override
|
@Override
|
||||||
public void onBalanceChanged(Coin balance) {
|
public void onBalanceChanged(Coin balance) {
|
||||||
updateBalance(balance);
|
updateBalance(balance);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
walletService.addBalanceListener(balanceListener);
|
||||||
updateBalance(walletService.getBalanceForAddress(address));
|
updateBalance(walletService.getBalanceForAddress(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void disarm() {
|
||||||
|
walletService.removeBalanceListener(balanceListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Private methods
|
// Private methods
|
||||||
|
|
|
@ -111,12 +111,16 @@ public abstract class PaymentMethodForm {
|
||||||
protected void addAllowedPeriod() {
|
protected void addAllowedPeriod() {
|
||||||
long hours = paymentAccount.getPaymentMethod().getMaxTradePeriod() / 6;
|
long hours = paymentAccount.getPaymentMethod().getMaxTradePeriod() / 6;
|
||||||
String displayText = hours + " hours";
|
String displayText = hours + " hours";
|
||||||
if (hours == 24)
|
if (hours == 1)
|
||||||
|
displayText = "1 hour";
|
||||||
|
else if (hours == 24)
|
||||||
displayText = "1 day";
|
displayText = "1 day";
|
||||||
if (hours > 24)
|
else if (hours > 24)
|
||||||
displayText = hours / 24 + " days";
|
displayText = hours / 24 + " days";
|
||||||
|
|
||||||
addLabelTextField(gridPane, ++gridRow, "Max. allowed trade period:", displayText);
|
displayText += " (Max. permitted period until the trade needs to be completed)";
|
||||||
|
|
||||||
|
addLabelTextField(gridPane, ++gridRow, "Max. permitted trade period:", displayText);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected void autoFillNameTextField();
|
abstract protected void autoFillNameTextField();
|
||||||
|
|
|
@ -202,10 +202,16 @@ public class SeedWordsView extends ActivatableView<GridPane, Void> {
|
||||||
log.debug("Wallet restored with seed words");
|
log.debug("Wallet restored with seed words");
|
||||||
|
|
||||||
new Popup()
|
new Popup()
|
||||||
|
.information("Wallet restored successfully with the new seed words.\n\n" +
|
||||||
|
"You need to shut down and restart the application.")
|
||||||
|
.closeButtonText("Shut down")
|
||||||
|
.onClose(() -> BitsquareApp.shutDownHandler.run()).show();
|
||||||
|
//TODO
|
||||||
|
/* new Popup()
|
||||||
.information("Wallet restored successfully with the new seed words.\n\n" +
|
.information("Wallet restored successfully with the new seed words.\n\n" +
|
||||||
"You need to restart now the application.")
|
"You need to restart now the application.")
|
||||||
.closeButtonText("Restart")
|
.closeButtonText("Restart")
|
||||||
.onClose(() -> BitsquareApp.restartDownHandler.run()).show();
|
.onClose(() -> BitsquareApp.restartDownHandler.run()).show();*/
|
||||||
}),
|
}),
|
||||||
throwable -> UserThread.execute(() -> {
|
throwable -> UserThread.execute(() -> {
|
||||||
log.error(throwable.getMessage());
|
log.error(throwable.getMessage());
|
||||||
|
|
|
@ -37,7 +37,6 @@ import io.bitsquare.gui.main.account.settings.AccountSettingsView;
|
||||||
import io.bitsquare.gui.main.offer.OfferView;
|
import io.bitsquare.gui.main.offer.OfferView;
|
||||||
import io.bitsquare.gui.main.portfolio.PortfolioView;
|
import io.bitsquare.gui.main.portfolio.PortfolioView;
|
||||||
import io.bitsquare.gui.main.portfolio.openoffer.OpenOffersView;
|
import io.bitsquare.gui.main.portfolio.openoffer.OpenOffersView;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesView;
|
|
||||||
import io.bitsquare.gui.popups.OfferDetailsPopup;
|
import io.bitsquare.gui.popups.OfferDetailsPopup;
|
||||||
import io.bitsquare.gui.popups.Popup;
|
import io.bitsquare.gui.popups.Popup;
|
||||||
import io.bitsquare.gui.util.BSFormatter;
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
|
@ -226,9 +225,13 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
private void onShowFundsScreen() {
|
private void onShowFundsScreen() {
|
||||||
if (!BitsquareApp.DEV_MODE) {
|
if (!BitsquareApp.DEV_MODE) {
|
||||||
if (model.getDisplaySecurityDepositInfo()) {
|
if (model.getDisplaySecurityDepositInfo()) {
|
||||||
new Popup().information("To ensure that both traders behave fair they need to pay a security deposit.\n\n" +
|
new Popup().information("To ensure that both traders follow the trade protocol they need to pay a security deposit.\n\n" +
|
||||||
"The deposit will stay in your local trading wallet until the offer gets accepted by another trader.\n" +
|
"The deposit will stay in your local trading wallet until the offer gets accepted by another trader.\n" +
|
||||||
"It will be refunded to you after the trade has successfully completed.").show();
|
"It will be refunded to you after the trade has successfully completed.\n\n" +
|
||||||
|
"You need to pay in the exact amount displayed to you from your external Bitcoin wallet into the " +
|
||||||
|
"Bitsquare trade wallet. The amount is the sum of the security deposit, the trading fee and " +
|
||||||
|
"the Bitcoin mining fee.\n" +
|
||||||
|
"You can see the details when you move the mouse over the question mark.").show();
|
||||||
|
|
||||||
model.onSecurityDepositInfoDisplayed();
|
model.onSecurityDepositInfoDisplayed();
|
||||||
}
|
}
|
||||||
|
@ -435,12 +438,16 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
UserThread.runAfter(() -> {
|
UserThread.runAfter(() -> {
|
||||||
new Popup().headLine(BSResources.get("createOffer.success.headline"))
|
new Popup().headLine(BSResources.get("createOffer.success.headline"))
|
||||||
.message(BSResources.get("createOffer.success.info"))
|
.message(BSResources.get("createOffer.success.info"))
|
||||||
.onClose(() -> {
|
.actionButtonText("Go to \"Open offers\"")
|
||||||
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
|
.onAction(() -> {
|
||||||
close();
|
close();
|
||||||
|
UserThread.runAfter(() ->
|
||||||
|
navigation.navigateTo(MainView.class, PortfolioView.class, OpenOffersView.class),
|
||||||
|
100, TimeUnit.MILLISECONDS);
|
||||||
})
|
})
|
||||||
|
.onClose(() -> close())
|
||||||
.show();
|
.show();
|
||||||
}, 300, TimeUnit.MILLISECONDS);
|
}, 100, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,7 +289,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
if (newValue != null) {
|
if (newValue != null) {
|
||||||
if (offer.getState() == Offer.State.OFFER_FEE_PAID)
|
if (offer.getState() == Offer.State.OFFER_FEE_PAID)
|
||||||
this.errorMessage.set(newValue +
|
this.errorMessage.set(newValue +
|
||||||
"\n\nThe create offer fee is already paid. In the worst case you have lost that fee. " +
|
"\n\nThe offer fee is already paid. In the worst case you have lost that fee. " +
|
||||||
"We are sorry about that but keep in mind it is a very small amount.\n" +
|
"We are sorry about that but keep in mind it is a very small amount.\n" +
|
||||||
"Please try to restart you application and check your network connection to see if you can resolve the issue.");
|
"Please try to restart you application and check your network connection to see if you can resolve the issue.");
|
||||||
else
|
else
|
||||||
|
|
|
@ -239,6 +239,19 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
|
|
||||||
private void onRemoveOpenOffer(Offer offer) {
|
private void onRemoveOpenOffer(Offer offer) {
|
||||||
if (model.isAuthenticated()) {
|
if (model.isAuthenticated()) {
|
||||||
|
new Popup().warning("Are you sure you want to remove that offer?\n" +
|
||||||
|
"The offer fee you have paid will be lost if you remove that offer.")
|
||||||
|
.actionButtonText("Remove offer")
|
||||||
|
.onAction(() -> doRemoveOffer(offer))
|
||||||
|
.closeButtonText("Don't remove the offer")
|
||||||
|
.show();
|
||||||
|
} else {
|
||||||
|
new Popup().warning("You need to wait until your client is authenticated in the network.\n" +
|
||||||
|
"That might take up to about 2 minutes at startup.").show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doRemoveOffer(Offer offer) {
|
||||||
model.onRemoveOpenOffer(offer,
|
model.onRemoveOpenOffer(offer,
|
||||||
() -> {
|
() -> {
|
||||||
log.debug("Remove offer was successful");
|
log.debug("Remove offer was successful");
|
||||||
|
@ -249,11 +262,6 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
log.error(message);
|
log.error(message);
|
||||||
new Popup().warning("Remove offer failed:\n" + message).show();
|
new Popup().warning("Remove offer failed:\n" + message).show();
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
|
||||||
new Popup().warning("You need to wait until your client is authenticated in the network.\n" +
|
|
||||||
"That might take up to about 2 minutes at startup.").show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showWarning(String masthead, String message, Class target) {
|
private void showWarning(String masthead, String message, Class target) {
|
||||||
|
|
|
@ -127,6 +127,9 @@ class TakeOfferDataModel extends ActivatableDataModel {
|
||||||
void initWithData(Offer offer) {
|
void initWithData(Offer offer) {
|
||||||
this.offer = offer;
|
this.offer = offer;
|
||||||
|
|
||||||
|
addressEntry = walletService.getAddressEntryByOfferId(offer.getId());
|
||||||
|
checkNotNull(addressEntry, "addressEntry must not be null");
|
||||||
|
|
||||||
ObservableList<PaymentAccount> possiblePaymentAccounts = getPossiblePaymentAccounts();
|
ObservableList<PaymentAccount> possiblePaymentAccounts = getPossiblePaymentAccounts();
|
||||||
checkArgument(!possiblePaymentAccounts.isEmpty(), "possiblePaymentAccounts.isEmpty()");
|
checkArgument(!possiblePaymentAccounts.isEmpty(), "possiblePaymentAccounts.isEmpty()");
|
||||||
paymentAccount = possiblePaymentAccounts.get(0);
|
paymentAccount = possiblePaymentAccounts.get(0);
|
||||||
|
@ -136,9 +139,6 @@ class TakeOfferDataModel extends ActivatableDataModel {
|
||||||
calculateVolume();
|
calculateVolume();
|
||||||
calculateTotalToPay();
|
calculateTotalToPay();
|
||||||
|
|
||||||
addressEntry = walletService.getAddressEntryByOfferId(offer.getId());
|
|
||||||
checkNotNull(addressEntry, "addressEntry must not be null");
|
|
||||||
|
|
||||||
balanceListener = new BalanceListener(addressEntry.getAddress()) {
|
balanceListener = new BalanceListener(addressEntry.getAddress()) {
|
||||||
@Override
|
@Override
|
||||||
public void onBalanceChanged(@NotNull Coin balance) {
|
public void onBalanceChanged(@NotNull Coin balance) {
|
||||||
|
@ -255,6 +255,8 @@ class TakeOfferDataModel extends ActivatableDataModel {
|
||||||
amountAsCoin.get() != null &&
|
amountAsCoin.get() != null &&
|
||||||
!amountAsCoin.get().isZero()) {
|
!amountAsCoin.get().isZero()) {
|
||||||
volumeAsFiat.set(new ExchangeRate(offer.getPrice()).coinToFiat(amountAsCoin.get()));
|
volumeAsFiat.set(new ExchangeRate(offer.getPrice()).coinToFiat(amountAsCoin.get()));
|
||||||
|
|
||||||
|
updateBalance(walletService.getBalanceForAddress(addressEntry.getAddress()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,12 +225,16 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
if (newValue && model.getTrade() != null && model.getTrade().errorMessageProperty().get() == null) {
|
if (newValue && model.getTrade() != null && model.getTrade().errorMessageProperty().get() == null) {
|
||||||
UserThread.runAfter(() -> {
|
UserThread.runAfter(() -> {
|
||||||
new Popup().information(BSResources.get("takeOffer.success.info"))
|
new Popup().information(BSResources.get("takeOffer.success.info"))
|
||||||
.onClose(() -> {
|
.actionButtonText("Go to \"Open trades\"")
|
||||||
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
|
.onAction(() -> {
|
||||||
close();
|
close();
|
||||||
|
UserThread.runAfter(() ->
|
||||||
|
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class),
|
||||||
|
100, TimeUnit.MILLISECONDS);
|
||||||
})
|
})
|
||||||
|
.onClose(() -> close())
|
||||||
.show();
|
.show();
|
||||||
}, 300, TimeUnit.MILLISECONDS);
|
}, 100, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -322,7 +326,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
private void onTakeOffer() {
|
private void onTakeOffer() {
|
||||||
Offer offer = model.getOffer();
|
Offer offer = model.getOffer();
|
||||||
if (model.getShowTakeOfferConfirmation()) {
|
if (model.getShowTakeOfferConfirmation()) {
|
||||||
offerDetailsPopup.onTakeOffer(() -> model.onTakeOffer()).show(offer);
|
offerDetailsPopup.onTakeOffer(() -> model.onTakeOffer()).show(offer, model.dataModel.amountAsCoin.get());
|
||||||
} else {
|
} else {
|
||||||
if (model.hasAcceptedArbitrators()) {
|
if (model.hasAcceptedArbitrators()) {
|
||||||
model.onTakeOffer();
|
model.onTakeOffer();
|
||||||
|
@ -351,9 +355,13 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
Dialog.Actions.CLOSE.handle(actionEvent);
|
Dialog.Actions.CLOSE.handle(actionEvent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
new Popup().information("To ensure that both traders behave fair they need to pay a security deposit.\n\n" +
|
new Popup().information("To ensure that both traders follow the trade protocol they need to pay a security deposit.\n\n" +
|
||||||
"The deposit will stay in your local trading wallet until the offer gets accepted by another trader.\n" +
|
"The deposit will stay in your local trading wallet until the offer gets accepted by another trader.\n" +
|
||||||
"It will be refunded to you after the trade has successfully completed.").show();
|
"It will be refunded to you after the trade has successfully completed.\n\n" +
|
||||||
|
"You need to pay in the exact amount displayed to you from your external Bitcoin wallet into the " +
|
||||||
|
"Bitsquare trade wallet. The amount is the sum of the trade amount, the security deposit, " +
|
||||||
|
"the trading fee and the Bitcoin mining fee.\n" +
|
||||||
|
"You can see the details when you move the mouse over the question mark.").show();
|
||||||
|
|
||||||
model.onSecurityDepositInfoDisplayed();
|
model.onSecurityDepositInfoDisplayed();
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,7 +288,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||||
"Please try to restart you application and check your network connection to see if you can resolve the issue.";
|
"Please try to restart you application and check your network connection to see if you can resolve the issue.";
|
||||||
break;
|
break;
|
||||||
case TAKER_FEE_PAID:
|
case TAKER_FEE_PAID:
|
||||||
appendMsg = "\n\nThe take offer fee is already paid. In the worst case you have lost that fee. " +
|
appendMsg = "\n\nThe trading fee is already paid. In the worst case you have lost that fee. " +
|
||||||
"We are sorry about that but keep in mind it is a very small amount.\n" +
|
"We are sorry about that but keep in mind it is a very small amount.\n" +
|
||||||
"Please try to restart you application and check your network connection to see if you can resolve the issue.";
|
"Please try to restart you application and check your network connection to see if you can resolve the issue.";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -72,8 +72,21 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
|
||||||
table.setItems(model.getList());
|
table.setItems(model.getList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onCancelOpenOffer(OpenOffer openOffer) {
|
private void onRemoveOpenOffer(OpenOffer openOffer) {
|
||||||
if (model.isAuthenticated()) {
|
if (model.isAuthenticated()) {
|
||||||
|
new Popup().warning("Are you sure you want to remove that offer?\n" +
|
||||||
|
"The offer fee you have paid will be lost if you remove that offer.")
|
||||||
|
.actionButtonText("Remove offer")
|
||||||
|
.onAction(() -> doRemoveOpenOffer(openOffer))
|
||||||
|
.closeButtonText("Don't remove the offer")
|
||||||
|
.show();
|
||||||
|
} else {
|
||||||
|
new Popup().warning("You need to wait until your client is authenticated in the network.\n" +
|
||||||
|
"That might take up to about 2 minutes at startup.").show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doRemoveOpenOffer(OpenOffer openOffer) {
|
||||||
model.onCancelOpenOffer(openOffer,
|
model.onCancelOpenOffer(openOffer,
|
||||||
() -> {
|
() -> {
|
||||||
log.debug("Remove offer was successful");
|
log.debug("Remove offer was successful");
|
||||||
|
@ -85,10 +98,6 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
|
||||||
log.error(message);
|
log.error(message);
|
||||||
new Popup().warning("Remove offer failed:\n" + message).show();
|
new Popup().warning("Remove offer failed:\n" + message).show();
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
new Popup().warning("You need to wait until your client is authenticated in the network.\n" +
|
|
||||||
"That might take up to about 2 minutes at startup.").show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* private void openOfferDetails(OpenOfferListItem item) {
|
/* private void openOfferDetails(OpenOfferListItem item) {
|
||||||
|
@ -284,7 +293,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
|
||||||
super.updateItem(item, empty);
|
super.updateItem(item, empty);
|
||||||
|
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
button.setOnAction(event -> onCancelOpenOffer(item.getOpenOffer()));
|
button.setOnAction(event -> onRemoveOpenOffer(item.getOpenOffer()));
|
||||||
setGraphic(button);
|
setGraphic(button);
|
||||||
} else {
|
} else {
|
||||||
setGraphic(null);
|
setGraphic(null);
|
||||||
|
|
|
@ -136,8 +136,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
trade = null;
|
trade = null;
|
||||||
tradeProperty.set(null);
|
tradeProperty.set(null);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
trade = item.getTrade();
|
trade = item.getTrade();
|
||||||
tradeProperty.set(trade);
|
tradeProperty.set(trade);
|
||||||
|
|
||||||
|
@ -169,18 +168,18 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doWithdrawRequest(String toAddress, KeyParameter aesKey) {
|
private void doWithdrawRequest(String toAddress, KeyParameter aesKey) {
|
||||||
|
if (toAddress != null && toAddress.length() > 0) {
|
||||||
tradeManager.onWithdrawRequest(
|
tradeManager.onWithdrawRequest(
|
||||||
toAddress,
|
toAddress,
|
||||||
aesKey,
|
aesKey,
|
||||||
trade,
|
trade,
|
||||||
() -> {
|
() -> UserThread.execute(() -> navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class)),
|
||||||
UserThread.execute(() -> navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class));
|
|
||||||
},
|
|
||||||
(errorMessage, throwable) -> {
|
(errorMessage, throwable) -> {
|
||||||
log.error(errorMessage);
|
log.error(errorMessage);
|
||||||
new Popup().error("An error occurred:\n" + throwable.getMessage()).show();
|
new Popup().error("An error occurred:\n" + throwable.getMessage()).show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void onOpenDispute() {
|
public void onOpenDispute() {
|
||||||
doOpenDispute(false);
|
doOpenDispute(false);
|
||||||
|
|
|
@ -60,9 +60,11 @@ public class CompletedView extends TradeStepDetailsView {
|
||||||
@Override
|
@Override
|
||||||
public void doActivate() {
|
public void doActivate() {
|
||||||
super.doActivate();
|
super.doActivate();
|
||||||
withdrawAddressTextField.focusedProperty().addListener(focusedPropertyListener);
|
|
||||||
withdrawAddressTextField.setValidator(model.getBtcAddressValidator());
|
// TODO valid. handler need improvement
|
||||||
withdrawButton.disableProperty().bind(model.getWithdrawalButtonDisable());
|
//withdrawAddressTextField.focusedProperty().addListener(focusedPropertyListener);
|
||||||
|
//withdrawAddressTextField.setValidator(model.getBtcAddressValidator());
|
||||||
|
// withdrawButton.disableProperty().bind(model.getWithdrawalButtonDisable());
|
||||||
|
|
||||||
// We need to handle both cases: Address not set and address already set (when returning from other view)
|
// We need to handle both cases: Address not set and address already set (when returning from other view)
|
||||||
// We get address validation after focus out, so first make sure we loose focus and then set it again as hint for user to put address in
|
// We get address validation after focus out, so first make sure we loose focus and then set it again as hint for user to put address in
|
||||||
|
@ -78,8 +80,8 @@ public class CompletedView extends TradeStepDetailsView {
|
||||||
@Override
|
@Override
|
||||||
public void doDeactivate() {
|
public void doDeactivate() {
|
||||||
super.doDeactivate();
|
super.doDeactivate();
|
||||||
withdrawAddressTextField.focusedProperty().removeListener(focusedPropertyListener);
|
//withdrawAddressTextField.focusedProperty().removeListener(focusedPropertyListener);
|
||||||
withdrawButton.disableProperty().unbind();
|
// withdrawButton.disableProperty().unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -111,12 +111,25 @@ public class ConfirmPaymentReceivedView extends TradeStepDetailsView {
|
||||||
Preferences preferences = model.dataModel.getPreferences();
|
Preferences preferences = model.dataModel.getPreferences();
|
||||||
String key = PopupId.PAYMENT_RECEIVED;
|
String key = PopupId.PAYMENT_RECEIVED;
|
||||||
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
||||||
new Popup().information("Please note that as soon you have confirmed that you have received the " +
|
new Popup().headLine("Confirmation")
|
||||||
"payment the locked Bitcoin will be released.\n" +
|
.message("Do you have received the payment from your trading partner?\n\n" +
|
||||||
"There is no way to reverse a Bitcoin payment. Confirm only if you are sure.")
|
"Please note that as soon you have confirmed the locked Bitcoin will be released.\n" +
|
||||||
.onClose(() -> preferences.dontShowAgain(key))
|
"There is no way to reverse a Bitcoin payment.")
|
||||||
|
.dontShowAgainId(key, preferences)
|
||||||
|
.actionButtonText("Yes I have received the payment")
|
||||||
|
.closeButtonText("No")
|
||||||
|
.onAction(() -> confirmPaymentReceived())
|
||||||
.show();
|
.show();
|
||||||
} else {
|
} else {
|
||||||
|
confirmPaymentReceived();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new Popup().warning("You need to wait until your client is authenticated in the network.\n" +
|
||||||
|
"That might take up to about 2 minutes at startup.").show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void confirmPaymentReceived() {
|
||||||
confirmFiatReceivedButton.setDisable(true);
|
confirmFiatReceivedButton.setDisable(true);
|
||||||
|
|
||||||
statusProgressIndicator.setVisible(true);
|
statusProgressIndicator.setVisible(true);
|
||||||
|
@ -125,11 +138,6 @@ public class ConfirmPaymentReceivedView extends TradeStepDetailsView {
|
||||||
|
|
||||||
model.fiatPaymentReceived();
|
model.fiatPaymentReceived();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
new Popup().warning("You need to wait until your client is authenticated in the network.\n" +
|
|
||||||
"That might take up to about 2 minutes at startup.").show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -143,11 +143,23 @@ public class StartPaymentView extends TradeStepDetailsView {
|
||||||
if (model.isAuthenticated()) {
|
if (model.isAuthenticated()) {
|
||||||
String key = PopupId.PAYMENT_SENT;
|
String key = PopupId.PAYMENT_SENT;
|
||||||
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
||||||
new Popup().information("You are confirming that you have transferred the payment to your trading partner.\n" +
|
new Popup().headLine("Confirmation")
|
||||||
"Please click the \"Payment started\" button only if you have completed the transfer.")
|
.message("Do you have transferred the payment to your trading partner?")
|
||||||
.onClose(() -> preferences.dontShowAgain(key))
|
.dontShowAgainId(key, preferences)
|
||||||
|
.actionButtonText("Yes I have started the payment")
|
||||||
|
.closeButtonText("No")
|
||||||
|
.onAction(() -> confirmPaymentStarted())
|
||||||
.show();
|
.show();
|
||||||
} else {
|
} else {
|
||||||
|
confirmPaymentStarted();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new Popup().warning("You need to wait until your client is authenticated in the network.\n" +
|
||||||
|
"That might take up to about 2 minutes at startup.").show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void confirmPaymentStarted() {
|
||||||
paymentStartedButton.setDisable(true);
|
paymentStartedButton.setDisable(true);
|
||||||
|
|
||||||
statusProgressIndicator.setVisible(true);
|
statusProgressIndicator.setVisible(true);
|
||||||
|
@ -156,11 +168,6 @@ public class StartPaymentView extends TradeStepDetailsView {
|
||||||
|
|
||||||
model.fiatPaymentStarted();
|
model.fiatPaymentStarted();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
new Popup().warning("You need to wait until your client is authenticated in the network.\n" +
|
|
||||||
"That might take up to about 2 minutes at startup.").show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||||
btcDenominationComboBox = addLabelComboBox(root, gridRow, "Bitcoin denomination:", Layout.FIRST_ROW_DISTANCE).second;
|
btcDenominationComboBox = addLabelComboBox(root, gridRow, "Bitcoin denomination:", Layout.FIRST_ROW_DISTANCE).second;
|
||||||
blockExplorerComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin block explorer:").second;
|
blockExplorerComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin block explorer:").second;
|
||||||
useAnimationsCheckBox = addLabelCheckBox(root, ++gridRow, "Use animations:", "").second;
|
useAnimationsCheckBox = addLabelCheckBox(root, ++gridRow, "Use animations:", "").second;
|
||||||
useEffectsCheckBox = addLabelCheckBox(root, ++gridRow, "Use efects:", "").second;
|
useEffectsCheckBox = addLabelCheckBox(root, ++gridRow, "Use effects:", "").second;
|
||||||
showPlaceOfferConfirmationCheckBox = addLabelCheckBox(root, ++gridRow, "Show confirmation at place offer:", "").second;
|
showPlaceOfferConfirmationCheckBox = addLabelCheckBox(root, ++gridRow, "Show confirmation at place offer:", "").second;
|
||||||
showTakeOfferConfirmationCheckBox = addLabelCheckBox(root, ++gridRow, "Show confirmation at take offer:", "").second;
|
showTakeOfferConfirmationCheckBox = addLabelCheckBox(root, ++gridRow, "Show confirmation at take offer:", "").second;
|
||||||
autoSelectArbitratorsCheckBox = addLabelCheckBox(root, ++gridRow, "Auto select arbitrators by language:", "").second;
|
autoSelectArbitratorsCheckBox = addLabelCheckBox(root, ++gridRow, "Auto select arbitrators by language:", "").second;
|
||||||
|
|
|
@ -153,10 +153,8 @@ public class NetworkSettingsView extends ActivatableViewAndModel<GridPane, Activ
|
||||||
private void onSelectNetwork() {
|
private void onSelectNetwork() {
|
||||||
if (netWorkComboBox.getSelectionModel().getSelectedItem() != preferences.getBitcoinNetwork()) {
|
if (netWorkComboBox.getSelectionModel().getSelectedItem() != preferences.getBitcoinNetwork()) {
|
||||||
if (netWorkComboBox.getSelectionModel().getSelectedItem() == BitcoinNetwork.MAINNET) {
|
if (netWorkComboBox.getSelectionModel().getSelectedItem() == BitcoinNetwork.MAINNET) {
|
||||||
new Popup().warning("The application is under heavy development. " +
|
new Popup().warning("The application needs more tested before it can be used in mainnet.\n" +
|
||||||
"Using the mainnet network with Bitcoin is not recommended at that stage.\n\n" +
|
"Please follow our mailing list to get informed when Bitsquare will be ready for mainnet.")
|
||||||
"Are you sure you want to switch to mainnet?")
|
|
||||||
.onAction(() -> selectNetwork())
|
|
||||||
.onClose(() -> UserThread.execute(() -> netWorkComboBox.getSelectionModel().select(preferences.getBitcoinNetwork())))
|
.onClose(() -> UserThread.execute(() -> netWorkComboBox.getSelectionModel().select(preferences.getBitcoinNetwork())))
|
||||||
.show();
|
.show();
|
||||||
} else {
|
} else {
|
||||||
|
@ -166,10 +164,14 @@ public class NetworkSettingsView extends ActivatableViewAndModel<GridPane, Activ
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectNetwork() {
|
private void selectNetwork() {
|
||||||
|
//TODO restart
|
||||||
|
new Popup().warning("You need to shut down and restart the application to apply the change of the Bitcoin network.\n\n" +
|
||||||
|
"Do you want to shut down now?")
|
||||||
|
.onAction(() -> {
|
||||||
preferences.setBitcoinNetwork(netWorkComboBox.getSelectionModel().getSelectedItem());
|
preferences.setBitcoinNetwork(netWorkComboBox.getSelectionModel().getSelectedItem());
|
||||||
new Popup().warning("You need to restart the application to apply the change of the Bitcoin network..\n\n" +
|
UserThread.runAfter(() -> BitsquareApp.shutDownHandler.run(), 1);
|
||||||
"Do you want to restart now?")
|
})
|
||||||
.onAction(() -> BitsquareApp.restartDownHandler.run())
|
.onClose(() -> netWorkComboBox.getSelectionModel().select(preferences.getBitcoinNetwork()))
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,8 +109,7 @@ public class ContractPopup extends Popup {
|
||||||
Layout.FIRST_ROW_DISTANCE).second.setMouseTransparent(false);
|
Layout.FIRST_ROW_DISTANCE).second.setMouseTransparent(false);
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Offer date:", formatter.formatDateTime(offer.getDate()));
|
addLabelTextField(gridPane, ++rowIndex, "Offer date:", formatter.formatDateTime(offer.getDate()));
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Trade date:", formatter.formatDateTime(dispute.getTradeDate()));
|
addLabelTextField(gridPane, ++rowIndex, "Trade date:", formatter.formatDateTime(dispute.getTradeDate()));
|
||||||
String direction = offer.getDirection() == Offer.Direction.BUY ? "Offerer as buyer / Taker as seller" : "Offerer as seller / Taker as buyer";
|
addLabelTextField(gridPane, ++rowIndex, "Trade type:", formatter.getDirectionDescription(offer.getDirection()));
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Trade type:", direction);
|
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode());
|
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode());
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(contract.getTradeAmount()));
|
addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(contract.getTradeAmount()));
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Buyer bitcoin address:",
|
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Buyer bitcoin address:",
|
||||||
|
@ -144,8 +143,8 @@ public class ContractPopup extends Popup {
|
||||||
}
|
}
|
||||||
//addLabelTextField(gridPane, ++rowIndex, "Buyer Bitsquare account ID:", contract.getBuyerAccountId()).second.setMouseTransparent(false);
|
//addLabelTextField(gridPane, ++rowIndex, "Buyer Bitsquare account ID:", contract.getBuyerAccountId()).second.setMouseTransparent(false);
|
||||||
//addLabelTextField(gridPane, ++rowIndex, "Seller Bitsquare account ID:", contract.getSellerAccountId()).second.setMouseTransparent(false);
|
//addLabelTextField(gridPane, ++rowIndex, "Seller Bitsquare account ID:", contract.getSellerAccountId()).second.setMouseTransparent(false);
|
||||||
addLabelTxIdTextField(gridPane, ++rowIndex, "Create offer fee transaction ID:", offer.getOfferFeePaymentTxID());
|
addLabelTxIdTextField(gridPane, ++rowIndex, "Offer fee transaction ID:", offer.getOfferFeePaymentTxID());
|
||||||
addLabelTxIdTextField(gridPane, ++rowIndex, "Take offer fee transaction ID:", contract.takeOfferFeeTxID);
|
addLabelTxIdTextField(gridPane, ++rowIndex, "Trading fee transaction ID:", contract.takeOfferFeeTxID);
|
||||||
if (dispute.getDepositTxSerialized() != null)
|
if (dispute.getDepositTxSerialized() != null)
|
||||||
addLabelTxIdTextField(gridPane, ++rowIndex, "Deposit transaction ID:", dispute.getDepositTxId());
|
addLabelTxIdTextField(gridPane, ++rowIndex, "Deposit transaction ID:", dispute.getDepositTxId());
|
||||||
if (dispute.getPayoutTxSerialized() != null)
|
if (dispute.getPayoutTxSerialized() != null)
|
||||||
|
|
|
@ -54,8 +54,8 @@ public class FirstTimeWebViewPopup extends WebViewPopup {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FirstTimeWebViewPopup id(String id) {
|
public FirstTimeWebViewPopup id(String dontShowAgainId) {
|
||||||
this.id = id;
|
this.id = dontShowAgainId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.CheckBox;
|
import javafx.scene.control.CheckBox;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
|
import org.bitcoinj.core.Coin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -52,6 +54,7 @@ public class OfferDetailsPopup extends Popup {
|
||||||
private User user;
|
private User user;
|
||||||
private final Navigation navigation;
|
private final Navigation navigation;
|
||||||
private Offer offer;
|
private Offer offer;
|
||||||
|
private Coin tradeAmount;
|
||||||
private Optional<Consumer<Offer>> placeOfferHandlerOptional = Optional.empty();
|
private Optional<Consumer<Offer>> placeOfferHandlerOptional = Optional.empty();
|
||||||
private Optional<Runnable> takeOfferHandlerOptional = Optional.empty();
|
private Optional<Runnable> takeOfferHandlerOptional = Optional.empty();
|
||||||
|
|
||||||
|
@ -68,6 +71,18 @@ public class OfferDetailsPopup extends Popup {
|
||||||
this.navigation = navigation;
|
this.navigation = navigation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OfferDetailsPopup show(Offer offer, Coin tradeAmount) {
|
||||||
|
this.offer = offer;
|
||||||
|
this.tradeAmount = tradeAmount;
|
||||||
|
|
||||||
|
rowIndex = -1;
|
||||||
|
width = 850;
|
||||||
|
createGridPane();
|
||||||
|
addContent();
|
||||||
|
createPopup();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public OfferDetailsPopup show(Offer offer) {
|
public OfferDetailsPopup show(Offer offer) {
|
||||||
this.offer = offer;
|
this.offer = offer;
|
||||||
|
|
||||||
|
@ -110,25 +125,36 @@ public class OfferDetailsPopup extends Popup {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addContent() {
|
private void addContent() {
|
||||||
int rows = 11;
|
int rows = 5;
|
||||||
|
if (!takeOfferHandlerOptional.isPresent())
|
||||||
|
rows++;
|
||||||
|
|
||||||
|
addTitledGroupBg(gridPane, ++rowIndex, rows, "Offer");
|
||||||
|
addLabelTextField(gridPane, rowIndex, "Offer type:", formatter.getDirectionDescription(offer.getDirection()), Layout.FIRST_ROW_DISTANCE);
|
||||||
|
addLabelTextField(gridPane, ++rowIndex, "Currency:", offer.getCurrencyCode());
|
||||||
|
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode() + "/" + "BTC");
|
||||||
|
if (takeOfferHandlerOptional.isPresent()) {
|
||||||
|
addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(tradeAmount));
|
||||||
|
} else {
|
||||||
|
addLabelTextField(gridPane, ++rowIndex, "Amount:", formatter.formatCoinWithCode(offer.getAmount()));
|
||||||
|
addLabelTextField(gridPane, ++rowIndex, "Min. amount:", formatter.formatCoinWithCode(offer.getMinAmount()));
|
||||||
|
}
|
||||||
|
addLabelTextField(gridPane, ++rowIndex, "Payment method:", BSResources.get(offer.getPaymentMethod().getId()));
|
||||||
|
|
||||||
|
rows = 3;
|
||||||
if (offer.getPaymentMethodCountryCode() != null)
|
if (offer.getPaymentMethodCountryCode() != null)
|
||||||
rows++;
|
rows++;
|
||||||
if (offer.getOfferFeePaymentTxID() != null)
|
if (offer.getOfferFeePaymentTxID() != null)
|
||||||
rows++;
|
rows++;
|
||||||
if (offer.getAcceptedCountryCodes() != null)
|
if (offer.getAcceptedCountryCodes() != null)
|
||||||
rows++;
|
rows++;
|
||||||
if (placeOfferHandlerOptional.isPresent())
|
/* if (placeOfferHandlerOptional.isPresent())
|
||||||
rows -= 2;
|
rows -= 2;*/
|
||||||
|
|
||||||
addTitledGroupBg(gridPane, ++rowIndex, rows, "Offer details");
|
addTitledGroupBg(gridPane, ++rowIndex, rows, "Details", Layout.GROUP_DISTANCE);
|
||||||
addLabelTextField(gridPane, rowIndex, "Offer ID:", offer.getId(), Layout.FIRST_ROW_DISTANCE);
|
addLabelTextField(gridPane, rowIndex, "Offer ID:", offer.getId(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Creation date:", formatter.formatDateTime(offer.getDate()));
|
addLabelTextField(gridPane, ++rowIndex, "Creation date:", formatter.formatDateTime(offer.getDate()));
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Offer direction:", Offer.Direction.BUY.name());
|
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Currency:", offer.getCurrencyCode());
|
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode() + "/" + "BTC");
|
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Amount:", formatter.formatCoinWithCode(offer.getAmount()));
|
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Min. amount:", formatter.formatCoinWithCode(offer.getMinAmount()));
|
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Payment method:", BSResources.get(offer.getPaymentMethod().getId()));
|
|
||||||
if (offer.getPaymentMethodCountryCode() != null)
|
if (offer.getPaymentMethodCountryCode() != null)
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Offerers country of bank:", offer.getPaymentMethodCountryCode());
|
addLabelTextField(gridPane, ++rowIndex, "Offerers country of bank:", offer.getPaymentMethodCountryCode());
|
||||||
if (offer.getAcceptedCountryCodes() != null) {
|
if (offer.getAcceptedCountryCodes() != null) {
|
||||||
|
@ -141,41 +167,48 @@ public class OfferDetailsPopup extends Popup {
|
||||||
tooltip = new Tooltip(CountryUtil.getNamesByCodesString(offer.getAcceptedCountryCodes()));
|
tooltip = new Tooltip(CountryUtil.getNamesByCodesString(offer.getAcceptedCountryCodes()));
|
||||||
}
|
}
|
||||||
TextField acceptedCountries = addLabelTextField(gridPane, ++rowIndex, "Accepted taker countries:", countries).second;
|
TextField acceptedCountries = addLabelTextField(gridPane, ++rowIndex, "Accepted taker countries:", countries).second;
|
||||||
if (tooltip != null) acceptedCountries.setTooltip(new Tooltip());
|
if (tooltip != null) {
|
||||||
|
acceptedCountries.setMouseTransparent(false);
|
||||||
|
acceptedCountries.setTooltip(tooltip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Accepted arbitrators:", formatter.arbitratorAddressesToString(offer.getArbitratorAddresses()));
|
addLabelTextField(gridPane, ++rowIndex, "Accepted arbitrators:", formatter.arbitratorAddressesToString(offer.getArbitratorAddresses()));
|
||||||
if (offer.getOfferFeePaymentTxID() != null)
|
if (offer.getOfferFeePaymentTxID() != null)
|
||||||
addLabelTxIdTextField(gridPane, ++rowIndex, "Create offer fee transaction ID:", offer.getOfferFeePaymentTxID());
|
addLabelTxIdTextField(gridPane, ++rowIndex, "Offer fee transaction ID:", offer.getOfferFeePaymentTxID());
|
||||||
|
|
||||||
if (placeOfferHandlerOptional.isPresent()) {
|
if (placeOfferHandlerOptional.isPresent()) {
|
||||||
Tuple2<Button, Button> tuple = add2ButtonsAfterGroup(gridPane, ++rowIndex, "Confirm place offer", "Cancel");
|
addTitledGroupBg(gridPane, ++rowIndex, 1, "Commitment", Layout.GROUP_DISTANCE);
|
||||||
Button placeButton = tuple.first;
|
addLabelTextField(gridPane, rowIndex, "Please note:", Offer.TAC_OFFERER, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
placeButton.setOnAction(e -> {
|
|
||||||
if (user.getAcceptedArbitrators().size() > 0) {
|
Button cancelButton = addConfirmButton(true);
|
||||||
placeOfferHandlerOptional.get().accept(offer);
|
addCancelButton(cancelButton, true);
|
||||||
|
} else if (takeOfferHandlerOptional.isPresent()) {
|
||||||
|
addTitledGroupBg(gridPane, ++rowIndex, 1, "Contract", Layout.GROUP_DISTANCE);
|
||||||
|
addLabelTextField(gridPane, rowIndex, "Terms and conditions:", Offer.TAC_TAKER, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
|
|
||||||
|
Button cancelButton = addConfirmButton(false);
|
||||||
|
addCancelButton(cancelButton, false);
|
||||||
} else {
|
} else {
|
||||||
new Popup().warning("You have no arbitrator selected.\n" +
|
Button cancelButton = addButtonAfterGroup(gridPane, ++rowIndex, "Close");
|
||||||
"Please select at least one arbitrator.").show();
|
|
||||||
|
|
||||||
navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, ArbitratorSelectionView.class);
|
|
||||||
}
|
|
||||||
hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
Button cancelButton = tuple.second;
|
|
||||||
cancelButton.setOnAction(e -> {
|
cancelButton.setOnAction(e -> {
|
||||||
closeHandlerOptional.ifPresent(closeHandler -> closeHandler.run());
|
closeHandlerOptional.ifPresent(closeHandler -> closeHandler.run());
|
||||||
hide();
|
hide();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CheckBox checkBox = addCheckBox(gridPane, ++rowIndex, "Don't show again", 5);
|
@NotNull
|
||||||
checkBox.setSelected(!preferences.getShowPlaceOfferConfirmation());
|
private Button addConfirmButton(boolean isPlaceOffer) {
|
||||||
checkBox.setOnAction(e -> preferences.setShowPlaceOfferConfirmation(!checkBox.isSelected()));
|
Tuple2<Button, Button> tuple = add2ButtonsAfterGroup(gridPane,
|
||||||
} else if (takeOfferHandlerOptional.isPresent()) {
|
++rowIndex,
|
||||||
Tuple2<Button, Button> tuple = add2ButtonsAfterGroup(gridPane, ++rowIndex, "Confirm take offer", "Cancel");
|
isPlaceOffer ? "Confirm place offer" : "Confirm take offer",
|
||||||
|
"Cancel");
|
||||||
Button placeButton = tuple.first;
|
Button placeButton = tuple.first;
|
||||||
placeButton.setOnAction(e -> {
|
placeButton.setOnAction(e -> {
|
||||||
if (user.getAcceptedArbitrators().size() > 0) {
|
if (user.getAcceptedArbitrators().size() > 0) {
|
||||||
|
if (isPlaceOffer)
|
||||||
|
placeOfferHandlerOptional.get().accept(offer);
|
||||||
|
else
|
||||||
takeOfferHandlerOptional.get().run();
|
takeOfferHandlerOptional.get().run();
|
||||||
} else {
|
} else {
|
||||||
new Popup().warning("You have no arbitrator selected.\n" +
|
new Popup().warning("You have no arbitrator selected.\n" +
|
||||||
|
@ -185,23 +218,22 @@ public class OfferDetailsPopup extends Popup {
|
||||||
}
|
}
|
||||||
hide();
|
hide();
|
||||||
});
|
});
|
||||||
|
return tuple.second;
|
||||||
|
}
|
||||||
|
|
||||||
Button cancelButton = tuple.second;
|
private void addCancelButton(Button cancelButton, boolean isPlaceOffer) {
|
||||||
cancelButton.setOnAction(e -> {
|
cancelButton.setOnAction(e -> {
|
||||||
closeHandlerOptional.ifPresent(closeHandler -> closeHandler.run());
|
closeHandlerOptional.ifPresent(closeHandler -> closeHandler.run());
|
||||||
hide();
|
hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
CheckBox checkBox = addCheckBox(gridPane, ++rowIndex, "Don't show again", 5);
|
CheckBox checkBox = addCheckBox(gridPane, ++rowIndex, "Don't show again", 5);
|
||||||
checkBox.setPadding(new Insets(20, 0, 25, 0));
|
if (isPlaceOffer) {
|
||||||
|
checkBox.setSelected(!preferences.getShowPlaceOfferConfirmation());
|
||||||
|
checkBox.setOnAction(e -> preferences.setShowPlaceOfferConfirmation(!checkBox.isSelected()));
|
||||||
|
} else {
|
||||||
checkBox.setSelected(!preferences.getShowTakeOfferConfirmation());
|
checkBox.setSelected(!preferences.getShowTakeOfferConfirmation());
|
||||||
checkBox.setOnAction(e -> preferences.setShowTakeOfferConfirmation(!checkBox.isSelected()));
|
checkBox.setOnAction(e -> preferences.setShowTakeOfferConfirmation(!checkBox.isSelected()));
|
||||||
} else {
|
|
||||||
Button cancelButton = addButtonAfterGroup(gridPane, ++rowIndex, "Close");
|
|
||||||
cancelButton.setOnAction(e -> {
|
|
||||||
closeHandlerOptional.ifPresent(closeHandler -> closeHandler.run());
|
|
||||||
hide();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,15 +21,13 @@ import io.bitsquare.common.util.Utilities;
|
||||||
import io.bitsquare.gui.main.MainView;
|
import io.bitsquare.gui.main.MainView;
|
||||||
import io.bitsquare.gui.util.Transitions;
|
import io.bitsquare.gui.util.Transitions;
|
||||||
import io.bitsquare.locale.BSResources;
|
import io.bitsquare.locale.BSResources;
|
||||||
|
import io.bitsquare.user.Preferences;
|
||||||
import javafx.geometry.HPos;
|
import javafx.geometry.HPos;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Orientation;
|
import javafx.geometry.Orientation;
|
||||||
import javafx.geometry.Point2D;
|
import javafx.geometry.Point2D;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.control.ProgressIndicator;
|
|
||||||
import javafx.scene.control.Separator;
|
|
||||||
import javafx.scene.layout.*;
|
import javafx.scene.layout.*;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.stage.Modality;
|
import javafx.stage.Modality;
|
||||||
|
@ -43,6 +41,8 @@ import org.slf4j.LoggerFactory;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static io.bitsquare.gui.util.FormBuilder.addCheckBox;
|
||||||
|
|
||||||
public class Popup {
|
public class Popup {
|
||||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@ -66,6 +66,8 @@ public class Popup {
|
||||||
private boolean showProgressIndicator;
|
private boolean showProgressIndicator;
|
||||||
private Button actionButton;
|
private Button actionButton;
|
||||||
protected Label headLineLabel;
|
protected Label headLineLabel;
|
||||||
|
private String dontShowAgainId;
|
||||||
|
private Preferences preferences;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -87,6 +89,7 @@ public class Popup {
|
||||||
addReportErrorButtons();
|
addReportErrorButtons();
|
||||||
|
|
||||||
addCloseButton();
|
addCloseButton();
|
||||||
|
addDontShowAgainCheckBox();
|
||||||
createPopup();
|
createPopup();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -164,6 +167,12 @@ public class Popup {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Popup dontShowAgainId(String dontShowAgainId, Preferences preferences) {
|
||||||
|
this.dontShowAgainId = dontShowAgainId;
|
||||||
|
this.preferences = preferences;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Protected
|
// Protected
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -297,6 +306,17 @@ public class Popup {
|
||||||
gridPane.getChildren().add(progressIndicator);
|
gridPane.getChildren().add(progressIndicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addDontShowAgainCheckBox() {
|
||||||
|
if (dontShowAgainId != null && preferences != null) {
|
||||||
|
CheckBox dontShowAgain = addCheckBox(gridPane, ++rowIndex, "Don't show again", 10);
|
||||||
|
GridPane.setHalignment(dontShowAgain, HPos.RIGHT);
|
||||||
|
dontShowAgain.setOnAction(e -> {
|
||||||
|
if (dontShowAgain.isSelected())
|
||||||
|
preferences.dontShowAgain(dontShowAgainId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void addCloseButton() {
|
protected void addCloseButton() {
|
||||||
closeButton = new Button(closeButtonText == null ? "Close" : closeButtonText);
|
closeButton = new Button(closeButtonText == null ? "Close" : closeButtonText);
|
||||||
closeButton.setOnAction(event -> {
|
closeButton.setOnAction(event -> {
|
||||||
|
@ -333,12 +353,11 @@ public class Popup {
|
||||||
GridPane.setColumnIndex(closeButton, 1);
|
GridPane.setColumnIndex(closeButton, 1);
|
||||||
gridPane.getChildren().add(closeButton);
|
gridPane.getChildren().add(closeButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setTruncatedMessage() {
|
protected void setTruncatedMessage() {
|
||||||
if (message != null && message.length() > 500)
|
if (message != null && message.length() > 600)
|
||||||
truncatedMessage = message.substring(0, 500) + "...";
|
truncatedMessage = message.substring(0, 600) + "...";
|
||||||
else
|
else
|
||||||
truncatedMessage = message;
|
truncatedMessage = message;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,15 @@ public class TradeDetailsPopup extends Popup {
|
||||||
Offer offer = trade.getOffer();
|
Offer offer = trade.getOffer();
|
||||||
Contract contract = trade.getContract();
|
Contract contract = trade.getContract();
|
||||||
|
|
||||||
int rows = 7;
|
int rows = 5;
|
||||||
|
addTitledGroupBg(gridPane, ++rowIndex, rows, "Trade");
|
||||||
|
addLabelTextField(gridPane, rowIndex, "Trade type:", formatter.getDirectionDescription(offer.getDirection()), Layout.FIRST_ROW_DISTANCE);
|
||||||
|
addLabelTextField(gridPane, ++rowIndex, "Currency:", offer.getCurrencyCode());
|
||||||
|
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode());
|
||||||
|
addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(trade.getTradeAmount()));
|
||||||
|
addLabelTextField(gridPane, ++rowIndex, "Payment method:", BSResources.get(offer.getPaymentMethod().getId()));
|
||||||
|
|
||||||
|
rows = 4;
|
||||||
PaymentAccountContractData buyerPaymentAccountContractData = null;
|
PaymentAccountContractData buyerPaymentAccountContractData = null;
|
||||||
PaymentAccountContractData sellerPaymentAccountContractData = null;
|
PaymentAccountContractData sellerPaymentAccountContractData = null;
|
||||||
|
|
||||||
|
@ -98,6 +106,8 @@ public class TradeDetailsPopup extends Popup {
|
||||||
rows++;
|
rows++;
|
||||||
|
|
||||||
if (contract != null) {
|
if (contract != null) {
|
||||||
|
rows++;
|
||||||
|
|
||||||
buyerPaymentAccountContractData = contract.getBuyerPaymentAccountContractData();
|
buyerPaymentAccountContractData = contract.getBuyerPaymentAccountContractData();
|
||||||
sellerPaymentAccountContractData = contract.getSellerPaymentAccountContractData();
|
sellerPaymentAccountContractData = contract.getSellerPaymentAccountContractData();
|
||||||
if (buyerPaymentAccountContractData != null)
|
if (buyerPaymentAccountContractData != null)
|
||||||
|
@ -120,13 +130,9 @@ public class TradeDetailsPopup extends Popup {
|
||||||
if (trade.errorMessageProperty().get() != null)
|
if (trade.errorMessageProperty().get() != null)
|
||||||
rows += 2;
|
rows += 2;
|
||||||
|
|
||||||
addTitledGroupBg(gridPane, ++rowIndex, rows, "Trade details");
|
addTitledGroupBg(gridPane, ++rowIndex, rows, "Details", Layout.GROUP_DISTANCE);
|
||||||
addLabelTextField(gridPane, rowIndex, "Trade ID:", trade.getId(), Layout.FIRST_ROW_DISTANCE);
|
addLabelTextField(gridPane, rowIndex, "Trade ID:", trade.getId(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Trade date:", formatter.formatDateTime(trade.getDate()));
|
addLabelTextField(gridPane, ++rowIndex, "Trade date:", formatter.formatDateTime(trade.getDate()));
|
||||||
String direction = offer.getDirection() == Offer.Direction.BUY ? "Offerer as buyer / Taker as seller" : "Offerer as seller / Taker as buyer";
|
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Offer direction:", direction);
|
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode());
|
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(trade.getTradeAmount()));
|
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Selected arbitrator:", trade.getArbitratorAddress().getFullAddress());
|
addLabelTextField(gridPane, ++rowIndex, "Selected arbitrator:", trade.getArbitratorAddress().getFullAddress());
|
||||||
|
|
||||||
if (contract != null) {
|
if (contract != null) {
|
||||||
|
@ -144,15 +150,22 @@ public class TradeDetailsPopup extends Popup {
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Payment method:", BSResources.get(contract.getPaymentMethodName()));
|
addLabelTextField(gridPane, ++rowIndex, "Payment method:", BSResources.get(contract.getPaymentMethodName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
addLabelTxIdTextField(gridPane, ++rowIndex, "Create offer fee transaction ID:", offer.getOfferFeePaymentTxID());
|
addLabelTxIdTextField(gridPane, ++rowIndex, "Offer fee transaction ID:", offer.getOfferFeePaymentTxID());
|
||||||
if (contract != null && contract.takeOfferFeeTxID != null)
|
if (contract != null && contract.takeOfferFeeTxID != null)
|
||||||
addLabelTxIdTextField(gridPane, ++rowIndex, "Take offer fee transaction ID:", contract.takeOfferFeeTxID);
|
addLabelTxIdTextField(gridPane, ++rowIndex, "Trading fee transaction ID:", contract.takeOfferFeeTxID);
|
||||||
|
|
||||||
if (trade.getDepositTx() != null)
|
if (trade.getDepositTx() != null)
|
||||||
addLabelTxIdTextField(gridPane, ++rowIndex, "Deposit transaction ID:", trade.getDepositTx().getHashAsString());
|
addLabelTxIdTextField(gridPane, ++rowIndex, "Deposit transaction ID:", trade.getDepositTx().getHashAsString());
|
||||||
if (trade.getPayoutTx() != null)
|
if (trade.getPayoutTx() != null)
|
||||||
addLabelTxIdTextField(gridPane, ++rowIndex, "Payout transaction ID:", trade.getPayoutTx().getHashAsString());
|
addLabelTxIdTextField(gridPane, ++rowIndex, "Payout transaction ID:", trade.getPayoutTx().getHashAsString());
|
||||||
|
|
||||||
|
if (contract != null) {
|
||||||
|
TextArea textArea = addLabelTextArea(gridPane, ++rowIndex, "Contract in JSON format:", trade.getContractAsJson()).second;
|
||||||
|
textArea.setText(trade.getContractAsJson());
|
||||||
|
textArea.setPrefHeight(50);
|
||||||
|
textArea.setEditable(false);
|
||||||
|
}
|
||||||
|
|
||||||
if (trade.errorMessageProperty().get() != null) {
|
if (trade.errorMessageProperty().get() != null) {
|
||||||
TextArea textArea = addLabelTextArea(gridPane, ++rowIndex, "Error message:", "").second;
|
TextArea textArea = addLabelTextArea(gridPane, ++rowIndex, "Error message:", "").second;
|
||||||
textArea.setText(trade.errorMessageProperty().get());
|
textArea.setText(trade.errorMessageProperty().get());
|
||||||
|
@ -169,26 +182,6 @@ public class TradeDetailsPopup extends Popup {
|
||||||
|
|
||||||
TextField state = addLabelTextField(gridPane, ++rowIndex, "Trade state:").second;
|
TextField state = addLabelTextField(gridPane, ++rowIndex, "Trade state:").second;
|
||||||
state.setText(trade.getState().getPhase().name());
|
state.setText(trade.getState().getPhase().name());
|
||||||
//TODO better msg display
|
|
||||||
/* switch (trade.getTradeState().getPhase()) {
|
|
||||||
case PREPARATION:
|
|
||||||
state.setText("Take offer fee is already paid.");
|
|
||||||
break;
|
|
||||||
case TAKER_FEE_PAID:
|
|
||||||
state.setText("Take offer fee is already paid.");
|
|
||||||
break;
|
|
||||||
case DEPOSIT_PAID:
|
|
||||||
case FIAT_SENT:
|
|
||||||
case FIAT_RECEIVED:
|
|
||||||
state.setText("Deposit is already paid.");
|
|
||||||
break;
|
|
||||||
case PAYOUT_PAID:
|
|
||||||
break;
|
|
||||||
case WITHDRAWN:
|
|
||||||
break;
|
|
||||||
case DISPUTE:
|
|
||||||
break;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Button cancelButton = addButtonAfterGroup(gridPane, ++rowIndex, "Close");
|
Button cancelButton = addButtonAfterGroup(gridPane, ++rowIndex, "Close");
|
||||||
|
|
|
@ -125,8 +125,7 @@ public class BSFormatter {
|
||||||
log.warn("Exception at formatBtc: " + t.toString());
|
log.warn("Exception at formatBtc: " + t.toString());
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,8 +140,7 @@ public class BSFormatter {
|
||||||
log.warn("Exception at formatBtcWithCode: " + t.toString());
|
log.warn("Exception at formatBtcWithCode: " + t.toString());
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,8 +153,7 @@ public class BSFormatter {
|
||||||
log.warn("Exception at parseToBtc: " + t.toString());
|
log.warn("Exception at parseToBtc: " + t.toString());
|
||||||
return Coin.ZERO;
|
return Coin.ZERO;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return Coin.ZERO;
|
return Coin.ZERO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,8 +205,7 @@ public class BSFormatter {
|
||||||
log.warn("Exception at formatFiat: " + t.toString());
|
log.warn("Exception at formatFiat: " + t.toString());
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,8 +219,7 @@ public class BSFormatter {
|
||||||
log.warn("Exception at formatFiatWithCode: " + t.toString());
|
log.warn("Exception at formatFiatWithCode: " + t.toString());
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,8 +233,7 @@ public class BSFormatter {
|
||||||
return Fiat.valueOf(currencyCode, 0);
|
return Fiat.valueOf(currencyCode, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return Fiat.valueOf(currencyCode, 0);
|
return Fiat.valueOf(currencyCode, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,4 +368,8 @@ public class BSFormatter {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDirectionDescription(Offer.Direction direction) {
|
||||||
|
return direction == Offer.Direction.BUY ? "Offerer as Bitcoin buyer / Taker as Bitcoin seller" : "Offerer as Bitcoin seller / Taker as Bitcoin buyer";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ arising from, out of or in connection with the software or the use or other deal
|
||||||
2. The user is responsible to use the software in compliance with local laws.
|
2. The user is responsible to use the software in compliance with local laws.
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
3. The user confirms that he has read and agreed to the rules defined in our
|
3. The user confirms that he has read and agreed to the rules defined in our
|
||||||
<a href="https://github.com/bitsquare/bitsquare/wiki/Dispute-process" target="_blank">wiki</a> regrading the dispute
|
<a href="https://github.com/bitsquare/bitsquare/wiki/Dispute-process" target="_blank">Wiki</a> regrading the dispute
|
||||||
process.<br/>
|
process.<br/>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -23,13 +23,12 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Information</h1>
|
<h1>Information</h1>
|
||||||
Bitsquare does not use a global wallet.<br/>
|
Bitsquare does not use a single application wallet, but dedicated wallets for every trade.<br/>
|
||||||
For every trade a dedicated wallet will be created. Funding of the wallet will be done just in time when it is needed.
|
Funding of the wallet will be done when needed, for instance when you create or take an offer.
|
||||||
For instance when you create an offer or
|
Withdrawing funds can be done after a trade is completed.<br/>
|
||||||
when you take an offer. Withdrawing from your funds can be done after a trade has been completed.<br/>
|
Dedicated wallets help protect user privacy and prevent leaking information of previous trades to other
|
||||||
That separation of addresses helps to protect users privacy and not leaking information of previous trades to new
|
|
||||||
traders.<br/>
|
traders.<br/>
|
||||||
Please read more background information to that topic at the Bitsquare <a href="https://bitsquare.io/faq/#tradeWallet"
|
For more background information please see the Bitsquare <a href="https://bitsquare.io/faq/#tradeWallet"
|
||||||
target="_blank">FAQ</a>.
|
target="_blank">FAQ</a>.
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -646,16 +646,32 @@ public class PeerGroup implements MessageListener, ConnectionListener {
|
||||||
// Reported peers
|
// Reported peers
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void addToReportedPeers(HashSet<ReportedPeer> reportedPeers, Connection connection) {
|
void addToReportedPeers(HashSet<ReportedPeer> newReportedPeers, Connection connection) {
|
||||||
Log.traceCall();
|
Log.traceCall();
|
||||||
// we disconnect misbehaving nodes trying to send too many peers
|
// we disconnect misbehaving nodes trying to send too many peers
|
||||||
// reported peers include the peers connected peers which is normally max. 8 but we give some headroom
|
// reported peers include the peers connected peers which is normally max. 8 but we give some headroom
|
||||||
// for safety
|
// for safety
|
||||||
if (reportedPeers.size() > 1100) {
|
if (newReportedPeers.size() > 1100) {
|
||||||
connection.shutDown();
|
connection.shutDown();
|
||||||
} else {
|
} else {
|
||||||
reportedPeers.remove(new ReportedPeer(getMyAddress(), new Date()));
|
newReportedPeers.remove(new ReportedPeer(getMyAddress(), new Date()));
|
||||||
this.reportedPeers.addAll(reportedPeers);
|
|
||||||
|
//TODO if we have already peer, we mix date from old and new item
|
||||||
|
//
|
||||||
|
/* Map<Address, ReportedPeer> reportedPeersMap = new HashMap<>();
|
||||||
|
reportedPeers.stream().forEach(e -> reportedPeersMap.put(e.address, e));
|
||||||
|
|
||||||
|
HashSet<ReportedPeer> newAdjustedReportedPeers = new HashSet<>();
|
||||||
|
newReportedPeers.stream()
|
||||||
|
.forEach(e -> {
|
||||||
|
if()
|
||||||
|
long adjustedTime = (e.lastActivityDate.getTime() +
|
||||||
|
reportedPeersMap.get(e.address).lastActivityDate.getTime()) / 2;
|
||||||
|
newAdjustedReportedPeers.add(new ReportedPeer(e.address,
|
||||||
|
new Date(adjustedTime)));
|
||||||
|
});*/
|
||||||
|
|
||||||
|
this.reportedPeers.addAll(newReportedPeers);
|
||||||
purgeReportedPeersIfExceeds();
|
purgeReportedPeersIfExceeds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,6 +686,8 @@ public class PeerGroup implements MessageListener, ConnectionListener {
|
||||||
"We remove random peers from the reported peers list.", MAX_REPORTED_PEERS, size);
|
"We remove random peers from the reported peers list.", MAX_REPORTED_PEERS, size);
|
||||||
int diff = size - MAX_REPORTED_PEERS;
|
int diff = size - MAX_REPORTED_PEERS;
|
||||||
List<ReportedPeer> list = new LinkedList<>(getReportedNotConnectedPeerAddresses());
|
List<ReportedPeer> list = new LinkedList<>(getReportedNotConnectedPeerAddresses());
|
||||||
|
|
||||||
|
//TODO sort and remove oldest
|
||||||
for (int i = 0; i < diff; i++) {
|
for (int i = 0; i < diff; i++) {
|
||||||
ReportedPeer toRemove = getAndRemoveRandomReportedPeer(list);
|
ReportedPeer toRemove = getAndRemoveRandomReportedPeer(list);
|
||||||
reportedPeers.remove(toRemove);
|
reportedPeers.remove(toRemove);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue