diff --git a/common/pom.xml b/common/pom.xml
index 5e2c8619b09..066c24a23e2 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -5,7 +5,7 @@
parentio.bitsquare
- 0.4.9.5
+ 0.4.9.64.0.0
diff --git a/common/src/main/java/io/bitsquare/app/Version.java b/common/src/main/java/io/bitsquare/app/Version.java
index 4adb79695c9..0de3cc0cd72 100644
--- a/common/src/main/java/io/bitsquare/app/Version.java
+++ b/common/src/main/java/io/bitsquare/app/Version.java
@@ -24,7 +24,7 @@ public class Version {
private static final Logger log = LoggerFactory.getLogger(Version.class);
// The application versions
- public static final String VERSION = "0.4.9.5";
+ public static final String VERSION = "0.4.9.6";
// The version nr. for the objects sent over the network. A change will break the serialization of old objects.
// If objects are used for both network and database the network version is applied.
diff --git a/core/pom.xml b/core/pom.xml
index 45dbafb6f39..905f127e131 100755
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -6,7 +6,7 @@
parentio.bitsquare
- 0.4.9.5
+ 0.4.9.6core
diff --git a/core/src/main/java/io/bitsquare/arbitration/DisputeManager.java b/core/src/main/java/io/bitsquare/arbitration/DisputeManager.java
index 253a7327a00..551d62edf02 100644
--- a/core/src/main/java/io/bitsquare/arbitration/DisputeManager.java
+++ b/core/src/main/java/io/bitsquare/arbitration/DisputeManager.java
@@ -62,6 +62,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DisputeManager {
@@ -543,94 +544,94 @@ private void onDisputeResultMessage(DisputeResultMessage disputeResultMessage) {
dispute.setIsClosed(true);
- if (dispute.disputeResultProperty().get() == null) {
- dispute.setDisputeResult(disputeResult);
+ if (dispute.disputeResultProperty().get() != null)
+ log.warn("We got already a dispute result. That should only happen if a dispute needs to be closed " +
+ "again because the first close did not succeed. TradeId = " + tradeId);
- // We need to avoid publishing the tx from both traders as it would create problems with zero confirmation withdrawals
- // There would be different transactions if both sign and publish (signers: once buyer+arb, once seller+arb)
- // The tx publisher is the winner or in case both get 50% the buyer, as the buyer has more inventive to publish the tx as he receives
- // more BTC as he has deposited
- final Contract contract = dispute.getContract();
+ dispute.setDisputeResult(disputeResult);
- boolean isBuyer = keyRing.getPubKeyRing().equals(contract.getBuyerPubKeyRing());
- if ((isBuyer && disputeResult.getWinner() == DisputeResult.Winner.BUYER)
- || (!isBuyer && disputeResult.getWinner() == DisputeResult.Winner.SELLER)
- || (isBuyer && disputeResult.getWinner() == DisputeResult.Winner.STALE_MATE)) {
+ // We need to avoid publishing the tx from both traders as it would create problems with zero confirmation withdrawals
+ // There would be different transactions if both sign and publish (signers: once buyer+arb, once seller+arb)
+ // The tx publisher is the winner or in case both get 50% the buyer, as the buyer has more inventive to publish the tx as he receives
+ // more BTC as he has deposited
+ final Contract contract = dispute.getContract();
+ boolean isBuyer = keyRing.getPubKeyRing().equals(contract.getBuyerPubKeyRing());
+ if ((isBuyer && disputeResult.getWinner() == DisputeResult.Winner.BUYER)
+ || (!isBuyer && disputeResult.getWinner() == DisputeResult.Winner.SELLER)
+ || (isBuyer && disputeResult.getWinner() == DisputeResult.Winner.STALE_MATE)) {
- final Optional tradeOptional = tradeManager.getTradeById(tradeId);
- Transaction payoutTx = null;
- if (tradeOptional.isPresent()) {
- payoutTx = tradeOptional.get().getPayoutTx();
- } else {
- final Optional tradableOptional = closedTradableManager.getTradableById(tradeId);
- if (tradableOptional.isPresent() && tradableOptional.get() instanceof Trade) {
- payoutTx = ((Trade) tradableOptional.get()).getPayoutTx();
- }
- }
- if (payoutTx == null) {
- if (dispute.getDepositTxSerialized() != null) {
- try {
- log.debug("do payout Transaction ");
-
- Transaction signedDisputedPayoutTx = tradeWalletService.traderSignAndFinalizeDisputedPayoutTx(
- dispute.getDepositTxSerialized(),
- disputeResult.getArbitratorSignature(),
- disputeResult.getBuyerPayoutAmount(),
- disputeResult.getSellerPayoutAmount(),
- disputeResult.getArbitratorPayoutAmount(),
- contract.getBuyerPayoutAddressString(),
- contract.getSellerPayoutAddressString(),
- disputeResult.getArbitratorAddressAsString(),
- walletService.getOrCreateAddressEntry(dispute.getTradeId(), AddressEntry.Context.MULTI_SIG),
- contract.getBuyerBtcPubKey(),
- contract.getSellerBtcPubKey(),
- disputeResult.getArbitratorPubKey()
- );
- Transaction committedDisputedPayoutTx = tradeWalletService.addTransactionToWallet(signedDisputedPayoutTx);
- log.debug("broadcast committedDisputedPayoutTx");
- tradeWalletService.broadcastTx(committedDisputedPayoutTx, new FutureCallback() {
- @Override
- public void onSuccess(Transaction transaction) {
- log.debug("BroadcastTx succeeded. Transaction:" + transaction);
-
- // after successful publish we send peer the tx
-
- dispute.setDisputePayoutTxId(transaction.getHashAsString());
- sendPeerPublishedPayoutTxMessage(transaction, dispute, contract);
-
- // set state after payout as we call swapTradeEntryToAvailableEntry
- if (tradeManager.getTradeById(dispute.getTradeId()).isPresent())
- tradeManager.closeDisputedTrade(dispute.getTradeId());
- else {
- Optional openOfferOptional = openOfferManager.getOpenOfferById(dispute.getTradeId());
- if (openOfferOptional.isPresent())
- openOfferManager.closeOpenOffer(openOfferOptional.get().getOffer());
- }
- }
+ final Optional tradeOptional = tradeManager.getTradeById(tradeId);
+ Transaction payoutTx = null;
+ if (tradeOptional.isPresent()) {
+ payoutTx = tradeOptional.get().getPayoutTx();
+ } else {
+ final Optional tradableOptional = closedTradableManager.getTradableById(tradeId);
+ if (tradableOptional.isPresent() && tradableOptional.get() instanceof Trade) {
+ payoutTx = ((Trade) tradableOptional.get()).getPayoutTx();
+ }
+ }
- @Override
- public void onFailure(@NotNull Throwable t) {
- log.error(t.getMessage());
+ if (payoutTx == null) {
+ if (dispute.getDepositTxSerialized() != null) {
+ try {
+ log.debug("do payout Transaction ");
+
+ Transaction signedDisputedPayoutTx = tradeWalletService.traderSignAndFinalizeDisputedPayoutTx(
+ dispute.getDepositTxSerialized(),
+ disputeResult.getArbitratorSignature(),
+ disputeResult.getBuyerPayoutAmount(),
+ disputeResult.getSellerPayoutAmount(),
+ disputeResult.getArbitratorPayoutAmount(),
+ contract.getBuyerPayoutAddressString(),
+ contract.getSellerPayoutAddressString(),
+ disputeResult.getArbitratorAddressAsString(),
+ walletService.getOrCreateAddressEntry(dispute.getTradeId(), AddressEntry.Context.MULTI_SIG),
+ contract.getBuyerBtcPubKey(),
+ contract.getSellerBtcPubKey(),
+ disputeResult.getArbitratorPubKey()
+ );
+ Transaction committedDisputedPayoutTx = tradeWalletService.addTransactionToWallet(signedDisputedPayoutTx);
+ log.debug("broadcast committedDisputedPayoutTx");
+ tradeWalletService.broadcastTx(committedDisputedPayoutTx, new FutureCallback() {
+ @Override
+ public void onSuccess(Transaction transaction) {
+ log.debug("BroadcastTx succeeded. Transaction:" + transaction);
+
+ // after successful publish we send peer the tx
+
+ dispute.setDisputePayoutTxId(transaction.getHashAsString());
+ sendPeerPublishedPayoutTxMessage(transaction, dispute, contract);
+
+ // set state after payout as we call swapTradeEntryToAvailableEntry
+ if (tradeManager.getTradeById(dispute.getTradeId()).isPresent())
+ tradeManager.closeDisputedTrade(dispute.getTradeId());
+ else {
+ Optional openOfferOptional = openOfferManager.getOpenOfferById(dispute.getTradeId());
+ if (openOfferOptional.isPresent())
+ openOfferManager.closeOpenOffer(openOfferOptional.get().getOffer());
}
- });
- } catch (AddressFormatException | WalletException | TransactionVerificationException e) {
- e.printStackTrace();
- log.error("Error at traderSignAndFinalizeDisputedPayoutTx " + e.getMessage());
- }
- } else {
- log.warn("DepositTx is null. TradeId = " + tradeId);
+ }
+
+ @Override
+ public void onFailure(@NotNull Throwable t) {
+ log.error(t.getMessage());
+ }
+ });
+ } catch (AddressFormatException | WalletException | TransactionVerificationException e) {
+ e.printStackTrace();
+ log.error("Error at traderSignAndFinalizeDisputedPayoutTx " + e.getMessage());
}
} else {
- log.warn("We got already a payout tx. That might be the case if the other peer did not get the " +
- "payout tx and opened a dispute. TradeId = " + tradeId);
- dispute.setDisputePayoutTxId(payoutTx.getHashAsString());
- sendPeerPublishedPayoutTxMessage(payoutTx, dispute, contract);
+ log.warn("DepositTx is null. TradeId = " + tradeId);
}
+ } else {
+ log.warn("We got already a payout tx. That might be the case if the other peer did not get the " +
+ "payout tx and opened a dispute. TradeId = " + tradeId);
+ dispute.setDisputePayoutTxId(payoutTx.getHashAsString());
+ sendPeerPublishedPayoutTxMessage(payoutTx, dispute, contract);
}
- } else {
- log.warn("We got a dispute msg what we have already stored. TradeId = " + tradeId);
}
} else {
log.debug("We got a dispute result msg but we don't have a matching dispute. " +
@@ -699,6 +700,23 @@ private boolean isArbitrator(DisputeResult disputeResult) {
return disputeResult.getArbitratorAddressAsString().equals(walletService.getOrCreateAddressEntry(AddressEntry.Context.ARBITRATOR).getAddressString());
}
+ public String getNrOfDisputes(boolean isBuyer, Contract contract) {
+ return String.valueOf(getDisputesAsObservableList().stream()
+ .filter(e -> {
+ Contract contract1 = e.getContract();
+ if (contract1 == null)
+ return false;
+
+ if (isBuyer) {
+ NodeAddress buyerNodeAddress = contract1.getBuyerNodeAddress();
+ return buyerNodeAddress != null && buyerNodeAddress.equals(contract.getBuyerNodeAddress());
+ } else {
+ NodeAddress sellerNodeAddress = contract1.getSellerNodeAddress();
+ return sellerNodeAddress != null && sellerNodeAddress.equals(contract.getSellerNodeAddress());
+ }
+ })
+ .collect(Collectors.toSet()).size());
+ }
///////////////////////////////////////////////////////////////////////////////////////////
// Utils
diff --git a/core/src/main/java/io/bitsquare/arbitration/DisputeResult.java b/core/src/main/java/io/bitsquare/arbitration/DisputeResult.java
index a7a059023b2..7cf0fdba4ab 100644
--- a/core/src/main/java/io/bitsquare/arbitration/DisputeResult.java
+++ b/core/src/main/java/io/bitsquare/arbitration/DisputeResult.java
@@ -25,6 +25,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.Nullable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Arrays;
@@ -47,18 +48,27 @@ public enum Winner {
STALE_MATE
}
+ // only append new values as we use the ordinal value
public enum Reason {
BUG,
USABILITY,
SCAM,
- OTHER
+ OTHER,
+ PROTOCOL_VIOLATION,
+ NO_REPLY
}
public final String tradeId;
public final int traderId;
private DisputeFeePolicy disputeFeePolicy;
private Winner winner;
+
+ // Keep it for backward compatibility but use reasonOrdinal to allow changes in the ENum without breaking serialisation
+ @Deprecated
+ @Nullable
private Reason reason;
+ private int reasonOrdinal = Reason.OTHER.ordinal();
+
private boolean tamperProofEvidence;
private boolean idVerification;
private boolean screenCast;
@@ -145,17 +155,20 @@ public DisputeFeePolicy getDisputeFeePolicy() {
}
public void setReason(Reason reason) {
- this.reason = reason;
+ this.reasonOrdinal = reason.ordinal();
}
public Reason getReason() {
- return reason;
+ if (reasonOrdinal < Reason.values().length)
+ return Reason.values()[reasonOrdinal];
+ else
+ return Reason.OTHER;
}
public void setSummaryNotes(String summaryNotes) {
this.summaryNotesProperty.set(summaryNotes);
}
-
+
public StringProperty summaryNotesProperty() {
return summaryNotesProperty;
}
@@ -249,6 +262,7 @@ public boolean equals(Object o) {
if (closeDate != that.closeDate) return false;
if (tradeId != null ? !tradeId.equals(that.tradeId) : that.tradeId != null) return false;
if (disputeFeePolicy != that.disputeFeePolicy) return false;
+ if (reasonOrdinal != that.reasonOrdinal) return false;
if (reason != that.reason) return false;
if (disputeFeePolicy != null && that.disputeFeePolicy != null && disputeFeePolicy.ordinal() != that.disputeFeePolicy.ordinal())
@@ -265,7 +279,7 @@ else if ((reason == null && that.reason != null) || (reason != null && that.reas
return false;
else if ((winner == null && that.winner != null) || (winner != null && that.winner == null))
return false;
-
+
if (summaryNotes != null ? !summaryNotes.equals(that.summaryNotes) : that.summaryNotes != null) return false;
if (disputeCommunicationMessage != null ? !disputeCommunicationMessage.equals(that.disputeCommunicationMessage) : that.disputeCommunicationMessage != null)
return false;
@@ -282,6 +296,7 @@ public int hashCode() {
int result = tradeId != null ? tradeId.hashCode() : 0;
result = 31 * result + traderId;
result = 31 * result + (disputeFeePolicy != null ? disputeFeePolicy.ordinal() : 0);
+ result = 31 * result + reasonOrdinal;
result = 31 * result + (reason != null ? reason.ordinal() : 0);
result = 31 * result + (winner != null ? winner.ordinal() : 0);
result = 31 * result + (tamperProofEvidence ? 1 : 0);
diff --git a/core/src/main/java/io/bitsquare/btc/AddressEntry.java b/core/src/main/java/io/bitsquare/btc/AddressEntry.java
index 38663c644d2..9b4ca524e46 100644
--- a/core/src/main/java/io/bitsquare/btc/AddressEntry.java
+++ b/core/src/main/java/io/bitsquare/btc/AddressEntry.java
@@ -93,8 +93,21 @@ public AddressEntry(@Nullable DeterministicKey keyPair, NetworkParameters params
this.keyPair = keyPair;
this.params = params;
this.context = context;
- this.offerId = offerId;
+ // We got some issues that users created offers with a dev version where we added the version nr after
+ // the id, but we reverted that as it caused issues. To avoid ongoing issues with those dangling offers
+ // we add that check.
+ // TODO remove after version 0.4.9.7 (if no offers with that invalid id are online anymore)
+ if (offerId != null) {
+ String[] tokens = offerId.split("_");
+ if (tokens.length > 1)
+ this.offerId = tokens[0];
+ else
+ this.offerId = offerId;
+ } else {
+ this.offerId = null;
+ }
+
paramId = params.getId();
checkNotNull(keyPair);
@@ -130,13 +143,26 @@ public void setDeterministicKey(DeterministicKey deterministicKey) {
@Nullable
public String getOfferId() {
- return offerId;
+ // We got some issues that users created offers with a dev version where we added the version nr after
+ // the id, but we reverted that as it caused issues. To avoid ongoing issues with those dangling offers
+ // we add that check.
+ // TODO remove after version 0.4.9.7 (if no offers with that invalid id are online anymore)
+ if (offerId != null) {
+ String[] tokens = offerId.split("_");
+
+ if (tokens.length > 1)
+ return tokens[0];
+ else
+ return offerId;
+ } else {
+ return null;
+ }
}
// For display we usually only display the first 8 characters.
@Nullable
public String getShortOfferId() {
- return offerId != null ? offerId.substring(0, Math.min(8, offerId.length())) : null;
+ return getOfferId() != null ? getOfferId().substring(0, Math.min(8, getOfferId().length())) : null;
}
public Context getContext() {
@@ -190,7 +216,7 @@ public Coin getLockedTradeAmount() {
@Override
public String toString() {
return "AddressEntry{" +
- "offerId='" + offerId + '\'' +
+ "offerId='" + getOfferId() + '\'' +
", context=" + context +
", address=" + getAddressString() +
'}';
diff --git a/core/src/main/java/io/bitsquare/locale/CurrencyUtil.java b/core/src/main/java/io/bitsquare/locale/CurrencyUtil.java
index 51c93054f23..dc717f286d1 100644
--- a/core/src/main/java/io/bitsquare/locale/CurrencyUtil.java
+++ b/core/src/main/java/io/bitsquare/locale/CurrencyUtil.java
@@ -158,6 +158,8 @@ public static List createAllSortedCryptoCurrenciesList() {
result.add(new CryptoCurrency("1CR", "1CRedit"));
result.add(new CryptoCurrency("YACC", "YACCoin"));
result.add(new CryptoCurrency("AIB", "Advanced Internet Blocks"));
+ result.add(new CryptoCurrency("OPAL", "Opal"));
+ result.add(new CryptoCurrency("AMP", "Synereo", true));
result.sort(TradeCurrency::compareTo);
return result;
diff --git a/core/src/main/java/io/bitsquare/payment/CashDepositAccount.java b/core/src/main/java/io/bitsquare/payment/CashDepositAccount.java
index a2319416f7b..ef94e8f8fc9 100644
--- a/core/src/main/java/io/bitsquare/payment/CashDepositAccount.java
+++ b/core/src/main/java/io/bitsquare/payment/CashDepositAccount.java
@@ -19,6 +19,8 @@
import io.bitsquare.app.Version;
+import javax.annotation.Nullable;
+
public final class CashDepositAccount extends CountryBasedPaymentAccount implements SameCountryRestrictedBankAccount {
// That object is saved to disc. We need to take care of changes to not break deserialization.
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
@@ -41,4 +43,13 @@ public String getBankId() {
public String getCountryCode() {
return getCountry() != null ? getCountry().code : "";
}
+
+ @Nullable
+ public String getRequirements() {
+ return ((CashDepositAccountContractData) contractData).getRequirements();
+ }
+
+ public void setRequirements(String requirements) {
+ ((CashDepositAccountContractData) contractData).setRequirements(requirements);
+ }
}
diff --git a/core/src/main/java/io/bitsquare/payment/CashDepositAccountContractData.java b/core/src/main/java/io/bitsquare/payment/CashDepositAccountContractData.java
index df785450430..3a0d25c1ad3 100644
--- a/core/src/main/java/io/bitsquare/payment/CashDepositAccountContractData.java
+++ b/core/src/main/java/io/bitsquare/payment/CashDepositAccountContractData.java
@@ -38,7 +38,8 @@ public class CashDepositAccountContractData extends CountryBasedPaymentAccountCo
protected String branchId;
protected String accountNr;
protected String accountType;
-
+ @Nullable
+ protected String requirements;
@Nullable
protected String holderTaxId;
@@ -59,6 +60,7 @@ public String getPaymentDetailsForTradePopup() {
String accountNr = BankUtil.isAccountNrRequired(countryCode) ? BankUtil.getAccountNrLabel(countryCode) + " " + this.accountNr + "\n" : "";
String accountType = BankUtil.isAccountTypeRequired(countryCode) ? BankUtil.getAccountTypeLabel(countryCode) + " " + this.accountType + "\n" : "";
String holderIdString = BankUtil.isHolderIdRequired(countryCode) ? (BankUtil.getHolderIdLabel(countryCode) + " " + holderTaxId + "\n") : "";
+ String requirementsString = requirements != null && !requirements.isEmpty() ? ("Extra requirements: " + requirements + "\n") : "";
return "Holder name: " + holderName + "\n" +
"Holder email: " + holderEmail + "\n" +
@@ -68,6 +70,7 @@ public String getPaymentDetailsForTradePopup() {
accountNr +
accountType +
holderIdString +
+ requirementsString +
"Country of bank: " + CountryUtil.getNameAndCode(getCountryCode());
}
@@ -145,4 +148,14 @@ public void setAccountType(String accountType) {
public String getAccountType() {
return accountType;
}
+
+ @Nullable
+ public String getRequirements() {
+ return requirements;
+ }
+
+ public void setRequirements(String requirements) {
+ this.requirements = requirements;
+ }
+
}
diff --git a/core/src/main/java/io/bitsquare/payment/FasterPaymentsAccount.java b/core/src/main/java/io/bitsquare/payment/FasterPaymentsAccount.java
new file mode 100644
index 00000000000..4bfd97ab406
--- /dev/null
+++ b/core/src/main/java/io/bitsquare/payment/FasterPaymentsAccount.java
@@ -0,0 +1,52 @@
+/*
+ * This file is part of Bitsquare.
+ *
+ * Bitsquare is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Bitsquare is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Bitsquare. If not, see .
+ */
+
+package io.bitsquare.payment;
+
+import io.bitsquare.app.Version;
+import io.bitsquare.locale.FiatCurrency;
+
+public final class FasterPaymentsAccount extends PaymentAccount {
+ // That object is saved to disc. We need to take care of changes to not break deserialization.
+ private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
+
+ public FasterPaymentsAccount() {
+ super(PaymentMethod.FASTER_PAYMENTS);
+ setSingleTradeCurrency(new FiatCurrency("GBP"));
+ }
+
+ @Override
+ protected PaymentAccountContractData setContractData() {
+ return new FasterPaymentsAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
+ }
+
+ public void setSortCode(String value) {
+ ((FasterPaymentsAccountContractData) contractData).setSortCode(value);
+ }
+
+ public String getSortCode() {
+ return ((FasterPaymentsAccountContractData) contractData).getSortCode();
+ }
+
+ public void setAccountNr(String value) {
+ ((FasterPaymentsAccountContractData) contractData).setAccountNr(value);
+ }
+
+ public String getAccountNr() {
+ return ((FasterPaymentsAccountContractData) contractData).getAccountNr();
+ }
+}
diff --git a/core/src/main/java/io/bitsquare/payment/FasterPaymentsAccountContractData.java b/core/src/main/java/io/bitsquare/payment/FasterPaymentsAccountContractData.java
new file mode 100644
index 00000000000..98b749c2914
--- /dev/null
+++ b/core/src/main/java/io/bitsquare/payment/FasterPaymentsAccountContractData.java
@@ -0,0 +1,59 @@
+/*
+ * This file is part of Bitsquare.
+ *
+ * Bitsquare is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Bitsquare is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Bitsquare. If not, see .
+ */
+
+package io.bitsquare.payment;
+
+import io.bitsquare.app.Version;
+
+public final class FasterPaymentsAccountContractData extends PaymentAccountContractData {
+ // That object is sent over the wire, so we need to take care of version compatibility.
+ private static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
+
+ private String sortCode;
+ private String accountNr;
+
+ public FasterPaymentsAccountContractData(String paymentMethod, String id, long maxTradePeriod) {
+ super(paymentMethod, id, maxTradePeriod);
+ }
+
+ public void setAccountNr(String accountNr) {
+ this.accountNr = accountNr;
+ }
+
+ public String getAccountNr() {
+ return accountNr;
+ }
+
+ public String getSortCode() {
+ return sortCode;
+ }
+
+ public void setSortCode(String sortCode) {
+ this.sortCode = sortCode;
+ }
+
+ @Override
+ public String getPaymentDetails() {
+ return "FasterPayments - UK Sort code: " + sortCode + ", Account number: " + accountNr;
+ }
+
+ @Override
+ public String getPaymentDetailsForTradePopup() {
+ return "UK Sort code: " + sortCode + "\n" +
+ "Account number: " + accountNr;
+ }
+}
diff --git a/core/src/main/java/io/bitsquare/payment/PaymentAccountFactory.java b/core/src/main/java/io/bitsquare/payment/PaymentAccountFactory.java
index c519f522222..397fa09a9ac 100644
--- a/core/src/main/java/io/bitsquare/payment/PaymentAccountFactory.java
+++ b/core/src/main/java/io/bitsquare/payment/PaymentAccountFactory.java
@@ -31,6 +31,8 @@ public static PaymentAccount getPaymentAccount(PaymentMethod paymentMethod) {
return new PerfectMoneyAccount();
case PaymentMethod.SEPA_ID:
return new SepaAccount();
+ case PaymentMethod.FASTER_PAYMENTS_ID:
+ return new FasterPaymentsAccount();
case PaymentMethod.NATIONAL_BANK_ID:
return new NationalBankAccount();
case PaymentMethod.SAME_BANK_ID:
diff --git a/core/src/main/java/io/bitsquare/payment/PaymentMethod.java b/core/src/main/java/io/bitsquare/payment/PaymentMethod.java
index 5ef034f938b..b1a2e7fec69 100644
--- a/core/src/main/java/io/bitsquare/payment/PaymentMethod.java
+++ b/core/src/main/java/io/bitsquare/payment/PaymentMethod.java
@@ -44,6 +44,7 @@ public final class PaymentMethod implements Persistable, Comparable {
public static final String OK_PAY_ID = "OK_PAY";
public static final String PERFECT_MONEY_ID = "PERFECT_MONEY";
public static final String SEPA_ID = "SEPA";
+ public static final String FASTER_PAYMENTS_ID = "FASTER_PAYMENTS";
public static final String NATIONAL_BANK_ID = "NATIONAL_BANK";
public static final String SAME_BANK_ID = "SAME_BANK";
public static final String SPECIFIC_BANKS_ID = "SPECIFIC_BANKS";
@@ -57,6 +58,7 @@ public final class PaymentMethod implements Persistable, Comparable {
public static PaymentMethod OK_PAY;
public static PaymentMethod PERFECT_MONEY;
public static PaymentMethod SEPA;
+ public static PaymentMethod FASTER_PAYMENTS;
public static PaymentMethod NATIONAL_BANK;
public static PaymentMethod SAME_BANK;
public static PaymentMethod SPECIFIC_BANKS;
@@ -70,15 +72,16 @@ public final class PaymentMethod implements Persistable, Comparable {
public static final List ALL_VALUES = new ArrayList<>(Arrays.asList(
OK_PAY = new PaymentMethod(OK_PAY_ID, 0, DAY, Coin.parseCoin("1.5")), // tx instant so min. wait time
SEPA = new PaymentMethod(SEPA_ID, 0, 8 * DAY, Coin.parseCoin("1")), // sepa takes 1-3 business days. We use 8 days to include safety for holidays
+ FASTER_PAYMENTS = new PaymentMethod(FASTER_PAYMENTS_ID, 0, DAY, Coin.parseCoin("1")),
+ CLEAR_X_CHANGE = new PaymentMethod(CLEAR_X_CHANGE_ID, 0, 8 * DAY, Coin.parseCoin("0.5")),
+ SWISH = new PaymentMethod(SWISH_ID, 0, DAY, Coin.parseCoin("1.5")),
NATIONAL_BANK = new PaymentMethod(NATIONAL_BANK_ID, 0, 4 * DAY, Coin.parseCoin("1")),
SAME_BANK = new PaymentMethod(SAME_BANK_ID, 0, 2 * DAY, Coin.parseCoin("1")),
SPECIFIC_BANKS = new PaymentMethod(SPECIFIC_BANKS_ID, 0, 4 * DAY, Coin.parseCoin("1")),
PERFECT_MONEY = new PaymentMethod(PERFECT_MONEY_ID, 0, DAY, Coin.parseCoin("1")),
- SWISH = new PaymentMethod(SWISH_ID, 0, DAY, Coin.parseCoin("1.5")),
ALI_PAY = new PaymentMethod(ALI_PAY_ID, 0, DAY, Coin.parseCoin("1.5")),
- CLEAR_X_CHANGE = new PaymentMethod(CLEAR_X_CHANGE_ID, 0, 8 * DAY, Coin.parseCoin("0.5")),
- US_POSTAL_MONEY_ORDER = new PaymentMethod(US_POSTAL_MONEY_ORDER_ID, 0, 6 * DAY, Coin.parseCoin("0.5")),
CASH_DEPOSIT = new PaymentMethod(CASH_DEPOSIT_ID, 0, 6 * DAY, Coin.parseCoin("0.5")),
+ US_POSTAL_MONEY_ORDER = new PaymentMethod(US_POSTAL_MONEY_ORDER_ID, 0, 6 * DAY, Coin.parseCoin("0.5")),
BLOCK_CHAINS = new PaymentMethod(BLOCK_CHAINS_ID, 0, DAY, Coin.parseCoin("2"))
));
diff --git a/core/src/main/java/io/bitsquare/trade/offer/Offer.java b/core/src/main/java/io/bitsquare/trade/offer/Offer.java
index cb805b94473..68d3e99e0a5 100644
--- a/core/src/main/java/io/bitsquare/trade/offer/Offer.java
+++ b/core/src/main/java/io/bitsquare/trade/offer/Offer.java
@@ -277,7 +277,7 @@ public Fiat getMinOfferVolume() {
}
public String getReferenceText() {
- return id.substring(0, Math.min(8, id.length()));
+ return getId().substring(0, Math.min(8, getId().length()));
}
@@ -348,11 +348,23 @@ public long getProtocolVersion() {
}
public String getId() {
- return id;
+ // We got some issues that users created offers with a dev version where we added the version nr after
+ // the id, but we reverted that as it caused issues. To avoid ongoing issues with those dangling offers
+ // we add that check.
+ // TODO remove after version 0.4.9.7 (if no offers with that invalid id are online anymore)
+ if (id != null) {
+ String[] tokens = id.split("_");
+ if (tokens.length > 1)
+ return tokens[0];
+ else
+ return id;
+ } else {
+ return null;
+ }
}
public String getShortId() {
- return id.substring(0, Math.min(8, id.length()));
+ return getId().substring(0, Math.min(8, getId().length()));
}
public NodeAddress getOffererNodeAddress() {
@@ -513,7 +525,7 @@ public boolean equals(Object o) {
if (useMarketBasedPrice != that.useMarketBasedPrice) return false;
if (amount != that.amount) return false;
if (minAmount != that.minAmount) return false;
- if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
if (direction != null && that.direction != null && direction.ordinal() != that.direction.ordinal())
return false;
@@ -542,7 +554,7 @@ else if ((direction == null && that.direction != null) || (direction != null &&
@Override
public int hashCode() {
- int result = id != null ? id.hashCode() : 0;
+ int result = getId() != null ? getId().hashCode() : 0;
result = 31 * result + (direction != null ? direction.ordinal() : 0);
result = 31 * result + (currencyCode != null ? currencyCode.hashCode() : 0);
result = 31 * result + (int) (date ^ (date >>> 32));
@@ -568,7 +580,7 @@ public int hashCode() {
@Override
public String toString() {
return "Offer{" +
- "\n\tid='" + id + '\'' +
+ "\n\tid='" + getId() + '\'' +
"\n\tdirection=" + direction +
"\n\tcurrencyCode='" + currencyCode + '\'' +
"\n\tdate=" + new Date(date) +
diff --git a/core/src/main/java/io/bitsquare/trade/statistics/TradeStatistics.java b/core/src/main/java/io/bitsquare/trade/statistics/TradeStatistics.java
index d80cb315e36..948950ade5d 100644
--- a/core/src/main/java/io/bitsquare/trade/statistics/TradeStatistics.java
+++ b/core/src/main/java/io/bitsquare/trade/statistics/TradeStatistics.java
@@ -97,6 +97,18 @@ public Fiat getTradeVolume() {
return new ExchangeRate(getTradePrice()).coinToFiat(getTradeAmount());
}
+ public String getOfferId() {
+ // We got some issues that users created offers with a dev version where we added the version nr after
+ // the id, but we reverted that as it caused issues. To avoid ongoing issues with those dangling offers
+ // we add that check.
+ // TODO remove after version 0.4.9.7 (if no offers with that invalid id are online anymore)
+ String[] tokens = offerId.split("_");
+ if (tokens.length > 1)
+ return tokens[0];
+ else
+ return offerId;
+ }
+
// We don't include the pubKeyRing as both traders might publish it if the offerer uses an old
// version and update later (taker publishes first, then later offerer)
// We also don't include the trade date as that is set locally and different for offerer and taker
@@ -123,7 +135,7 @@ else if ((direction == null && that.direction != null) || (direction != null &&
if (paymentMethod != null ? !paymentMethod.equals(that.paymentMethod) : that.paymentMethod != null)
return false;
- if (offerId != null ? !offerId.equals(that.offerId) : that.offerId != null) return false;
+ if (getOfferId() != null ? !getOfferId().equals(that.getOfferId()) : that.getOfferId() != null) return false;
return !(depositTxId != null ? !depositTxId.equals(that.depositTxId) : that.depositTxId != null);
}
@@ -142,7 +154,7 @@ public int hashCode() {
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + (int) (offerAmount ^ (offerAmount >>> 32));
result = 31 * result + (int) (offerMinAmount ^ (offerMinAmount >>> 32));
- result = 31 * result + (offerId != null ? offerId.hashCode() : 0);
+ result = 31 * result + (getOfferId() != null ? getOfferId().hashCode() : 0);
result = 31 * result + (depositTxId != null ? depositTxId.hashCode() : 0);
return result;
}
@@ -161,7 +173,7 @@ public String toString() {
", marketPriceMargin=" + marketPriceMargin +
", offerAmount=" + offerAmount +
", offerMinAmount=" + offerMinAmount +
- ", offerId='" + offerId + '\'' +
+ ", offerId='" + getOfferId() + '\'' +
", depositTxId='" + depositTxId + '\'' +
", pubKeyRing=" + pubKeyRing +
", hashCode=" + hashCode() +
diff --git a/core/src/main/java/io/bitsquare/trade/statistics/TradeStatisticsForJson.java b/core/src/main/java/io/bitsquare/trade/statistics/TradeStatisticsForJson.java
index e6cefd2f320..9a8528b1621 100644
--- a/core/src/main/java/io/bitsquare/trade/statistics/TradeStatisticsForJson.java
+++ b/core/src/main/java/io/bitsquare/trade/statistics/TradeStatisticsForJson.java
@@ -54,7 +54,7 @@ public TradeStatisticsForJson(TradeStatistics tradeStatistics) {
this.marketPriceMargin = tradeStatistics.marketPriceMargin;
this.offerAmount = tradeStatistics.offerAmount;
this.offerMinAmount = tradeStatistics.offerMinAmount;
- this.offerId = tradeStatistics.offerId;
+ this.offerId = tradeStatistics.getOfferId();
this.tradePrice = tradeStatistics.tradePrice;
this.tradeAmount = tradeStatistics.tradeAmount;
this.tradeDate = tradeStatistics.tradeDate;
diff --git a/core/src/main/java/io/bitsquare/trade/statistics/TradeStatisticsManager.java b/core/src/main/java/io/bitsquare/trade/statistics/TradeStatisticsManager.java
index a3e1dd2e9ea..c0eff3d91d8 100644
--- a/core/src/main/java/io/bitsquare/trade/statistics/TradeStatisticsManager.java
+++ b/core/src/main/java/io/bitsquare/trade/statistics/TradeStatisticsManager.java
@@ -95,7 +95,7 @@ public void onRemoved(ProtectedStorageEntry data) {
public void add(TradeStatistics tradeStatistics) {
if (!tradeStatisticsSet.contains(tradeStatistics)) {
- boolean itemAlreadyAdded = tradeStatisticsSet.stream().filter(e -> (e.offerId.equals(tradeStatistics.offerId))).findAny().isPresent();
+ boolean itemAlreadyAdded = tradeStatisticsSet.stream().filter(e -> (e.getOfferId().equals(tradeStatistics.getOfferId()))).findAny().isPresent();
if (!itemAlreadyAdded) {
tradeStatisticsSet.add(tradeStatistics);
observableTradeStatisticsSet.add(tradeStatistics);
diff --git a/doc/build.md b/doc/build.md
index e04ec0bad06..0034ad4cb7e 100644
--- a/doc/build.md
+++ b/doc/build.md
@@ -73,11 +73,11 @@ You need to get the Bitsquare dependencies first as we need to copy the BountyCa
### 4. Copy the jdkfix jar file
-Copy the jdkfix-0.4.9.5.jar from the Bitsquare jdkfix/target directory to $JAVA_HOME/jre/lib/ext/.
-jdkfix-0.4.9.5.jar includes a bugfix of the SortedList class which will be released with the next JDK version.
+Copy the jdkfix-0.4.9.6.jar from the Bitsquare jdkfix/target directory to $JAVA_HOME/jre/lib/ext/.
+jdkfix-0.4.9.6.jar includes a bugfix of the SortedList class which will be released with the next JDK version.
We need to load that class before the default java class. This step will be removed once the bugfix is in the official JDK.
- $ sudo cp bitsquare/jdkfix/target/jdkfix-0.4.9.5.jar $JAVA_HOME/jre/lib/ext/jdkfix-0.4.9.5.jar
+ $ sudo cp bitsquare/jdkfix/target/jdkfix-0.4.9.6.jar $JAVA_HOME/jre/lib/ext/jdkfix-0.4.9.6.jar
### 5. Copy the BountyCastle provider jar file
diff --git a/doc/install_on_unix.sh b/doc/install_on_unix.sh
index 5c8b696c6ec..bab05578139 100755
--- a/doc/install_on_unix.sh
+++ b/doc/install_on_unix.sh
@@ -36,7 +36,7 @@ cd bitsquare
mvn clean package -DskipTests -Dmaven.javadoc.skip=true
echo "Copy the jdkfix jar file"
-cp bitsquare/jdkfix/target/jdkfix-0.4.9.5.jar $JAVA_HOME/jre/lib/ext/jdkfix-0.4.9.5.jar
+cp bitsquare/jdkfix/target/jdkfix-0.4.9.6.jar $JAVA_HOME/jre/lib/ext/jdkfix-0.4.9.6.jar
echo "Add BountyCastle.jar"
cd ~
diff --git a/gui/pom.xml b/gui/pom.xml
index 7447db6326a..ce6db9c02a3 100644
--- a/gui/pom.xml
+++ b/gui/pom.xml
@@ -22,7 +22,7 @@
parentio.bitsquare
- 0.4.9.5
+ 0.4.9.64.0.0
diff --git a/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/BankForm.java b/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/BankForm.java
index bb25d655793..ac59f9392b3 100644
--- a/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/BankForm.java
+++ b/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/BankForm.java
@@ -50,7 +50,6 @@ abstract class BankForm extends PaymentMethodForm {
protected final BankAccountContractData bankAccountContractData;
private InputTextField bankNameInputTextField, bankIdInputTextField, branchIdInputTextField, accountNrInputTextField, holderIdInputTextField;
- private TextField currencyTextField;
private Label holderIdLabel;
protected InputTextField holderNameInputTextField;
private Label bankIdLabel;
@@ -66,6 +65,8 @@ abstract class BankForm extends PaymentMethodForm {
private boolean validatorsApplied;
private boolean useHolderID;
private Runnable closeHandler;
+ private ComboBox currencyComboBox;
+
static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
BankAccountContractData data = (BankAccountContractData) paymentAccountContractData;
String countryCode = ((BankAccountContractData) paymentAccountContractData).getCountryCode();
@@ -231,8 +232,6 @@ public void addFormForAddAccount() {
gridRowFrom = gridRow + 1;
Tuple3