Tests for Payment accounts matches

This commit is contained in:
Manfred Karrer 2016-03-10 14:06:00 +01:00
parent 94288021dd
commit 44445cd411
50 changed files with 863 additions and 236 deletions

View File

@ -63,7 +63,7 @@ public class Log {
logbackLogger = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
//TODO for now use always trace
logbackLogger.setLevel(useDetailedLogging ? Level.TRACE : Level.WARN);
logbackLogger.setLevel(useDetailedLogging ? Level.TRACE : Level.TRACE);
// logbackLogger.setLevel(useDetailedLogging ? Level.TRACE : Level.DEBUG);
logbackLogger.addAppender(appender);
}

View File

@ -8,7 +8,6 @@ public class ProgramArguments {
// program arg names
public static final String TOR_DIR = "torDir";
public static final String USE_LOCALHOST = "useLocalhost";
public static final String DEV_TEST = "devTest";
public static final String NAME_KEY = "node.name";

View File

@ -44,7 +44,7 @@ public class AlertManager {
private final ObjectProperty<Alert> alertMessageProperty = new SimpleObjectProperty<>();
// Pub key for developer global alert message
private static final String devPubKeyAsHex = "02682880ae61fc1ea9375198bf2b5594fc3ed28074d3f5f0ed907e38acc5fb1fdc";
private static final String pubKeyAsHex = "036d8a1dfcb406886037d2381da006358722823e1940acc2598c844bbc0fd1026f";
private ECKey alertSigningKey;
@ -116,7 +116,7 @@ public class AlertManager {
private boolean isKeyValid(String privKeyString) {
try {
alertSigningKey = ECKey.fromPrivate(new BigInteger(1, HEX.decode(privKeyString)));
return devPubKeyAsHex.equals(Utils.HEX.encode(alertSigningKey.getPubKey()));
return pubKeyAsHex.equals(Utils.HEX.encode(alertSigningKey.getPubKey()));
} catch (Throwable t) {
return false;
}
@ -131,7 +131,7 @@ public class AlertManager {
private boolean verifySignature(Alert alert) {
String alertMessageAsHex = Utils.HEX.encode(alert.message.getBytes());
try {
ECKey.fromPublicOnly(HEX.decode(devPubKeyAsHex)).verifyMessage(alertMessageAsHex, alert.getSignatureAsBase64());
ECKey.fromPublicOnly(HEX.decode(pubKeyAsHex)).verifyMessage(alertMessageAsHex, alert.getSignatureAsBase64());
return true;
} catch (SignatureException e) {
log.warn("verifySignature failed");

View File

@ -18,8 +18,6 @@
package io.bitsquare.arbitration;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import io.bitsquare.app.ProgramArguments;
import io.bitsquare.common.Timer;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.crypto.KeyRing;
@ -63,13 +61,11 @@ public class ArbitratorManager {
private static final long RETRY_REPUBLISH_SEC = 5;
private static final long REPEATED_REPUBLISH_AT_STARTUP_SEC = 60;
private static final String publicKeyForTesting = "027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee";
// Keys for invited arbitrators in bootstrapping phase (before registration is open to anyone and security payment is implemented)
// For testing purpose here is a private key so anyone can setup an arbitrator for now.
// The matching pubkey will be removed once we use real arbitrators.
// PrivKey for testing: 6ac43ea1df2a290c1c8391736aa42e4339c5cb4f110ff0257a13b63211977b7a
// Matching pubKey: 027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee
// For developers we add here 2 test keys so one can setup an arbitrator by adding that test pubKey
// to the publicKeys list and use the test PrivKey for arbitrator registration.
// PrivKey for dev testing: 6ac43ea1df2a290c1c8391736aa42e4339c5cb4f110ff0257a13b63211977b7a
// Matching pubKey for dev testing: 027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee
private static final List<String> publicKeys = new ArrayList<>(Arrays.asList(
"03697a499d24f497b3c46bf716318231e46c4e6a685a4e122d8e2a2b229fa1f4b8",
"0365c6af94681dbee69de1851f98d4684063bf5c2d64b1c73ed5d90434f375a054",
@ -87,8 +83,7 @@ public class ArbitratorManager {
"03df837a3a0f3d858e82f3356b71d1285327f101f7c10b404abed2abc1c94e7169",
"0203a90fb2ab698e524a5286f317a183a84327b8f8c3f7fa4a98fec9e1cefd6b72",
"023c99cc073b851c892d8c43329ca3beb5d2213ee87111af49884e3ce66cbd5ba5",
"0274f772a98d23e7a0251ab30d7121897b5aebd11a2f1e45ab654aa57503173245",
"036d8a1dfcb406886037d2381da006358722823e1940acc2598c844bbc0fd1026f"
"0274f772a98d23e7a0251ab30d7121897b5aebd11a2f1e45ab654aa57503173245"
));
@ -100,7 +95,6 @@ public class ArbitratorManager {
private final ArbitratorService arbitratorService;
private final User user;
private final ObservableMap<NodeAddress, Arbitrator> arbitratorsObservableMap = FXCollections.observableHashMap();
private final boolean isDevTest;
private BootstrapListener bootstrapListener;
private Timer republishArbitratorTimer, retryRepublishArbitratorTimer;
@ -110,8 +104,7 @@ public class ArbitratorManager {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public ArbitratorManager(@Named(ProgramArguments.DEV_TEST) boolean isDevTest, KeyRing keyRing, ArbitratorService arbitratorService, User user) {
this.isDevTest = isDevTest;
public ArbitratorManager(KeyRing keyRing, ArbitratorService arbitratorService, User user) {
this.keyRing = keyRing;
this.arbitratorService = arbitratorService;
this.user = user;
@ -242,7 +235,7 @@ public class ArbitratorManager {
}
public boolean isPublicKeyInList(String pubKeyAsHex) {
return isDevTest && pubKeyAsHex.equals(publicKeyForTesting) || publicKeys.contains(pubKeyAsHex);
return publicKeys.contains(pubKeyAsHex);
}

View File

@ -18,9 +18,7 @@
package io.bitsquare.arbitration;
import com.google.inject.Singleton;
import com.google.inject.name.Names;
import io.bitsquare.app.AppModule;
import io.bitsquare.app.ProgramArguments;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
@ -37,8 +35,5 @@ public class ArbitratorModule extends AppModule {
bind(ArbitratorManager.class).in(Singleton.class);
bind(DisputeManager.class).in(Singleton.class);
bind(ArbitratorService.class).in(Singleton.class);
Boolean devTest = env.getProperty(ProgramArguments.DEV_TEST, boolean.class, false);
bind(boolean.class).annotatedWith(Names.named(ProgramArguments.DEV_TEST)).toInstance(devTest);
}
}

View File

@ -0,0 +1,5 @@
package io.bitsquare.payment;
public interface BankAccount {
String getBankId();
}

View File

@ -23,7 +23,9 @@ import io.bitsquare.locale.CountryUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class BankAccountContractData extends PaymentAccountContractData {
import javax.annotation.Nullable;
public abstract class BankAccountContractData extends CountryBasedPaymentAccountContractData {
// 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;
@ -34,7 +36,9 @@ public abstract class BankAccountContractData extends PaymentAccountContractData
protected String bankId;
protected String branchId;
protected String accountNr;
protected String holderId;
@Nullable
protected String holderTaxId;
public BankAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
super(paymentMethod, id, maxTradePeriod);
@ -47,7 +51,7 @@ public abstract class BankAccountContractData extends PaymentAccountContractData
@Override
public String getPaymentDetailsForTradePopup() {
String holderIdString = BankUtil.requiresHolderId(countryCode) ? (getHolderIdLabel() + ": " + holderId + "\n") : "";
String holderIdString = BankUtil.requiresHolderId(countryCode) ? (getHolderIdLabel() + ": " + holderTaxId + "\n") : "";
return "Holder name: " + holderName + "\n" +
"Bank name: " + bankName + "\n" +
"Bank Nr.: " + bankId + "\n" +
@ -98,12 +102,13 @@ public abstract class BankAccountContractData extends PaymentAccountContractData
this.accountNr = accountNr;
}
public String getHolderId() {
return holderId;
@Nullable
public String getHolderTaxId() {
return holderTaxId;
}
public void setHolderId(String holderId) {
this.holderId = holderId;
public void setHolderTaxId(String holderTaxId) {
this.holderTaxId = holderTaxId;
}
public String getHolderIdLabel() {

View File

@ -0,0 +1,5 @@
package io.bitsquare.payment;
public interface BankNameRestrictedBankAccount extends BankAccount {
}

View File

@ -0,0 +1,88 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.payment;
import io.bitsquare.app.Version;
import io.bitsquare.locale.Country;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
public abstract class CountryBasedPaymentAccount 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;
private static final Logger log = LoggerFactory.getLogger(CountryBasedPaymentAccount.class);
@Nullable
protected Country country;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
protected CountryBasedPaymentAccount(PaymentMethod paymentMethod) {
super(paymentMethod);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter, Setter
///////////////////////////////////////////////////////////////////////////////////////////
@Nullable
public Country getCountry() {
return country;
}
public void setCountry(@NotNull Country country) {
this.country = country;
((CountryBasedPaymentAccountContractData) contractData).setCountryCode(country.code);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CountryBasedPaymentAccount)) return false;
if (!super.equals(o)) return false;
CountryBasedPaymentAccount that = (CountryBasedPaymentAccount) o;
return !(country != null ? !country.equals(that.country) : that.country != null);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (country != null ? country.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "CountryBasedPaymentAccount{" +
"country=" + country +
"} " + super.toString();
}
}

View File

@ -0,0 +1,88 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.payment;
import io.bitsquare.app.Version;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
public abstract class CountryBasedPaymentAccountContractData 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;
@Nullable
protected String countryCode;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
CountryBasedPaymentAccountContractData(String paymentMethodName, String id, int maxTradePeriod) {
super(paymentMethodName, id, maxTradePeriod);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter, Setter
///////////////////////////////////////////////////////////////////////////////////////////
public void setCountryCode(@NotNull String countryCode) {
this.countryCode = countryCode;
}
@Nullable
public String getCountryCode() {
return countryCode;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter
///////////////////////////////////////////////////////////////////////////////////////////
abstract public String getPaymentDetails();
abstract public String getPaymentDetailsForTradePopup();
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CountryBasedPaymentAccountContractData)) return false;
if (!super.equals(o)) return false;
CountryBasedPaymentAccountContractData that = (CountryBasedPaymentAccountContractData) o;
return countryCode.equals(that.countryCode);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + countryCode.hashCode();
return result;
}
@Override
public String toString() {
return "CountryBasedPaymentAccountContractData{" +
"countryCode='" + countryCode + '\'' +
"} " + super.toString();
}
}

View File

@ -19,26 +19,26 @@ package io.bitsquare.payment;
import io.bitsquare.app.Version;
public final class BlockChainAccount extends PaymentAccount {
public final class CryptoCurrencyAccount 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 BlockChainAccount() {
public CryptoCurrencyAccount() {
super(PaymentMethod.BLOCK_CHAINS);
}
@Override
protected PaymentAccountContractData setContractData() {
return new BlockChainAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
return new CryptoCurrencyAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
}
public void setAddress(String address) {
((BlockChainAccountContractData) contractData).setAddress(address);
((CryptoCurrencyAccountContractData) contractData).setAddress(address);
}
public String getAddress() {
return ((BlockChainAccountContractData) contractData).getAddress();
return ((CryptoCurrencyAccountContractData) contractData).getAddress();
}
}

View File

@ -19,15 +19,19 @@ package io.bitsquare.payment;
import io.bitsquare.app.Version;
public final class BlockChainAccountContractData extends PaymentAccountContractData {
import javax.annotation.Nullable;
public final class CryptoCurrencyAccountContractData 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 address;
// used in crypto note coins. not supported now but hopefully in future, so leave it for now.
// used in crypto note coins. not supported now but hopefully in future, so leave it for now to avoid
// incompatibility from serialized data.
@Nullable
private String paymentId;
public BlockChainAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
public CryptoCurrencyAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
super(paymentMethod, id, maxTradePeriod);
}
@ -49,10 +53,11 @@ public final class BlockChainAccountContractData extends PaymentAccountContractD
return getPaymentDetails();
}
public void setPaymentId(String paymentId) {
public void setPaymentId(@Nullable String paymentId) {
this.paymentId = paymentId;
}
@Nullable
public String getPaymentId() {
return paymentId;
}

View File

@ -19,7 +19,7 @@ package io.bitsquare.payment;
import io.bitsquare.app.Version;
public final class NationalBankAccount extends PaymentAccount {
public final class NationalBankAccount 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;
@ -31,4 +31,14 @@ public final class NationalBankAccount extends PaymentAccount {
protected PaymentAccountContractData setContractData() {
return new NationalBankAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
}
@Override
public String getBankId() {
return ((BankAccountContractData) contractData).getBankId();
}
@Override
public String getCountryCode() {
return getCountry() != null ? getCountry().code : "";
}
}

View File

@ -22,6 +22,7 @@ import io.bitsquare.locale.CurrencyUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//TODO missing support for selected trade currency
public final class OKPayAccount 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;

View File

@ -25,6 +25,8 @@ public final class OKPayAccountContractData extends PaymentAccountContractData {
private String accountNr;
// TODO refactor PaymentAccountContractData to avoid null values (countryCode, country, selectedTradeCountry)
public OKPayAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
super(paymentMethod, id, maxTradePeriod);
}

View File

@ -19,12 +19,10 @@ package io.bitsquare.payment;
import io.bitsquare.app.Version;
import io.bitsquare.common.persistance.Persistable;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.TradeCurrency;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@ -42,8 +40,6 @@ public abstract class PaymentAccount implements Persistable {
protected String accountName;
final List<TradeCurrency> tradeCurrencies = new ArrayList<>();
protected TradeCurrency selectedTradeCurrency;
@Nullable
protected Country country = null;
public final PaymentAccountContractData contractData;
@ -97,7 +93,7 @@ public abstract class PaymentAccount implements Persistable {
///////////////////////////////////////////////////////////////////////////////////////////
protected abstract PaymentAccountContractData setContractData();
public String getAccountName() {
return accountName;
}
@ -106,16 +102,6 @@ public abstract class PaymentAccount implements Persistable {
this.accountName = accountName;
}
@Nullable
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
contractData.setCountryCode(country.code);
}
public void setSelectedTradeCurrency(TradeCurrency tradeCurrency) {
selectedTradeCurrency = tradeCurrency;
}
@ -158,21 +144,47 @@ public abstract class PaymentAccount implements Persistable {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Util
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PaymentAccount)) return false;
PaymentAccount that = (PaymentAccount) o;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
if (creationDate != null ? !creationDate.equals(that.creationDate) : that.creationDate != null) return false;
if (paymentMethod != null ? !paymentMethod.equals(that.paymentMethod) : that.paymentMethod != null)
return false;
if (accountName != null ? !accountName.equals(that.accountName) : that.accountName != null) return false;
if (tradeCurrencies != null ? !tradeCurrencies.equals(that.tradeCurrencies) : that.tradeCurrencies != null)
return false;
if (selectedTradeCurrency != null ? !selectedTradeCurrency.equals(that.selectedTradeCurrency) : that.selectedTradeCurrency != null)
return false;
return !(contractData != null ? !contractData.equals(that.contractData) : that.contractData != null);
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (creationDate != null ? creationDate.hashCode() : 0);
result = 31 * result + (paymentMethod != null ? paymentMethod.hashCode() : 0);
result = 31 * result + (accountName != null ? accountName.hashCode() : 0);
result = 31 * result + (tradeCurrencies != null ? tradeCurrencies.hashCode() : 0);
result = 31 * result + (selectedTradeCurrency != null ? selectedTradeCurrency.hashCode() : 0);
result = 31 * result + (contractData != null ? contractData.hashCode() : 0);
return result;
}
@Override
public String toString() {
return contractData.toString() + '\'' +
"PaymentAccount{" +
return "PaymentAccount{" +
"id='" + id + '\'' +
", creationDate=" + creationDate +
", paymentMethod=" + paymentMethod +
", accountName='" + accountName + '\'' +
", tradeCurrencies=" + tradeCurrencies +
", selectedTradeCurrency=" + selectedTradeCurrency +
", country=" + country +
", contractData=" + contractData +
'}';
}

View File

@ -20,18 +20,13 @@ package io.bitsquare.payment;
import io.bitsquare.app.Version;
import io.bitsquare.common.wire.Payload;
import javax.annotation.Nullable;
public abstract class PaymentAccountContractData implements Payload {
// 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 final String paymentMethodName;
private final String id;
private final int maxTradePeriod;
@Nullable
protected String countryCode;
protected final String paymentMethodName;
protected final String id;
protected final int maxTradePeriod;
///////////////////////////////////////////////////////////////////////////////////////////
@ -44,20 +39,6 @@ public abstract class PaymentAccountContractData implements Payload {
this.maxTradePeriod = maxTradePeriod;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter, Setter
///////////////////////////////////////////////////////////////////////////////////////////
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
@Nullable
public String getCountryCode() {
return countryCode;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getter
///////////////////////////////////////////////////////////////////////////////////////////
@ -78,6 +59,7 @@ public abstract class PaymentAccountContractData implements Payload {
return maxTradePeriod;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -88,8 +70,7 @@ public abstract class PaymentAccountContractData implements Payload {
if (maxTradePeriod != that.maxTradePeriod) return false;
if (paymentMethodName != null ? !paymentMethodName.equals(that.paymentMethodName) : that.paymentMethodName != null)
return false;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
return !(countryCode != null ? !countryCode.equals(that.countryCode) : that.countryCode != null);
return !(id != null ? !id.equals(that.id) : that.id != null);
}
@ -98,7 +79,15 @@ public abstract class PaymentAccountContractData implements Payload {
int result = paymentMethodName != null ? paymentMethodName.hashCode() : 0;
result = 31 * result + (id != null ? id.hashCode() : 0);
result = 31 * result + maxTradePeriod;
result = 31 * result + (countryCode != null ? countryCode.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "PaymentAccountContractData{" +
"paymentMethodName='" + paymentMethodName + '\'' +
", id='" + id + '\'' +
", maxTradePeriod=" + maxTradePeriod +
'}';
}
}

View File

@ -37,13 +37,13 @@ public abstract class PaymentAccountFactory implements Persistable {
case PaymentMethod.SAME_BANK_ID:
return new SameBankAccount();
case PaymentMethod.SPECIFIC_BANKS_ID:
return new SpecificBankAccount();
return new SpecificBanksAccount();
case PaymentMethod.ALI_PAY_ID:
return new AliPayAccount();
case PaymentMethod.SWISH_ID:
return new SwishAccount();
case PaymentMethod.BLOCK_CHAINS_ID:
return new BlockChainAccount();
return new CryptoCurrencyAccount();
default:
throw new RuntimeException("Not supported PaymentMethod: " + paymentMethod);
}

View File

@ -19,7 +19,7 @@ package io.bitsquare.payment;
import io.bitsquare.app.Version;
public final class SameBankAccount extends PaymentAccount {
public final class SameBankAccount extends CountryBasedPaymentAccount implements BankNameRestrictedBankAccount, 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;
@ -32,7 +32,13 @@ public final class SameBankAccount extends PaymentAccount {
return new SameBankAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
}
public String getAcceptedBank() {
return ((SameBankAccountContractData) contractData).getBankName();
@Override
public String getBankId() {
return ((BankAccountContractData) contractData).getBankId();
}
@Override
public String getCountryCode() {
return getCountry() != null ? getCountry().code : "";
}
}

View File

@ -0,0 +1,5 @@
package io.bitsquare.payment;
public interface SameCountryRestrictedBankAccount extends BankAccount {
String getCountryCode();
}

View File

@ -21,7 +21,7 @@ import io.bitsquare.app.Version;
import java.util.List;
public final class SepaAccount extends PaymentAccount {
public final class SepaAccount extends CountryBasedPaymentAccount implements BankAccount {
// 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;
@ -34,6 +34,11 @@ public final class SepaAccount extends PaymentAccount {
return new SepaAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
}
@Override
public String getBankId() {
return ((SepaAccountContractData) contractData).getBic();
}
public void setHolderName(String holderName) {
((SepaAccountContractData) contractData).setHolderName(holderName);
}

View File

@ -27,7 +27,8 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public final class SepaAccountContractData extends PaymentAccountContractData {
// TODO refactor with BankAccountContractData
public final class SepaAccountContractData extends CountryBasedPaymentAccountContractData {
// 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;

View File

@ -21,11 +21,11 @@ import io.bitsquare.app.Version;
import java.util.ArrayList;
public final class SpecificBankAccount extends PaymentAccount {
public final class SpecificBanksAccount extends CountryBasedPaymentAccount implements BankNameRestrictedBankAccount, 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;
public SpecificBankAccount() {
public SpecificBanksAccount() {
super(PaymentMethod.SPECIFIC_BANKS);
}
@ -37,4 +37,14 @@ public final class SpecificBankAccount extends PaymentAccount {
public ArrayList<String> getAcceptedBanks() {
return ((SpecificBanksAccountContractData) contractData).getAcceptedBanks();
}
@Override
public String getBankId() {
return ((SpecificBanksAccountContractData) contractData).getBankId();
}
@Override
public String getCountryCode() {
return getCountry() != null ? getCountry().code : "";
}
}

View File

@ -62,7 +62,7 @@ public final class SpecificBanksAccountContractData extends BankAccountContractD
@Override
public String getPaymentDetailsForTradePopup() {
String holderIdString = BankUtil.requiresHolderId(countryCode) ? (getHolderIdLabel() + ": " + holderId + "\n") : "";
String holderIdString = BankUtil.requiresHolderId(countryCode) ? (getHolderIdLabel() + ": " + holderTaxId + "\n") : "";
return "Holder name: " + holderName + "\n" +
holderIdString +
"Bank name: " + bankName + "\n" +

View File

@ -23,7 +23,6 @@ import io.bitsquare.common.crypto.KeyRing;
import io.bitsquare.common.crypto.PubKeyRing;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.common.util.JsonExclude;
import io.bitsquare.locale.Country;
import io.bitsquare.p2p.NodeAddress;
import io.bitsquare.p2p.storage.payload.RequiresOwnerIsOnlinePayload;
import io.bitsquare.p2p.storage.payload.StoragePayload;
@ -84,9 +83,26 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
// Instance fields
///////////////////////////////////////////////////////////////////////////////////////////
private final String id;
// Fields for filtering offers
private final Direction direction;
private final String currencyCode;
// payment method
private final String paymentMethodName;
@Nullable
private final String countryCode;
@Nullable
private final ArrayList<String> acceptedCountryCodes;
@Nullable
private final String bankId;
@Nullable
private final ArrayList<String> acceptedBankIds;
private final ArrayList<NodeAddress> arbitratorNodeAddresses;
private final String id;
private final long date;
private final long protocolVersion;
private final long fiatPrice;
@ -95,17 +111,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
private final NodeAddress offererNodeAddress;
@JsonExclude
private final PubKeyRing pubKeyRing;
private final String paymentMethodName;
@Nullable
private final String paymentMethodCountryCode;
private final String offererPaymentAccountId;
@Nullable
private final ArrayList<String> acceptedCountryCodes;
@Nullable
private final ArrayList<String> acceptedBanks;
private final ArrayList<NodeAddress> arbitratorNodeAddresses;
// Mutable property. Has to be set before offer is save in P2P network as it changes the objects hash!
private String offerFeePaymentTxID;
@ -133,13 +140,14 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
long fiatPrice,
long amount,
long minAmount,
String paymentMethodName,
String currencyCode,
@Nullable Country paymentMethodCountry,
String offererPaymentAccountId,
ArrayList<NodeAddress> arbitratorNodeAddresses,
String paymentMethodName,
String offererPaymentAccountId,
@Nullable String countryCode,
@Nullable ArrayList<String> acceptedCountryCodes,
@Nullable ArrayList<String> acceptedBanks) {
@Nullable String bankId,
@Nullable ArrayList<String> acceptedBankIds) {
this.id = id;
this.offererNodeAddress = offererNodeAddress;
this.pubKeyRing = pubKeyRing;
@ -147,13 +155,14 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
this.fiatPrice = fiatPrice;
this.amount = amount;
this.minAmount = minAmount;
this.paymentMethodName = paymentMethodName;
this.currencyCode = currencyCode;
this.paymentMethodCountryCode = paymentMethodCountry != null ? paymentMethodCountry.code : null;
this.offererPaymentAccountId = offererPaymentAccountId;
this.arbitratorNodeAddresses = arbitratorNodeAddresses;
this.paymentMethodName = paymentMethodName;
this.offererPaymentAccountId = offererPaymentAccountId;
this.countryCode = countryCode;
this.acceptedCountryCodes = acceptedCountryCodes;
this.acceptedBanks = acceptedBanks;
this.bankId = bankId;
this.acceptedBankIds = acceptedBankIds;
protocolVersion = Version.TRADE_PROTOCOL_VERSION;
@ -331,8 +340,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
}
@Nullable
public String getPaymentMethodCountryCode() {
return paymentMethodCountryCode;
public String getCountryCode() {
return countryCode;
}
@Nullable
@ -341,8 +350,13 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
}
@Nullable
public List<String> getAcceptedBanks() {
return acceptedBanks;
public List<String> getAcceptedBankIds() {
return acceptedBankIds;
}
@Nullable
public String getBankId() {
return bankId;
}
public String getOfferFeePaymentTxID() {
@ -392,13 +406,14 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
if (pubKeyRing != null ? !pubKeyRing.equals(offer.pubKeyRing) : offer.pubKeyRing != null) return false;
if (paymentMethodName != null ? !paymentMethodName.equals(offer.paymentMethodName) : offer.paymentMethodName != null)
return false;
if (paymentMethodCountryCode != null ? !paymentMethodCountryCode.equals(offer.paymentMethodCountryCode) : offer.paymentMethodCountryCode != null)
if (countryCode != null ? !countryCode.equals(offer.countryCode) : offer.countryCode != null)
return false;
if (offererPaymentAccountId != null ? !offererPaymentAccountId.equals(offer.offererPaymentAccountId) : offer.offererPaymentAccountId != null)
return false;
if (acceptedCountryCodes != null ? !acceptedCountryCodes.equals(offer.acceptedCountryCodes) : offer.acceptedCountryCodes != null)
return false;
if (acceptedBanks != null ? !acceptedBanks.equals(offer.acceptedBanks) : offer.acceptedBanks != null)
if (bankId != null ? !bankId.equals(offer.bankId) : offer.bankId != null) return false;
if (acceptedBankIds != null ? !acceptedBankIds.equals(offer.acceptedBankIds) : offer.acceptedBankIds != null)
return false;
if (arbitratorNodeAddresses != null ? !arbitratorNodeAddresses.equals(offer.arbitratorNodeAddresses) : offer.arbitratorNodeAddresses != null)
return false;
@ -418,10 +433,11 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
result = 31 * result + (offererNodeAddress != null ? offererNodeAddress.hashCode() : 0);
result = 31 * result + (pubKeyRing != null ? pubKeyRing.hashCode() : 0);
result = 31 * result + (paymentMethodName != null ? paymentMethodName.hashCode() : 0);
result = 31 * result + (paymentMethodCountryCode != null ? paymentMethodCountryCode.hashCode() : 0);
result = 31 * result + (countryCode != null ? countryCode.hashCode() : 0);
result = 31 * result + (bankId != null ? bankId.hashCode() : 0);
result = 31 * result + (offererPaymentAccountId != null ? offererPaymentAccountId.hashCode() : 0);
result = 31 * result + (acceptedCountryCodes != null ? acceptedCountryCodes.hashCode() : 0);
result = 31 * result + (acceptedBanks != null ? acceptedBanks.hashCode() : 0);
result = 31 * result + (acceptedBankIds != null ? acceptedBankIds.hashCode() : 0);
result = 31 * result + (arbitratorNodeAddresses != null ? arbitratorNodeAddresses.hashCode() : 0);
result = 31 * result + (offerFeePaymentTxID != null ? offerFeePaymentTxID.hashCode() : 0);
return result;
@ -440,10 +456,11 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
"\n\toffererAddress=" + offererNodeAddress +
"\n\tpubKeyRing=" + pubKeyRing +
"\n\tpaymentMethodName='" + paymentMethodName + '\'' +
"\n\tpaymentMethodCountryCode='" + paymentMethodCountryCode + '\'' +
"\n\tpaymentMethodCountryCode='" + countryCode + '\'' +
"\n\toffererPaymentAccountId='" + offererPaymentAccountId + '\'' +
"\n\tacceptedCountryCodes=" + acceptedCountryCodes +
"\n\tacceptedBanks=" + acceptedBanks +
"\n\tbankId=" + bankId +
"\n\tacceptedBanks=" + acceptedBankIds +
"\n\tarbitratorAddresses=" + arbitratorNodeAddresses +
"\n\tofferFeePaymentTxID='" + offerFeePaymentTxID + '\'' +
"\n\tstate=" + state +

View File

@ -20,7 +20,7 @@ package io.bitsquare.trade.protocol.trade.tasks.offerer;
import io.bitsquare.common.crypto.Hash;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.payment.BlockChainAccountContractData;
import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.messages.PayDepositRequest;
@ -64,10 +64,10 @@ public class ProcessPayDepositRequest extends TradeTask {
PaymentAccountContractData paymentAccountContractData = checkNotNull(payDepositRequest.takerPaymentAccountContractData);
processModel.tradingPeer.setPaymentAccountContractData(paymentAccountContractData);
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
if (paymentAccountContractData instanceof CryptoCurrencyAccountContractData &&
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, Math.min(32, trade.getId().length()));
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
((CryptoCurrencyAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
}
processModel.tradingPeer.setAccountId(nonEmptyStringOf(payDepositRequest.takerAccountId));

View File

@ -20,7 +20,7 @@ package io.bitsquare.trade.protocol.trade.tasks.taker;
import io.bitsquare.common.crypto.Hash;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.payment.BlockChainAccountContractData;
import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest;
@ -52,10 +52,10 @@ public class ProcessPublishDepositTxRequest extends TradeTask {
PaymentAccountContractData paymentAccountContractData = checkNotNull(publishDepositTxRequest.offererPaymentAccountContractData);
processModel.tradingPeer.setPaymentAccountContractData(paymentAccountContractData);
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
if (paymentAccountContractData instanceof CryptoCurrencyAccountContractData &&
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, Math.min(32, trade.getId().length()));
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
((CryptoCurrencyAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
}
processModel.tradingPeer.setAccountId(nonEmptyStringOf(publishDepositTxRequest.offererAccountId));

View File

@ -239,15 +239,17 @@ public final class User implements Persistable {
}
public List<Arbitrator> getAcceptedArbitrators() {
return acceptedArbitrators;
return acceptedArbitrators != null ? acceptedArbitrators : new ArrayList<>();
}
public List<NodeAddress> getAcceptedArbitratorAddresses() {
return acceptedArbitrators.stream().map(Arbitrator::getArbitratorNodeAddress).collect(Collectors.toList());
return acceptedArbitrators != null ?
acceptedArbitrators.stream().map(Arbitrator::getArbitratorNodeAddress).collect(Collectors.toList()) :
new ArrayList<>();
}
public List<String> getAcceptedLanguageLocaleCodes() {
return acceptedLanguageLocaleCodes;
return acceptedLanguageLocaleCodes != null ? acceptedLanguageLocaleCodes : new ArrayList<>();
}
/* public List<String> getArbitratorAddresses(List<String> idList) {

View File

@ -106,9 +106,6 @@ public class BitsquareAppMain extends BitsquareExecutable {
parser.accepts(ProgramArguments.USE_LOCALHOST, description("Use localhost network for development", false))
.withRequiredArg()
.ofType(boolean.class);
parser.accepts(ProgramArguments.DEV_TEST, description("Enable arbitrator dev priv key", false))
.withRequiredArg()
.ofType(boolean.class);
parser.accepts(BitcoinNetwork.KEY, description("Bitcoin network", BitcoinNetwork.DEFAULT))
.withRequiredArg()
.ofType(BitcoinNetwork.class)

View File

@ -25,6 +25,7 @@ import io.bitsquare.gui.util.Layout;
import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.locale.*;
import io.bitsquare.payment.BankAccountContractData;
import io.bitsquare.payment.CountryBasedPaymentAccount;
import io.bitsquare.payment.PaymentAccount;
import io.bitsquare.payment.PaymentAccountContractData;
import javafx.collections.FXCollections;
@ -53,9 +54,9 @@ abstract class BankForm extends PaymentMethodForm {
static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
BankAccountContractData bankAccountContractData = (BankAccountContractData) paymentAccountContractData;
if (bankAccountContractData.getHolderId() != null)
if (bankAccountContractData.getHolderTaxId() != null)
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name / " + bankAccountContractData.getHolderIdLabel(),
bankAccountContractData.getHolderName() + " / " + bankAccountContractData.getHolderId());
bankAccountContractData.getHolderName() + " / " + bankAccountContractData.getHolderTaxId());
else
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name:", bankAccountContractData.getHolderName());
@ -112,10 +113,10 @@ abstract class BankForm extends PaymentMethodForm {
countryComboBox.setOnAction(e -> {
Country selectedItem = countryComboBox.getSelectionModel().getSelectedItem();
if (selectedItem != null) {
paymentAccount.setCountry(selectedItem);
getCountryBasedPaymentAccount().setCountry(selectedItem);
String countryCode = selectedItem.code;
TradeCurrency currency = CurrencyUtil.getCurrencyByCountryCode(countryCode);
paymentAccount.setSingleTradeCurrency(currency);
this.paymentAccount.setSingleTradeCurrency(currency);
currencyTextField.setText(currency.getNameAndCode());
bankIdLabel.setText(BankUtil.getBankCodeLabel(bankAccountContractData.getCountryCode()));
@ -203,6 +204,10 @@ abstract class BankForm extends PaymentMethodForm {
updateFromInputs();
}
private CountryBasedPaymentAccount getCountryBasedPaymentAccount() {
return (CountryBasedPaymentAccount) this.paymentAccount;
}
protected void onCountryChanged() {
}
@ -226,7 +231,7 @@ abstract class BankForm extends PaymentMethodForm {
holderIdInputTextField.setManaged(false);
holderIdInputTextField.setValidator(inputValidator);
holderIdInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
bankAccountContractData.setHolderId(newValue);
bankAccountContractData.setHolderTaxId(newValue);
updateFromInputs();
});
}
@ -253,9 +258,9 @@ abstract class BankForm extends PaymentMethodForm {
@Override
public void updateAllInputsValid() {
boolean holderIdValid = true;
if (paymentAccount.getCountry() != null) {
if (BankUtil.requiresHolderId(paymentAccount.getCountry().code))
holderIdValid = inputValidator.validate(bankAccountContractData.getHolderId()).isValid;
if (getCountryBasedPaymentAccount().getCountry() != null) {
if (BankUtil.requiresHolderId(getCountryBasedPaymentAccount().getCountry().code))
holderIdValid = inputValidator.validate(bankAccountContractData.getHolderTaxId()).isValid;
}
allInputsValid.set(isAccountNameValid()
@ -265,7 +270,7 @@ abstract class BankForm extends PaymentMethodForm {
&& inputValidator.validate(bankAccountContractData.getAccountNr()).isValid
&& holderIdValid
&& paymentAccount.getSingleTradeCurrency() != null
&& paymentAccount.getCountry() != null);
&& getCountryBasedPaymentAccount().getCountry() != null);
}
@Override
@ -274,7 +279,7 @@ abstract class BankForm extends PaymentMethodForm {
addLabelTextField(gridPane, gridRow, "Account name:", paymentAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccount.getPaymentMethod().getId()));
addLabelTextField(gridPane, ++gridRow, "Country:", paymentAccount.getCountry() != null ? paymentAccount.getCountry().name : "");
addLabelTextField(gridPane, ++gridRow, "Country:", getCountryBasedPaymentAccount().getCountry() != null ? getCountryBasedPaymentAccount().getCountry().name : "");
addLabelTextField(gridPane, ++gridRow, "Currency:", paymentAccount.getSingleTradeCurrency().getNameAndCode());
addAcceptedBanksForDisplayAccount();
addHolderNameAndIdForDisplayAccount();
@ -293,7 +298,7 @@ abstract class BankForm extends PaymentMethodForm {
TextField holderNameTextField = tuple.second;
holderNameTextField.setText(bankAccountContractData.getHolderName());
holderNameTextField.setMinWidth(300);
tuple.forth.setText(bankAccountContractData.getHolderId());
tuple.forth.setText(bankAccountContractData.getHolderTaxId());
} else {
addLabelTextField(gridPane, ++gridRow, "Account holder name:", bankAccountContractData.getHolderName());
}

View File

@ -24,8 +24,8 @@ import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.locale.BSResources;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.locale.TradeCurrency;
import io.bitsquare.payment.BlockChainAccount;
import io.bitsquare.payment.BlockChainAccountContractData;
import io.bitsquare.payment.CryptoCurrencyAccount;
import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccount;
import io.bitsquare.payment.PaymentAccountContractData;
import javafx.collections.FXCollections;
@ -42,16 +42,16 @@ import static io.bitsquare.gui.util.FormBuilder.*;
public class BlockChainForm extends PaymentMethodForm {
private static final Logger log = LoggerFactory.getLogger(BlockChainForm.class);
private final BlockChainAccount blockChainAccount;
private final CryptoCurrencyAccount cryptoCurrencyAccount;
private final AltCoinAddressValidator altCoinAddressValidator;
private InputTextField addressInputTextField;
private ComboBox<TradeCurrency> currencyComboBox;
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Cryptocurrency address:", ((BlockChainAccountContractData) paymentAccountContractData).getAddress());
if (((BlockChainAccountContractData) paymentAccountContractData).getPaymentId() != null)
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Payment ID:", ((BlockChainAccountContractData) paymentAccountContractData).getPaymentId());
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Cryptocurrency address:", ((CryptoCurrencyAccountContractData) paymentAccountContractData).getAddress());
if (((CryptoCurrencyAccountContractData) paymentAccountContractData).getPaymentId() != null)
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Payment ID:", ((CryptoCurrencyAccountContractData) paymentAccountContractData).getPaymentId());
return gridRow;
}
@ -59,7 +59,7 @@ public class BlockChainForm extends PaymentMethodForm {
public BlockChainForm(PaymentAccount paymentAccount, AltCoinAddressValidator altCoinAddressValidator, InputValidator inputValidator, GridPane gridPane,
int gridRow) {
super(paymentAccount, inputValidator, gridPane, gridRow);
this.blockChainAccount = (BlockChainAccount) paymentAccount;
this.cryptoCurrencyAccount = (CryptoCurrencyAccount) paymentAccount;
this.altCoinAddressValidator = altCoinAddressValidator;
}
@ -73,7 +73,7 @@ public class BlockChainForm extends PaymentMethodForm {
addressInputTextField.setValidator(altCoinAddressValidator);
addressInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
blockChainAccount.setAddress(newValue);
cryptoCurrencyAccount.setAddress(newValue);
updateFromInputs();
});
@ -95,19 +95,19 @@ public class BlockChainForm extends PaymentMethodForm {
@Override
public void addFormForDisplayAccount() {
gridRowFrom = gridRow;
addLabelTextField(gridPane, gridRow, "Account name:", blockChainAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(blockChainAccount.getPaymentMethod().getId()));
TextField field = addLabelTextField(gridPane, ++gridRow, "Cryptocurrency address:", blockChainAccount.getAddress()).second;
addLabelTextField(gridPane, gridRow, "Account name:", cryptoCurrencyAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(cryptoCurrencyAccount.getPaymentMethod().getId()));
TextField field = addLabelTextField(gridPane, ++gridRow, "Cryptocurrency address:", cryptoCurrencyAccount.getAddress()).second;
field.setMouseTransparent(false);
addLabelTextField(gridPane, ++gridRow, "Cryptocurrency:", blockChainAccount.getSingleTradeCurrency().getNameAndCode());
addLabelTextField(gridPane, ++gridRow, "Cryptocurrency:", cryptoCurrencyAccount.getSingleTradeCurrency().getNameAndCode());
addAllowedPeriod();
}
@Override
public void updateAllInputsValid() {
allInputsValid.set(isAccountNameValid()
&& altCoinAddressValidator.validate(blockChainAccount.getAddress()).isValid
&& blockChainAccount.getSingleTradeCurrency() != null);
&& altCoinAddressValidator.validate(cryptoCurrencyAccount.getAddress()).isValid
&& cryptoCurrencyAccount.getSingleTradeCurrency() != null);
}
@Override

View File

@ -20,6 +20,7 @@ package io.bitsquare.gui.components.paymentmethods;
import io.bitsquare.common.util.Tuple2;
import io.bitsquare.gui.components.InputTextField;
import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.payment.CountryBasedPaymentAccount;
import io.bitsquare.payment.PaymentAccount;
import io.bitsquare.payment.PaymentAccountContractData;
import javafx.scene.control.Label;
@ -63,7 +64,7 @@ public class SameBankForm extends BankForm {
&& inputValidator.validate(bankAccountContractData.getBranchId()).isValid
&& inputValidator.validate(bankAccountContractData.getAccountNr()).isValid
&& paymentAccount.getSingleTradeCurrency() != null
&& paymentAccount.getCountry() != null);
&& ((CountryBasedPaymentAccount) paymentAccount).getCountry() != null);
}
@Override

View File

@ -24,10 +24,7 @@ import io.bitsquare.gui.util.validation.BICValidator;
import io.bitsquare.gui.util.validation.IBANValidator;
import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.locale.*;
import io.bitsquare.payment.PaymentAccount;
import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.payment.SepaAccount;
import io.bitsquare.payment.SepaAccountContractData;
import io.bitsquare.payment.*;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
@ -59,7 +56,7 @@ public class SepaForm extends PaymentMethodForm {
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name:", ((SepaAccountContractData) paymentAccountContractData).getHolderName());
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Country of bank:", CountryUtil.getNameAndCode(paymentAccountContractData.getCountryCode()));
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Country of bank:", CountryUtil.getNameAndCode(((CountryBasedPaymentAccountContractData) paymentAccountContractData).getCountryCode()));
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "IBAN:", ((SepaAccountContractData) paymentAccountContractData).getIban());
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "BIC/SWIFT:", ((SepaAccountContractData) paymentAccountContractData).getBic());
return gridRow;
@ -228,7 +225,7 @@ public class SepaForm extends PaymentMethodForm {
if (iban.length() > 5)
iban = StringUtils.abbreviate(iban, 5);
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
String country = paymentAccount.getCountry() != null ? paymentAccount.getCountry().code : "?";
String country = ((CountryBasedPaymentAccount) paymentAccount).getCountry() != null ? ((CountryBasedPaymentAccount) paymentAccount).getCountry().code : "?";
String currency = paymentAccount.getSingleTradeCurrency() != null ? paymentAccount.getSingleTradeCurrency().getCode() : "?";
accountNameTextField.setText(method.concat(", ").concat(currency).concat(", ").concat(country).concat(", ").concat(iban));
}

View File

@ -46,7 +46,6 @@ import io.bitsquare.gui.main.overlays.windows.DisplayAlertMessageWindow;
import io.bitsquare.gui.main.overlays.windows.TacWindow;
import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.CountryUtil;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.p2p.P2PService;
import io.bitsquare.p2p.P2PServiceListener;
@ -735,7 +734,6 @@ public class MainViewModel implements ViewModel {
okPayAccount.setAccountNr("dummy");
okPayAccount.setAccountName("OKPay dummy");
okPayAccount.setSelectedTradeCurrency(CurrencyUtil.getDefaultTradeCurrency());
okPayAccount.setCountry(CountryUtil.getDefaultCountry());
user.addPaymentAccount(okPayAccount);
}
}

View File

@ -33,13 +33,9 @@ import io.bitsquare.gui.main.overlays.notifications.Notification;
import io.bitsquare.gui.main.overlays.popups.Popup;
import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.TradeCurrency;
import io.bitsquare.p2p.P2PService;
import io.bitsquare.payment.PaymentAccount;
import io.bitsquare.payment.SameBankAccount;
import io.bitsquare.payment.SepaAccount;
import io.bitsquare.payment.SpecificBankAccount;
import io.bitsquare.payment.*;
import io.bitsquare.trade.handlers.TransactionResultHandler;
import io.bitsquare.trade.offer.Offer;
import io.bitsquare.trade.offer.OpenOfferManager;
@ -242,18 +238,27 @@ class CreateOfferDataModel extends ActivatableDataModel {
long amount = amountAsCoin.get() != null ? amountAsCoin.get().getValue() : 0L;
long minAmount = minAmountAsCoin.get() != null ? minAmountAsCoin.get().getValue() : 0L;
ArrayList<String> acceptedCountryCodes = new ArrayList<>();
if (paymentAccount instanceof SepaAccount)
ArrayList<String> acceptedCountryCodes = null;
if (paymentAccount instanceof SepaAccount) {
acceptedCountryCodes = new ArrayList<>();
acceptedCountryCodes.addAll(((SepaAccount) paymentAccount).getAcceptedCountryCodes());
} else if (paymentAccount instanceof CountryBasedPaymentAccount) {
acceptedCountryCodes = new ArrayList<>();
acceptedCountryCodes.add(((CountryBasedPaymentAccount) paymentAccount).getCountry().code);
}
ArrayList<String> acceptedBanks = new ArrayList<>();
if (paymentAccount instanceof SpecificBankAccount)
acceptedBanks.addAll(((SpecificBankAccount) paymentAccount).getAcceptedBanks());
else if (paymentAccount instanceof SameBankAccount)
acceptedBanks.add(((SameBankAccount) paymentAccount).getAcceptedBank());
ArrayList<String> acceptedBanks = null;
if (paymentAccount instanceof SpecificBanksAccount) {
acceptedBanks = new ArrayList<>(((SpecificBanksAccount) paymentAccount).getAcceptedBanks());
} else if (paymentAccount instanceof SameBankAccount) {
acceptedBanks = new ArrayList<>();
acceptedBanks.add(((SameBankAccount) paymentAccount).getBankId());
}
String bankId = paymentAccount instanceof BankAccount ? ((BankAccount) paymentAccount).getBankId() : null;
// That is optional and set to null if not supported (AltCoins, OKPay,...)
Country country = paymentAccount.getCountry();
String countryCode = paymentAccount instanceof CountryBasedPaymentAccount ? ((CountryBasedPaymentAccount) paymentAccount).getCountry().code : null;
checkNotNull(p2PService.getAddress(), "Address must not be null");
return new Offer(offerId,
@ -263,12 +268,13 @@ class CreateOfferDataModel extends ActivatableDataModel {
fiatPrice,
amount,
minAmount,
paymentAccount.getPaymentMethod().getId(),
tradeCurrencyCode.get(),
country,
paymentAccount.getId(),
new ArrayList<>(user.getAcceptedArbitratorAddresses()),
paymentAccount.getPaymentMethod().getId(),
paymentAccount.getId(),
countryCode,
acceptedCountryCodes,
bankId,
acceptedBanks);
}

View File

@ -166,6 +166,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
paymentAccountsComboBox.getSelectionModel().select(model.getPaymentAccount());
onPaymentAccountsComboBoxSelected();
if (spinner != null && placeOfferButton.isVisible())
spinner.setProgress(-1);
}
@Override

View File

@ -500,7 +500,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
boolean myOffer = model.isMyOffer(offer);
TableRow tableRow = getTableRow();
if (tableRow != null) {
isPaymentAccountValidForOffer = model.isPaymentAccountValidForOffer(offer);
isPaymentAccountValidForOffer = model.isAnyPaymentAccountValidForOffer(offer);
hasMatchingArbitrator = model.hasMatchingArbitrator(offer);
hasSameProtocolVersion = model.hasSameProtocolVersion(offer);
isTradable = isPaymentAccountValidForOffer && hasMatchingArbitrator &&

View File

@ -32,8 +32,7 @@ import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.*;
import io.bitsquare.p2p.NodeAddress;
import io.bitsquare.p2p.P2PService;
import io.bitsquare.payment.PaymentMethod;
import io.bitsquare.payment.SepaAccount;
import io.bitsquare.payment.*;
import io.bitsquare.trade.offer.Offer;
import io.bitsquare.trade.offer.OpenOfferManager;
import io.bitsquare.user.Preferences;
@ -48,11 +47,19 @@ import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import org.bitcoinj.utils.Fiat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
class OfferBookViewModel extends ActivatableViewModel {
protected final static Logger log = LoggerFactory.getLogger(OfferBookViewModel.class);
final static String SHOW_ALL_FLAG = "SHOW_ALL_FLAG";
final static String EDIT_FLAG = "EDIT_FLAG";
@ -263,7 +270,7 @@ class OfferBookViewModel extends ActivatableViewModel {
if (item != null) {
Offer offer = item.getOffer();
String method = BSResources.get(offer.getPaymentMethod().getId() + "_SHORT");
String methodCountryCode = offer.getPaymentMethodCountryCode();
String methodCountryCode = offer.getCountryCode();
if (methodCountryCode != null)
result = method + " (" + methodCountryCode + ")";
@ -278,7 +285,7 @@ class OfferBookViewModel extends ActivatableViewModel {
if (item != null) {
Offer offer = item.getOffer();
String method = BSResources.get(offer.getPaymentMethod().getId());
String methodCountryCode = offer.getPaymentMethodCountryCode();
String methodCountryCode = offer.getCountryCode();
if (methodCountryCode != null)
result = method + "\n\nOfferers seat of bank country:\n" + CountryUtil.getNameByCode(methodCountryCode);
@ -286,7 +293,7 @@ class OfferBookViewModel extends ActivatableViewModel {
result = method;
List<String> acceptedCountryCodes = offer.getAcceptedCountryCodes();
List<String> acceptedBanks = offer.getAcceptedBanks();
List<String> acceptedBanks = offer.getAcceptedBankIds();
if (acceptedCountryCodes != null && !acceptedCountryCodes.isEmpty()) {
if (CountryUtil.containsAllSepaEuroCountries(acceptedCountryCodes))
result += "\n\nAccepted takers seat of bank countries:\nAll Euro countries";
@ -315,23 +322,100 @@ class OfferBookViewModel extends ActivatableViewModel {
return user.currentPaymentAccountProperty().get() != null;
}
boolean isPaymentAccountValidForOffer(Offer offer) {
// TODO not supporting yet check for acceptedBanks in cae of SpecificBankAccount and SameBankAccount
Optional<TradeCurrency> result1 = user.getPaymentAccounts().stream()
.filter(paymentAccount -> paymentAccount.getPaymentMethod().equals(offer.getPaymentMethod()))
.filter(paymentAccount -> {
List<String> offerAcceptedCountryCodes = offer.getAcceptedCountryCodes();
if (offerAcceptedCountryCodes != null && paymentAccount instanceof SepaAccount) {
return ((SepaAccount) paymentAccount).getAcceptedCountryCodes().stream()
.filter(offerAcceptedCountryCodes::contains)
.findAny().isPresent();
} else {
return true;
}
})
.flatMap(paymentAccount -> paymentAccount.getTradeCurrencies().stream())
.filter(currency -> currency.getCode().equals(offer.getCurrencyCode())).findAny();
return result1.isPresent();
boolean isAnyPaymentAccountValidForOffer(Offer offer) {
return isAnyPaymentAccountValidForOffer(offer, user.getPaymentAccounts());
}
static boolean isAnyPaymentAccountValidForOffer(Offer offer, Collection<PaymentAccount> paymentAccounts) {
for (PaymentAccount paymentAccount : paymentAccounts) {
if (isPaymentAccountValidForOffer(offer, paymentAccount))
return true;
}
return false;
}
static boolean isPaymentAccountValidForOffer(Offer offer, PaymentAccount paymentAccount) {
// check if we have a matching currency
Set<String> paymentAccountCurrencyCodes = paymentAccount.getTradeCurrencies().stream().map(TradeCurrency::getCode).collect(Collectors.toSet());
boolean matchesCurrencyCode = paymentAccountCurrencyCodes.contains(offer.getCurrencyCode());
log.error("paymentAccount.paymentAccountCurrencyCodes " + paymentAccountCurrencyCodes);
log.error("offer.getCurrencyCode() " + offer.getCurrencyCode());
log.error("matchesCurrencyCode " + matchesCurrencyCode);
if (!matchesCurrencyCode)
return false;
// check if we have a matching payment method or if its a bank account payment method which is treated special
if (paymentAccount instanceof CountryBasedPaymentAccount) {
CountryBasedPaymentAccount countryBasedPaymentAccount = (CountryBasedPaymentAccount) paymentAccount;
checkNotNull(offer.getCountryCode(), "offer.getCountryCode() must not be null");
checkNotNull(offer.getBankId(), "offer.getBankId() must not be null");
checkNotNull(offer.getAcceptedCountryCodes(), "offer.getAcceptedCountryCodes() must not be null");
checkNotNull(countryBasedPaymentAccount.getCountry(), "paymentAccount.getCountry() must not be null");
// check if we have a matching country
boolean matchesCountryCodes = offer.getAcceptedCountryCodes().contains(countryBasedPaymentAccount.getCountry().code);
log.error("offer.getAcceptedCountryCodes() " + offer.getAcceptedCountryCodes());
log.error("paymentAccount.getCountry().code " + countryBasedPaymentAccount.getCountry().code);
log.error("matchesCountryCodes " + matchesCountryCodes);
if (!matchesCountryCodes)
return false;
if (paymentAccount instanceof SepaAccount || offer.getPaymentMethod().equals(PaymentMethod.SEPA)) {
boolean samePaymentMethod = paymentAccount.getPaymentMethod().equals(offer.getPaymentMethod());
log.error("samePaymentMethod " + samePaymentMethod);
return samePaymentMethod;
} else if (offer.getPaymentMethod().equals(PaymentMethod.SAME_BANK) ||
offer.getPaymentMethod().equals(PaymentMethod.SPECIFIC_BANKS)) {
checkNotNull(offer.getAcceptedBankIds(), "offer.getAcceptedBankIds() must not be null");
if (paymentAccount instanceof SpecificBanksAccount) {
// check if we have a matching bank
boolean offerSideMatchesBank = offer.getAcceptedBankIds().contains(((BankAccount) paymentAccount).getBankId());
boolean paymentAccountSideMatchesBank = ((SpecificBanksAccount) paymentAccount).getAcceptedBanks().contains(offer.getBankId());
log.error("offer.getAcceptedBankIds() " + offer.getAcceptedBankIds());
log.error("((BankAccount) paymentAccount).getBankId() " + ((BankAccount) paymentAccount).getBankId());
log.error("offerSideMatchesBank " + offerSideMatchesBank);
log.error("paymentAccountSideMatchesBank " + paymentAccountSideMatchesBank);
return offerSideMatchesBank && paymentAccountSideMatchesBank;
} else {
// national or same bank
boolean matchesBank = offer.getAcceptedBankIds().contains(((BankAccount) paymentAccount).getBankId());
log.error("offer.getAcceptedBankIds() " + offer.getAcceptedBankIds());
log.error("((BankAccount) paymentAccount).getBankId() " + ((BankAccount) paymentAccount).getBankId());
log.error("matchesBank " + matchesBank);
return matchesBank;
}
} else {
if (paymentAccount instanceof SpecificBanksAccount) {
// check if we have a matching bank
boolean paymentAccountSideMatchesBank = ((SpecificBanksAccount) paymentAccount).getAcceptedBanks().contains(offer.getBankId());
log.error("offer.getAcceptedBankIds() " + offer.getAcceptedBankIds());
log.error("((BankAccount) paymentAccount).getBankId() " + ((BankAccount) paymentAccount).getBankId());
log.error("paymentAccountSideMatchesBank " + paymentAccountSideMatchesBank);
return paymentAccountSideMatchesBank;
} else if (paymentAccount instanceof SameBankAccount) {
// check if we have a matching bank
boolean paymentAccountSideMatchesBank = ((SameBankAccount) paymentAccount).getBankId().equals(offer.getBankId());
log.error("offer.getAcceptedBankIds() " + offer.getAcceptedBankIds());
log.error("((BankAccount) paymentAccount).getBankId() " + ((BankAccount) paymentAccount).getBankId());
log.error("paymentAccountSideMatchesBank " + paymentAccountSideMatchesBank);
return paymentAccountSideMatchesBank;
} else {
// national
return true;
}
}
} else {
return paymentAccount.getPaymentMethod().equals(offer.getPaymentMethod());
}
}
public boolean hasPaymentAccountForCurrency() {

View File

@ -271,6 +271,8 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
};
model.dataModel.feeFromFundingTxProperty.addListener(feeFromFundingTxListener);
if (spinner != null && takeOfferButton.isVisible())
spinner.setProgress(-1);
}
@Override

View File

@ -220,7 +220,16 @@ public abstract class Overlay<T extends Overlay> {
public T instruction(String message) {
type = Type.Instruction;
if (headLine == null)
this.headLine = "Instruction";
this.headLine = "Please note:";
this.message = message;
setTruncatedMessage();
return (T) this;
}
public T attention(String message) {
type = Type.Attention;
if (headLine == null)
this.headLine = "Attention";
this.message = message;
setTruncatedMessage();
return (T) this;
@ -238,7 +247,7 @@ public abstract class Overlay<T extends Overlay> {
public T feedback(String message) {
type = Type.Feedback;
if (headLine == null)
this.headLine = "Feedback";
this.headLine = "Completed";
this.message = message;
setTruncatedMessage();
return (T) this;

View File

@ -24,7 +24,7 @@ import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.Layout;
import io.bitsquare.locale.BSResources;
import io.bitsquare.locale.CountryUtil;
import io.bitsquare.payment.BlockChainAccountContractData;
import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.payment.PaymentMethod;
import io.bitsquare.trade.Contract;
@ -88,7 +88,7 @@ public class ContractWindow extends Overlay<ContractWindow> {
Contract contract = dispute.getContract();
Offer offer = contract.offer;
List<String> acceptedBanks = offer.getAcceptedBanks();
List<String> acceptedBanks = offer.getAcceptedBankIds();
boolean showAcceptedBanks = acceptedBanks != null && !acceptedBanks.isEmpty();
List<String> acceptedCountryCodes = offer.getAcceptedCountryCodes();
boolean showAcceptedCountryCodes = acceptedCountryCodes != null && !acceptedCountryCodes.isEmpty();
@ -105,8 +105,8 @@ public class ContractWindow extends Overlay<ContractWindow> {
boolean isPaymentIdAvailable = false;
PaymentAccountContractData sellerPaymentAccountContractData = contract.getSellerPaymentAccountContractData();
if (sellerPaymentAccountContractData instanceof BlockChainAccountContractData &&
((BlockChainAccountContractData) sellerPaymentAccountContractData).getPaymentId() != null) {
if (sellerPaymentAccountContractData instanceof CryptoCurrencyAccountContractData &&
((CryptoCurrencyAccountContractData) sellerPaymentAccountContractData).getPaymentId() != null) {
rows++;
isPaymentIdAvailable = true;
}
@ -133,7 +133,7 @@ public class ContractWindow extends Overlay<ContractWindow> {
BSResources.get(sellerPaymentAccountContractData.getPaymentDetails())).second.setMouseTransparent(false);
if (isPaymentIdAvailable)
addLabelTextField(gridPane, ++rowIndex, "Seller payment ID:",
((BlockChainAccountContractData) sellerPaymentAccountContractData).getPaymentId());
((CryptoCurrencyAccountContractData) sellerPaymentAccountContractData).getPaymentId());
if (showAcceptedCountryCodes) {
String countries;

View File

@ -73,7 +73,7 @@ public class DisplayAlertMessageWindow extends Overlay<DisplayAlertMessageWindow
headLineLabel.setStyle("-fx-text-fill: -fx-accent; -fx-font-weight: bold; -fx-font-size: 22;");
String url = "https://github.com/bitsquare/bitsquare/releases";
HyperlinkWithIcon download = addLabelHyperlinkWithIcon(gridPane, ++rowIndex, "Download:", url).second;
download.setMaxWidth(350);
download.setMaxWidth(550);
download.setOnAction(e -> Utilities.openWebPage(url));
} else {
headLine = "Important information!";

View File

@ -392,7 +392,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
if (!finalPeersDispute.isClosed())
UserThread.runAfter(() ->
new Popup().instruction("You need to close also the trading peers ticket!").show(),
new Popup().attention("You need to close also the trading peers ticket!").show(),
Transitions.DEFAULT_DURATION, TimeUnit.MILLISECONDS);
hide();

View File

@ -134,7 +134,7 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
private void addContent() {
int rows = 5;
List<String> acceptedBanks = offer.getAcceptedBanks();
List<String> acceptedBanks = offer.getAcceptedBankIds();
boolean showAcceptedBanks = acceptedBanks != null && !acceptedBanks.isEmpty();
List<String> acceptedCountryCodes = offer.getAcceptedCountryCodes();
boolean showAcceptedCountryCodes = acceptedCountryCodes != null && !acceptedCountryCodes.isEmpty();
@ -198,7 +198,7 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
}
rows = 4;
String paymentMethodCountryCode = offer.getPaymentMethodCountryCode();
String paymentMethodCountryCode = offer.getCountryCode();
if (paymentMethodCountryCode != null)
rows++;
if (offer.getOfferFeePaymentTxID() != null)

View File

@ -186,7 +186,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
if (item != null) {
Offer offer = item.getTrade().getOffer();
String method = BSResources.get(offer.getPaymentMethod().getId() + "_SHORT");
String methodCountryCode = offer.getPaymentMethodCountryCode();
String methodCountryCode = offer.getCountryCode();
if (methodCountryCode != null)
result = method + " (" + methodCountryCode + ")";

View File

@ -27,7 +27,7 @@ import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
import io.bitsquare.gui.util.Layout;
import io.bitsquare.locale.BSResources;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.payment.BlockChainAccountContractData;
import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.payment.PaymentMethod;
import io.bitsquare.trade.Trade;
@ -66,7 +66,7 @@ public class BuyerStep2View extends TradeStepView {
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
String key = "startPayment" + trade.getId();
String message = "";
if (paymentAccountContractData instanceof BlockChainAccountContractData)
if (paymentAccountContractData instanceof CryptoCurrencyAccountContractData)
message = "Your trade has reached at least one blockchain confirmation.\n" +
"(You can wait for more confirmations if you want - 6 confirmations are considered as very secure.)\n\n" +
"Please transfer from your external " +
@ -91,7 +91,7 @@ public class BuyerStep2View extends TradeStepView {
if (preferences.showAgain(key)) {
preferences.dontShowAgain(key, true);
new Popup().headLine("Attention required for trade with ID " + trade.getShortId())
.instruction(message)
.attention(message)
.show();
}
} else if (state == Trade.State.BUYER_CONFIRMED_FIAT_PAYMENT_INITIATED) {
@ -166,7 +166,7 @@ public class BuyerStep2View extends TradeStepView {
log.error("Not supported PaymentMethod: " + paymentMethodName);
}
if (!(paymentAccountContractData instanceof BlockChainAccountContractData))
if (!(paymentAccountContractData instanceof CryptoCurrencyAccountContractData))
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Reference text:", model.dataModel.getReference());
GridPane.setRowSpan(accountTitledGroupBg, gridRow - 3);

View File

@ -25,7 +25,7 @@ import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
import io.bitsquare.gui.util.Layout;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.payment.BlockChainAccountContractData;
import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.trade.Contract;
import io.bitsquare.trade.Trade;
@ -68,8 +68,8 @@ public class SellerStep3View extends TradeStepView {
String message;
String tradeAmountWithCode = model.formatter.formatFiatWithCode(trade.getTradeVolume());
String currencyName = CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode());
if (paymentAccountContractData instanceof BlockChainAccountContractData) {
String address = ((BlockChainAccountContractData) paymentAccountContractData).getAddress();
if (paymentAccountContractData instanceof CryptoCurrencyAccountContractData) {
String address = ((CryptoCurrencyAccountContractData) paymentAccountContractData).getAddress();
message = "Your trading partner has confirmed that he initiated the " + currencyName + " payment.\n\n" +
"Please check on your favorite " + currencyName +
" blockchain explorer if the transaction to your receiving address\n" +
@ -87,7 +87,7 @@ public class SellerStep3View extends TradeStepView {
if (preferences.showAgain(key)) {
preferences.dontShowAgain(key, true);
new Popup().headLine("Attention required for trade with ID " + trade.getShortId())
.instruction(message)
.attention(message)
.show();
}
@ -134,8 +134,8 @@ public class SellerStep3View extends TradeStepView {
Contract contract = trade.getContract();
if (contract != null) {
PaymentAccountContractData paymentAccountContractData = contract.getSellerPaymentAccountContractData();
if (paymentAccountContractData instanceof BlockChainAccountContractData) {
paymentDetails = ((BlockChainAccountContractData) paymentAccountContractData).getAddress();
if (paymentAccountContractData instanceof CryptoCurrencyAccountContractData) {
paymentDetails = ((CryptoCurrencyAccountContractData) paymentAccountContractData).getAddress();
title = "Your " + nameByCode + " address:";
isBlockChain = true;
} else {

View File

@ -164,4 +164,4 @@ FED_WIRE_SHORT=Fed Wire
SWISH_SHORT= Swish
TRANSFER_WISE_SHORT=TransferWise
US_POSTAL_MONEY_ORDER_SHORT=Money order
BLOCK_CHAINS_SHORT=Crypto currencies
BLOCK_CHAINS_SHORT=Block chain

View File

@ -0,0 +1,271 @@
package io.bitsquare.gui.main.offer.offerbook;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.CryptoCurrency;
import io.bitsquare.locale.FiatCurrency;
import io.bitsquare.payment.*;
import io.bitsquare.trade.offer.Offer;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class OfferBookViewModelTest {
private static final Logger log = LoggerFactory.getLogger(OfferBookViewModelTest.class);
@Test
public void testIsAnyPaymentAccountValidForOffer() {
Offer offer;
Collection<PaymentAccount> paymentAccounts;
// empty paymentAccounts
paymentAccounts = new ArrayList<>();
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(getSEPAPaymentMethod("EUR", "AT", new ArrayList(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
// simple cases: same payment methods
// offer: okpay paymentAccount: okpay - same country, same currency
paymentAccounts = new ArrayList<>(Arrays.asList(getOKPayAccount("EUR")));
assertTrue(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getOKPayPaymentMethod("EUR"), paymentAccounts));
// offer: ether paymentAccount: ether - same country, same currency
paymentAccounts = new ArrayList<>(Arrays.asList(getCryptoAccount("ETH")));
assertTrue(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getBlockChainsPaymentMethod("ETH"), paymentAccounts));
// offer: sepa paymentAccount: sepa - same country, same currency
paymentAccounts = new ArrayList<>(Arrays.asList(getSepaAccount("EUR", "AT", "1212324", new ArrayList<>(Arrays.asList("AT", "DE")))));
assertTrue(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getSEPAPaymentMethod("EUR", "AT", new ArrayList(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
// offer: nationalBank paymentAccount: nationalBank - same country, same currency
paymentAccounts = new ArrayList<>(Arrays.asList(getNationalBankAccount("EUR", "AT", "PSK")));
assertTrue(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// offer: SameBank paymentAccount: SameBank - same country, same currency
paymentAccounts = new ArrayList<>(Arrays.asList(getSameBankAccount("EUR", "AT", "PSK")));
assertTrue(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getSameBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// offer: SpecificBanks paymentAccount: SpecificBanks - same country, same currency
paymentAccounts = new ArrayList<>(Arrays.asList(getSpecificBanksAccount("EUR", "AT", "PSK",
new ArrayList<>(Arrays.asList("PSK", "Raika")))));
assertTrue(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getSpecificBanksPaymentMethod("EUR", "AT", "PSK",
new ArrayList<>(Arrays.asList("PSK", "Raika"))), paymentAccounts));
//////
// offer: sepa paymentAccount: nationalBank - same country, same currency
// wrong method
paymentAccounts = new ArrayList<>(Arrays.asList(getNationalBankAccount("EUR", "AT", "PSK")));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getSEPAPaymentMethod("EUR", "AT", new ArrayList(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
// wrong currency
paymentAccounts = new ArrayList<>(Arrays.asList(getNationalBankAccount("USD", "US", "XXX")));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// wrong country
paymentAccounts = new ArrayList<>(Arrays.asList(getNationalBankAccount("EUR", "FR", "PSK")));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// sepa wrong country
paymentAccounts = new ArrayList<>(Arrays.asList(getNationalBankAccount("EUR", "CH", "PSK")));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getSEPAPaymentMethod("EUR", "AT", new ArrayList(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
// sepa wrong currency
paymentAccounts = new ArrayList<>(Arrays.asList(getNationalBankAccount("CHF", "DE", "PSK")));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getSEPAPaymentMethod("EUR", "AT", new ArrayList(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
// same bank
paymentAccounts = new ArrayList<>(Arrays.asList(getSameBankAccount("EUR", "AT", "PSK")));
assertTrue(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// not same bank
paymentAccounts = new ArrayList<>(Arrays.asList(getSameBankAccount("EUR", "AT", "Raika")));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// same bank, wrong country
paymentAccounts = new ArrayList<>(Arrays.asList(getSameBankAccount("EUR", "DE", "PSK")));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// same bank, wrong currency
paymentAccounts = new ArrayList<>(Arrays.asList(getSameBankAccount("USD", "AT", "PSK")));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// spec. bank
paymentAccounts = new ArrayList<>(Arrays.asList(getSpecificBanksAccount("EUR", "AT", "PSK",
new ArrayList<>(Arrays.asList("PSK", "Raika")))));
assertTrue(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// spec. bank, missing bank
paymentAccounts = new ArrayList<>(Arrays.asList(getSpecificBanksAccount("EUR", "AT", "PSK",
new ArrayList<>(Arrays.asList("Raika")))));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// spec. bank, wrong country
paymentAccounts = new ArrayList<>(Arrays.asList(getSpecificBanksAccount("EUR", "FR", "PSK",
new ArrayList<>(Arrays.asList("PSK", "Raika")))));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
// spec. bank, wrong currency
paymentAccounts = new ArrayList<>(Arrays.asList(getSpecificBanksAccount("USD", "AT", "PSK",
new ArrayList<>(Arrays.asList("PSK", "Raika")))));
assertFalse(OfferBookViewModel.isAnyPaymentAccountValidForOffer(
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
//TODO add more tests
}
private PaymentAccount getOKPayAccount(String currencyCode) {
PaymentAccount paymentAccount = new OKPayAccount();
paymentAccount.setSelectedTradeCurrency(new FiatCurrency(currencyCode));
return paymentAccount;
}
private PaymentAccount getCryptoAccount(String currencyCode) {
PaymentAccount paymentAccount = new CryptoCurrencyAccount();
paymentAccount.addCurrency(new CryptoCurrency(currencyCode, null));
return paymentAccount;
}
private PaymentAccount getSepaAccount(String currencyCode, String countryCode, String bic, ArrayList<String> countryCodes) {
CountryBasedPaymentAccount paymentAccount = new SepaAccount();
paymentAccount.setSingleTradeCurrency(new FiatCurrency(currencyCode));
paymentAccount.setCountry(new Country(countryCode, null, null));
((SepaAccountContractData) paymentAccount.getContractData()).setBic(bic);
countryCodes.forEach(((SepaAccountContractData) paymentAccount.getContractData())::addAcceptedCountry);
return paymentAccount;
}
private PaymentAccount getNationalBankAccount(String currencyCode, String countryCode, String bankId) {
CountryBasedPaymentAccount paymentAccount = new NationalBankAccount();
paymentAccount.setSingleTradeCurrency(new FiatCurrency(currencyCode));
paymentAccount.setCountry(new Country(countryCode, null, null));
((NationalBankAccountContractData) paymentAccount.getContractData()).setBankId(bankId);
return paymentAccount;
}
private PaymentAccount getSameBankAccount(String currencyCode, String countryCode, String bankId) {
SameBankAccount paymentAccount = new SameBankAccount();
paymentAccount.setSingleTradeCurrency(new FiatCurrency(currencyCode));
paymentAccount.setCountry(new Country(countryCode, null, null));
((SameBankAccountContractData) paymentAccount.getContractData()).setBankId(bankId);
return paymentAccount;
}
private PaymentAccount getSpecificBanksAccount(String currencyCode, String countryCode, String bankId, ArrayList<String> bankIds) {
SpecificBanksAccount paymentAccount = new SpecificBanksAccount();
paymentAccount.setSingleTradeCurrency(new FiatCurrency(currencyCode));
paymentAccount.setCountry(new Country(countryCode, null, null));
((SpecificBanksAccountContractData) paymentAccount.getContractData()).setBankId(bankId);
bankIds.forEach(((SpecificBanksAccountContractData) paymentAccount.getContractData())::addAcceptedBank);
return paymentAccount;
}
private Offer getBlockChainsPaymentMethod(String currencyCode) {
return getOffer(currencyCode,
PaymentMethod.BLOCK_CHAINS_ID,
null,
null,
null,
null);
}
private Offer getOKPayPaymentMethod(String currencyCode) {
return getOffer(currencyCode,
PaymentMethod.OK_PAY_ID,
null,
null,
null,
null);
}
private Offer getSEPAPaymentMethod(String currencyCode, String countryCode, ArrayList<String> countryCodes, String bankId) {
return getPaymentMethod(currencyCode,
PaymentMethod.SEPA_ID,
countryCode,
countryCodes,
bankId,
null);
}
private Offer getNationalBankPaymentMethod(String currencyCode, String countryCode, String bankId) {
return getPaymentMethod(currencyCode,
PaymentMethod.NATIONAL_BANK_ID,
countryCode,
new ArrayList(Arrays.asList(countryCode)),
bankId,
null);
}
private Offer getSameBankPaymentMethod(String currencyCode, String countryCode, String bankId) {
return getPaymentMethod(currencyCode,
PaymentMethod.SAME_BANK_ID,
countryCode,
new ArrayList(Arrays.asList(countryCode)),
bankId,
new ArrayList<>(Arrays.asList(bankId)));
}
private Offer getSpecificBanksPaymentMethod(String currencyCode, String countryCode, String bankId, ArrayList<String> bankIds) {
return getPaymentMethod(currencyCode,
PaymentMethod.SPECIFIC_BANKS_ID,
countryCode,
new ArrayList(Arrays.asList(countryCode)),
bankId,
bankIds);
}
private Offer getPaymentMethod(String currencyCode, String paymentMethodId, String countryCode, ArrayList<String> countryCodes, String bankId, ArrayList<String> bankIds) {
return getOffer(currencyCode,
paymentMethodId,
countryCode,
countryCodes,
bankId,
bankIds);
}
private Offer getOffer(String tradeCurrencyCode, String paymentMethodId, String countryCode, ArrayList<String> acceptedCountryCodes, String bankId, ArrayList<String> acceptedBanks) {
return new Offer(null,
null,
null,
null,
0,
0,
0,
tradeCurrencyCode,
null,
paymentMethodId,
null,
countryCode,
acceptedCountryCodes,
bankId,
acceptedBanks);
}
}

View File

@ -163,7 +163,7 @@ public class Connection implements MessageListener {
if (!stopped) {
try {
Log.traceCall();
// Throttle outgoing messages
// Throttle outbound messages
if (System.currentTimeMillis() - lastSendTimeStamp < 20) {
log.info("We got 2 sendMessage requests in less then 20 ms. We set the thread to sleep " +
"for 50 ms to avoid that we flood our peer. lastSendTimeStamp={}, now={}, elapsed={}",
@ -589,6 +589,7 @@ public class Connection implements MessageListener {
private final MessageListener messageListener;
private volatile boolean stopped;
private long lastReadTimeStamp;
public InputHandler(SharedModel sharedModel, ObjectInputStream objectInputStream, String portInfo, MessageListener messageListener) {
this.sharedModel = sharedModel;
@ -619,6 +620,16 @@ public class Connection implements MessageListener {
log.trace("InputHandler waiting for incoming messages.\n\tConnection=" + sharedModel.connection);
Object rawInputObject = objectInputStream.readObject();
// Throttle inbound messages
if (System.currentTimeMillis() - lastReadTimeStamp < 10) {
log.info("We got 2 messages received in less then 10 ms. We set the thread to sleep " +
"for 20 ms to avoid that we get flooded by our peer. lastReadTimeStamp={}, now={}, elapsed={}",
lastReadTimeStamp, System.currentTimeMillis(), (System.currentTimeMillis() - lastReadTimeStamp));
Thread.sleep(20);
}
lastReadTimeStamp = System.currentTimeMillis();
int size = ByteArrayUtils.objectToByteArray(rawInputObject).length;
boolean doPrintLogs = true;
if (rawInputObject instanceof Message) {