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); logbackLogger = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
//TODO for now use always trace //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.setLevel(useDetailedLogging ? Level.TRACE : Level.DEBUG);
logbackLogger.addAppender(appender); logbackLogger.addAppender(appender);
} }

View file

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

View file

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

View file

@ -18,8 +18,6 @@
package io.bitsquare.arbitration; package io.bitsquare.arbitration;
import com.google.inject.Inject; 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.Timer;
import io.bitsquare.common.UserThread; import io.bitsquare.common.UserThread;
import io.bitsquare.common.crypto.KeyRing; 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 RETRY_REPUBLISH_SEC = 5;
private static final long REPEATED_REPUBLISH_AT_STARTUP_SEC = 60; 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) // 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. // For developers we add here 2 test keys so one can setup an arbitrator by adding that test pubKey
// The matching pubkey will be removed once we use real arbitrators. // to the publicKeys list and use the test PrivKey for arbitrator registration.
// PrivKey for testing: 6ac43ea1df2a290c1c8391736aa42e4339c5cb4f110ff0257a13b63211977b7a // PrivKey for dev testing: 6ac43ea1df2a290c1c8391736aa42e4339c5cb4f110ff0257a13b63211977b7a
// Matching pubKey: 027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee // Matching pubKey for dev testing: 027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee
private static final List<String> publicKeys = new ArrayList<>(Arrays.asList( private static final List<String> publicKeys = new ArrayList<>(Arrays.asList(
"03697a499d24f497b3c46bf716318231e46c4e6a685a4e122d8e2a2b229fa1f4b8", "03697a499d24f497b3c46bf716318231e46c4e6a685a4e122d8e2a2b229fa1f4b8",
"0365c6af94681dbee69de1851f98d4684063bf5c2d64b1c73ed5d90434f375a054", "0365c6af94681dbee69de1851f98d4684063bf5c2d64b1c73ed5d90434f375a054",
@ -87,8 +83,7 @@ public class ArbitratorManager {
"03df837a3a0f3d858e82f3356b71d1285327f101f7c10b404abed2abc1c94e7169", "03df837a3a0f3d858e82f3356b71d1285327f101f7c10b404abed2abc1c94e7169",
"0203a90fb2ab698e524a5286f317a183a84327b8f8c3f7fa4a98fec9e1cefd6b72", "0203a90fb2ab698e524a5286f317a183a84327b8f8c3f7fa4a98fec9e1cefd6b72",
"023c99cc073b851c892d8c43329ca3beb5d2213ee87111af49884e3ce66cbd5ba5", "023c99cc073b851c892d8c43329ca3beb5d2213ee87111af49884e3ce66cbd5ba5",
"0274f772a98d23e7a0251ab30d7121897b5aebd11a2f1e45ab654aa57503173245", "0274f772a98d23e7a0251ab30d7121897b5aebd11a2f1e45ab654aa57503173245"
"036d8a1dfcb406886037d2381da006358722823e1940acc2598c844bbc0fd1026f"
)); ));
@ -100,7 +95,6 @@ public class ArbitratorManager {
private final ArbitratorService arbitratorService; private final ArbitratorService arbitratorService;
private final User user; private final User user;
private final ObservableMap<NodeAddress, Arbitrator> arbitratorsObservableMap = FXCollections.observableHashMap(); private final ObservableMap<NodeAddress, Arbitrator> arbitratorsObservableMap = FXCollections.observableHashMap();
private final boolean isDevTest;
private BootstrapListener bootstrapListener; private BootstrapListener bootstrapListener;
private Timer republishArbitratorTimer, retryRepublishArbitratorTimer; private Timer republishArbitratorTimer, retryRepublishArbitratorTimer;
@ -110,8 +104,7 @@ public class ArbitratorManager {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Inject @Inject
public ArbitratorManager(@Named(ProgramArguments.DEV_TEST) boolean isDevTest, KeyRing keyRing, ArbitratorService arbitratorService, User user) { public ArbitratorManager(KeyRing keyRing, ArbitratorService arbitratorService, User user) {
this.isDevTest = isDevTest;
this.keyRing = keyRing; this.keyRing = keyRing;
this.arbitratorService = arbitratorService; this.arbitratorService = arbitratorService;
this.user = user; this.user = user;
@ -242,7 +235,7 @@ public class ArbitratorManager {
} }
public boolean isPublicKeyInList(String pubKeyAsHex) { 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; package io.bitsquare.arbitration;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.google.inject.name.Names;
import io.bitsquare.app.AppModule; import io.bitsquare.app.AppModule;
import io.bitsquare.app.ProgramArguments;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -37,8 +35,5 @@ public class ArbitratorModule extends AppModule {
bind(ArbitratorManager.class).in(Singleton.class); bind(ArbitratorManager.class).in(Singleton.class);
bind(DisputeManager.class).in(Singleton.class); bind(DisputeManager.class).in(Singleton.class);
bind(ArbitratorService.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.Logger;
import org.slf4j.LoggerFactory; 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. // 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 static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
@ -34,7 +36,9 @@ public abstract class BankAccountContractData extends PaymentAccountContractData
protected String bankId; protected String bankId;
protected String branchId; protected String branchId;
protected String accountNr; protected String accountNr;
protected String holderId;
@Nullable
protected String holderTaxId;
public BankAccountContractData(String paymentMethod, String id, int maxTradePeriod) { public BankAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
super(paymentMethod, id, maxTradePeriod); super(paymentMethod, id, maxTradePeriod);
@ -47,7 +51,7 @@ public abstract class BankAccountContractData extends PaymentAccountContractData
@Override @Override
public String getPaymentDetailsForTradePopup() { public String getPaymentDetailsForTradePopup() {
String holderIdString = BankUtil.requiresHolderId(countryCode) ? (getHolderIdLabel() + ": " + holderId + "\n") : ""; String holderIdString = BankUtil.requiresHolderId(countryCode) ? (getHolderIdLabel() + ": " + holderTaxId + "\n") : "";
return "Holder name: " + holderName + "\n" + return "Holder name: " + holderName + "\n" +
"Bank name: " + bankName + "\n" + "Bank name: " + bankName + "\n" +
"Bank Nr.: " + bankId + "\n" + "Bank Nr.: " + bankId + "\n" +
@ -98,12 +102,13 @@ public abstract class BankAccountContractData extends PaymentAccountContractData
this.accountNr = accountNr; this.accountNr = accountNr;
} }
public String getHolderId() { @Nullable
return holderId; public String getHolderTaxId() {
return holderTaxId;
} }
public void setHolderId(String holderId) { public void setHolderTaxId(String holderTaxId) {
this.holderId = holderId; this.holderTaxId = holderTaxId;
} }
public String getHolderIdLabel() { 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; 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. // 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 long serialVersionUID = Version.LOCAL_DB_VERSION;
public BlockChainAccount() { public CryptoCurrencyAccount() {
super(PaymentMethod.BLOCK_CHAINS); super(PaymentMethod.BLOCK_CHAINS);
} }
@Override @Override
protected PaymentAccountContractData setContractData() { protected PaymentAccountContractData setContractData() {
return new BlockChainAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod()); return new CryptoCurrencyAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
} }
public void setAddress(String address) { public void setAddress(String address) {
((BlockChainAccountContractData) contractData).setAddress(address); ((CryptoCurrencyAccountContractData) contractData).setAddress(address);
} }
public String getAddress() { 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; 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. // 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 static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
private String address; 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; private String paymentId;
public BlockChainAccountContractData(String paymentMethod, String id, int maxTradePeriod) { public CryptoCurrencyAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
super(paymentMethod, id, maxTradePeriod); super(paymentMethod, id, maxTradePeriod);
} }
@ -49,10 +53,11 @@ public final class BlockChainAccountContractData extends PaymentAccountContractD
return getPaymentDetails(); return getPaymentDetails();
} }
public void setPaymentId(String paymentId) { public void setPaymentId(@Nullable String paymentId) {
this.paymentId = paymentId; this.paymentId = paymentId;
} }
@Nullable
public String getPaymentId() { public String getPaymentId() {
return paymentId; return paymentId;
} }

View file

@ -19,7 +19,7 @@ package io.bitsquare.payment;
import io.bitsquare.app.Version; 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. // 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 long serialVersionUID = Version.LOCAL_DB_VERSION;
@ -31,4 +31,14 @@ public final class NationalBankAccount extends PaymentAccount {
protected PaymentAccountContractData setContractData() { protected PaymentAccountContractData setContractData() {
return new NationalBankAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod()); 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
//TODO missing support for selected trade currency
public final class OKPayAccount extends PaymentAccount { public final class OKPayAccount extends PaymentAccount {
// That object is saved to disc. We need to take care of changes to not break deserialization. // 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 long serialVersionUID = Version.LOCAL_DB_VERSION;

View file

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

View file

@ -19,12 +19,10 @@ package io.bitsquare.payment;
import io.bitsquare.app.Version; import io.bitsquare.app.Version;
import io.bitsquare.common.persistance.Persistable; import io.bitsquare.common.persistance.Persistable;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.TradeCurrency; import io.bitsquare.locale.TradeCurrency;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -42,8 +40,6 @@ public abstract class PaymentAccount implements Persistable {
protected String accountName; protected String accountName;
final List<TradeCurrency> tradeCurrencies = new ArrayList<>(); final List<TradeCurrency> tradeCurrencies = new ArrayList<>();
protected TradeCurrency selectedTradeCurrency; protected TradeCurrency selectedTradeCurrency;
@Nullable
protected Country country = null;
public final PaymentAccountContractData contractData; public final PaymentAccountContractData contractData;
@ -106,16 +102,6 @@ public abstract class PaymentAccount implements Persistable {
this.accountName = accountName; 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) { public void setSelectedTradeCurrency(TradeCurrency tradeCurrency) {
selectedTradeCurrency = tradeCurrency; selectedTradeCurrency = tradeCurrency;
} }
@ -158,21 +144,47 @@ public abstract class PaymentAccount implements Persistable {
} }
/////////////////////////////////////////////////////////////////////////////////////////// @Override
// Util 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 @Override
public String toString() { public String toString() {
return contractData.toString() + '\'' + return "PaymentAccount{" +
"PaymentAccount{" +
"id='" + id + '\'' + "id='" + id + '\'' +
", creationDate=" + creationDate + ", creationDate=" + creationDate +
", paymentMethod=" + paymentMethod + ", paymentMethod=" + paymentMethod +
", accountName='" + accountName + '\'' + ", accountName='" + accountName + '\'' +
", tradeCurrencies=" + tradeCurrencies + ", tradeCurrencies=" + tradeCurrencies +
", selectedTradeCurrency=" + selectedTradeCurrency + ", selectedTradeCurrency=" + selectedTradeCurrency +
", country=" + country +
", contractData=" + contractData + ", contractData=" + contractData +
'}'; '}';
} }

View file

@ -20,18 +20,13 @@ package io.bitsquare.payment;
import io.bitsquare.app.Version; import io.bitsquare.app.Version;
import io.bitsquare.common.wire.Payload; import io.bitsquare.common.wire.Payload;
import javax.annotation.Nullable;
public abstract class PaymentAccountContractData implements Payload { public abstract class PaymentAccountContractData implements Payload {
// That object is sent over the wire, so we need to take care of version compatibility. // 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 static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
private final String paymentMethodName; protected final String paymentMethodName;
private final String id; protected final String id;
private final int maxTradePeriod; protected final int maxTradePeriod;
@Nullable
protected String countryCode;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -44,20 +39,6 @@ public abstract class PaymentAccountContractData implements Payload {
this.maxTradePeriod = maxTradePeriod; this.maxTradePeriod = maxTradePeriod;
} }
///////////////////////////////////////////////////////////////////////////////////////////
// Getter, Setter
///////////////////////////////////////////////////////////////////////////////////////////
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
@Nullable
public String getCountryCode() {
return countryCode;
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Getter // Getter
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -78,6 +59,7 @@ public abstract class PaymentAccountContractData implements Payload {
return maxTradePeriod; return maxTradePeriod;
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
@ -88,8 +70,7 @@ public abstract class PaymentAccountContractData implements Payload {
if (maxTradePeriod != that.maxTradePeriod) return false; if (maxTradePeriod != that.maxTradePeriod) return false;
if (paymentMethodName != null ? !paymentMethodName.equals(that.paymentMethodName) : that.paymentMethodName != null) if (paymentMethodName != null ? !paymentMethodName.equals(that.paymentMethodName) : that.paymentMethodName != null)
return false; return false;
if (id != null ? !id.equals(that.id) : that.id != null) return false; return !(id != null ? !id.equals(that.id) : that.id != null);
return !(countryCode != null ? !countryCode.equals(that.countryCode) : that.countryCode != null);
} }
@ -98,7 +79,15 @@ public abstract class PaymentAccountContractData implements Payload {
int result = paymentMethodName != null ? paymentMethodName.hashCode() : 0; int result = paymentMethodName != null ? paymentMethodName.hashCode() : 0;
result = 31 * result + (id != null ? id.hashCode() : 0); result = 31 * result + (id != null ? id.hashCode() : 0);
result = 31 * result + maxTradePeriod; result = 31 * result + maxTradePeriod;
result = 31 * result + (countryCode != null ? countryCode.hashCode() : 0);
return result; 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: case PaymentMethod.SAME_BANK_ID:
return new SameBankAccount(); return new SameBankAccount();
case PaymentMethod.SPECIFIC_BANKS_ID: case PaymentMethod.SPECIFIC_BANKS_ID:
return new SpecificBankAccount(); return new SpecificBanksAccount();
case PaymentMethod.ALI_PAY_ID: case PaymentMethod.ALI_PAY_ID:
return new AliPayAccount(); return new AliPayAccount();
case PaymentMethod.SWISH_ID: case PaymentMethod.SWISH_ID:
return new SwishAccount(); return new SwishAccount();
case PaymentMethod.BLOCK_CHAINS_ID: case PaymentMethod.BLOCK_CHAINS_ID:
return new BlockChainAccount(); return new CryptoCurrencyAccount();
default: default:
throw new RuntimeException("Not supported PaymentMethod: " + paymentMethod); throw new RuntimeException("Not supported PaymentMethod: " + paymentMethod);
} }

View file

@ -19,7 +19,7 @@ package io.bitsquare.payment;
import io.bitsquare.app.Version; 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. // 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 long serialVersionUID = Version.LOCAL_DB_VERSION;
@ -32,7 +32,13 @@ public final class SameBankAccount extends PaymentAccount {
return new SameBankAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod()); return new SameBankAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
} }
public String getAcceptedBank() { @Override
return ((SameBankAccountContractData) contractData).getBankName(); 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; 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. // 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 long serialVersionUID = Version.LOCAL_DB_VERSION;
@ -34,6 +34,11 @@ public final class SepaAccount extends PaymentAccount {
return new SepaAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod()); return new SepaAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
} }
@Override
public String getBankId() {
return ((SepaAccountContractData) contractData).getBic();
}
public void setHolderName(String holderName) { public void setHolderName(String holderName) {
((SepaAccountContractData) contractData).setHolderName(holderName); ((SepaAccountContractData) contractData).setHolderName(holderName);
} }

View file

@ -27,7 +27,8 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; 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. // 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 static final long serialVersionUID = Version.P2P_NETWORK_VERSION;

View file

@ -21,11 +21,11 @@ import io.bitsquare.app.Version;
import java.util.ArrayList; 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. // 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 long serialVersionUID = Version.LOCAL_DB_VERSION;
public SpecificBankAccount() { public SpecificBanksAccount() {
super(PaymentMethod.SPECIFIC_BANKS); super(PaymentMethod.SPECIFIC_BANKS);
} }
@ -37,4 +37,14 @@ public final class SpecificBankAccount extends PaymentAccount {
public ArrayList<String> getAcceptedBanks() { public ArrayList<String> getAcceptedBanks() {
return ((SpecificBanksAccountContractData) contractData).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 @Override
public String getPaymentDetailsForTradePopup() { public String getPaymentDetailsForTradePopup() {
String holderIdString = BankUtil.requiresHolderId(countryCode) ? (getHolderIdLabel() + ": " + holderId + "\n") : ""; String holderIdString = BankUtil.requiresHolderId(countryCode) ? (getHolderIdLabel() + ": " + holderTaxId + "\n") : "";
return "Holder name: " + holderName + "\n" + return "Holder name: " + holderName + "\n" +
holderIdString + holderIdString +
"Bank name: " + bankName + "\n" + "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.crypto.PubKeyRing;
import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.common.util.JsonExclude; import io.bitsquare.common.util.JsonExclude;
import io.bitsquare.locale.Country;
import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.NodeAddress;
import io.bitsquare.p2p.storage.payload.RequiresOwnerIsOnlinePayload; import io.bitsquare.p2p.storage.payload.RequiresOwnerIsOnlinePayload;
import io.bitsquare.p2p.storage.payload.StoragePayload; import io.bitsquare.p2p.storage.payload.StoragePayload;
@ -84,9 +83,26 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
// Instance fields // Instance fields
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private final String id;
// Fields for filtering offers
private final Direction direction; private final Direction direction;
private final String currencyCode; 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 date;
private final long protocolVersion; private final long protocolVersion;
private final long fiatPrice; private final long fiatPrice;
@ -95,17 +111,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
private final NodeAddress offererNodeAddress; private final NodeAddress offererNodeAddress;
@JsonExclude @JsonExclude
private final PubKeyRing pubKeyRing; private final PubKeyRing pubKeyRing;
private final String paymentMethodName;
@Nullable
private final String paymentMethodCountryCode;
private final String offererPaymentAccountId; 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! // Mutable property. Has to be set before offer is save in P2P network as it changes the objects hash!
private String offerFeePaymentTxID; private String offerFeePaymentTxID;
@ -133,13 +140,14 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
long fiatPrice, long fiatPrice,
long amount, long amount,
long minAmount, long minAmount,
String paymentMethodName,
String currencyCode, String currencyCode,
@Nullable Country paymentMethodCountry,
String offererPaymentAccountId,
ArrayList<NodeAddress> arbitratorNodeAddresses, ArrayList<NodeAddress> arbitratorNodeAddresses,
String paymentMethodName,
String offererPaymentAccountId,
@Nullable String countryCode,
@Nullable ArrayList<String> acceptedCountryCodes, @Nullable ArrayList<String> acceptedCountryCodes,
@Nullable ArrayList<String> acceptedBanks) { @Nullable String bankId,
@Nullable ArrayList<String> acceptedBankIds) {
this.id = id; this.id = id;
this.offererNodeAddress = offererNodeAddress; this.offererNodeAddress = offererNodeAddress;
this.pubKeyRing = pubKeyRing; this.pubKeyRing = pubKeyRing;
@ -147,13 +155,14 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
this.fiatPrice = fiatPrice; this.fiatPrice = fiatPrice;
this.amount = amount; this.amount = amount;
this.minAmount = minAmount; this.minAmount = minAmount;
this.paymentMethodName = paymentMethodName;
this.currencyCode = currencyCode; this.currencyCode = currencyCode;
this.paymentMethodCountryCode = paymentMethodCountry != null ? paymentMethodCountry.code : null;
this.offererPaymentAccountId = offererPaymentAccountId;
this.arbitratorNodeAddresses = arbitratorNodeAddresses; this.arbitratorNodeAddresses = arbitratorNodeAddresses;
this.paymentMethodName = paymentMethodName;
this.offererPaymentAccountId = offererPaymentAccountId;
this.countryCode = countryCode;
this.acceptedCountryCodes = acceptedCountryCodes; this.acceptedCountryCodes = acceptedCountryCodes;
this.acceptedBanks = acceptedBanks; this.bankId = bankId;
this.acceptedBankIds = acceptedBankIds;
protocolVersion = Version.TRADE_PROTOCOL_VERSION; protocolVersion = Version.TRADE_PROTOCOL_VERSION;
@ -331,8 +340,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
} }
@Nullable @Nullable
public String getPaymentMethodCountryCode() { public String getCountryCode() {
return paymentMethodCountryCode; return countryCode;
} }
@Nullable @Nullable
@ -341,8 +350,13 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
} }
@Nullable @Nullable
public List<String> getAcceptedBanks() { public List<String> getAcceptedBankIds() {
return acceptedBanks; return acceptedBankIds;
}
@Nullable
public String getBankId() {
return bankId;
} }
public String getOfferFeePaymentTxID() { 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 (pubKeyRing != null ? !pubKeyRing.equals(offer.pubKeyRing) : offer.pubKeyRing != null) return false;
if (paymentMethodName != null ? !paymentMethodName.equals(offer.paymentMethodName) : offer.paymentMethodName != null) if (paymentMethodName != null ? !paymentMethodName.equals(offer.paymentMethodName) : offer.paymentMethodName != null)
return false; return false;
if (paymentMethodCountryCode != null ? !paymentMethodCountryCode.equals(offer.paymentMethodCountryCode) : offer.paymentMethodCountryCode != null) if (countryCode != null ? !countryCode.equals(offer.countryCode) : offer.countryCode != null)
return false; return false;
if (offererPaymentAccountId != null ? !offererPaymentAccountId.equals(offer.offererPaymentAccountId) : offer.offererPaymentAccountId != null) if (offererPaymentAccountId != null ? !offererPaymentAccountId.equals(offer.offererPaymentAccountId) : offer.offererPaymentAccountId != null)
return false; return false;
if (acceptedCountryCodes != null ? !acceptedCountryCodes.equals(offer.acceptedCountryCodes) : offer.acceptedCountryCodes != null) if (acceptedCountryCodes != null ? !acceptedCountryCodes.equals(offer.acceptedCountryCodes) : offer.acceptedCountryCodes != null)
return false; 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; return false;
if (arbitratorNodeAddresses != null ? !arbitratorNodeAddresses.equals(offer.arbitratorNodeAddresses) : offer.arbitratorNodeAddresses != null) if (arbitratorNodeAddresses != null ? !arbitratorNodeAddresses.equals(offer.arbitratorNodeAddresses) : offer.arbitratorNodeAddresses != null)
return false; return false;
@ -418,10 +433,11 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
result = 31 * result + (offererNodeAddress != null ? offererNodeAddress.hashCode() : 0); result = 31 * result + (offererNodeAddress != null ? offererNodeAddress.hashCode() : 0);
result = 31 * result + (pubKeyRing != null ? pubKeyRing.hashCode() : 0); result = 31 * result + (pubKeyRing != null ? pubKeyRing.hashCode() : 0);
result = 31 * result + (paymentMethodName != null ? paymentMethodName.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 + (offererPaymentAccountId != null ? offererPaymentAccountId.hashCode() : 0);
result = 31 * result + (acceptedCountryCodes != null ? acceptedCountryCodes.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 + (arbitratorNodeAddresses != null ? arbitratorNodeAddresses.hashCode() : 0);
result = 31 * result + (offerFeePaymentTxID != null ? offerFeePaymentTxID.hashCode() : 0); result = 31 * result + (offerFeePaymentTxID != null ? offerFeePaymentTxID.hashCode() : 0);
return result; return result;
@ -440,10 +456,11 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
"\n\toffererAddress=" + offererNodeAddress + "\n\toffererAddress=" + offererNodeAddress +
"\n\tpubKeyRing=" + pubKeyRing + "\n\tpubKeyRing=" + pubKeyRing +
"\n\tpaymentMethodName='" + paymentMethodName + '\'' + "\n\tpaymentMethodName='" + paymentMethodName + '\'' +
"\n\tpaymentMethodCountryCode='" + paymentMethodCountryCode + '\'' + "\n\tpaymentMethodCountryCode='" + countryCode + '\'' +
"\n\toffererPaymentAccountId='" + offererPaymentAccountId + '\'' + "\n\toffererPaymentAccountId='" + offererPaymentAccountId + '\'' +
"\n\tacceptedCountryCodes=" + acceptedCountryCodes + "\n\tacceptedCountryCodes=" + acceptedCountryCodes +
"\n\tacceptedBanks=" + acceptedBanks + "\n\tbankId=" + bankId +
"\n\tacceptedBanks=" + acceptedBankIds +
"\n\tarbitratorAddresses=" + arbitratorNodeAddresses + "\n\tarbitratorAddresses=" + arbitratorNodeAddresses +
"\n\tofferFeePaymentTxID='" + offerFeePaymentTxID + '\'' + "\n\tofferFeePaymentTxID='" + offerFeePaymentTxID + '\'' +
"\n\tstate=" + state + "\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.crypto.Hash;
import io.bitsquare.common.taskrunner.TaskRunner; import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.payment.BlockChainAccountContractData; import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.messages.PayDepositRequest; import io.bitsquare.trade.protocol.trade.messages.PayDepositRequest;
@ -64,10 +64,10 @@ public class ProcessPayDepositRequest extends TradeTask {
PaymentAccountContractData paymentAccountContractData = checkNotNull(payDepositRequest.takerPaymentAccountContractData); PaymentAccountContractData paymentAccountContractData = checkNotNull(payDepositRequest.takerPaymentAccountContractData);
processModel.tradingPeer.setPaymentAccountContractData(paymentAccountContractData); 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 // 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())) { CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, Math.min(32, trade.getId().length())); 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)); 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.crypto.Hash;
import io.bitsquare.common.taskrunner.TaskRunner; import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.payment.BlockChainAccountContractData; import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest; import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest;
@ -52,10 +52,10 @@ public class ProcessPublishDepositTxRequest extends TradeTask {
PaymentAccountContractData paymentAccountContractData = checkNotNull(publishDepositTxRequest.offererPaymentAccountContractData); PaymentAccountContractData paymentAccountContractData = checkNotNull(publishDepositTxRequest.offererPaymentAccountContractData);
processModel.tradingPeer.setPaymentAccountContractData(paymentAccountContractData); 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 // 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())) { CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, Math.min(32, trade.getId().length())); 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)); processModel.tradingPeer.setAccountId(nonEmptyStringOf(publishDepositTxRequest.offererAccountId));

View file

@ -239,15 +239,17 @@ public final class User implements Persistable {
} }
public List<Arbitrator> getAcceptedArbitrators() { public List<Arbitrator> getAcceptedArbitrators() {
return acceptedArbitrators; return acceptedArbitrators != null ? acceptedArbitrators : new ArrayList<>();
} }
public List<NodeAddress> getAcceptedArbitratorAddresses() { 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() { public List<String> getAcceptedLanguageLocaleCodes() {
return acceptedLanguageLocaleCodes; return acceptedLanguageLocaleCodes != null ? acceptedLanguageLocaleCodes : new ArrayList<>();
} }
/* public List<String> getArbitratorAddresses(List<String> idList) { /* 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)) parser.accepts(ProgramArguments.USE_LOCALHOST, description("Use localhost network for development", false))
.withRequiredArg() .withRequiredArg()
.ofType(boolean.class); .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)) parser.accepts(BitcoinNetwork.KEY, description("Bitcoin network", BitcoinNetwork.DEFAULT))
.withRequiredArg() .withRequiredArg()
.ofType(BitcoinNetwork.class) .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.gui.util.validation.InputValidator;
import io.bitsquare.locale.*; import io.bitsquare.locale.*;
import io.bitsquare.payment.BankAccountContractData; import io.bitsquare.payment.BankAccountContractData;
import io.bitsquare.payment.CountryBasedPaymentAccount;
import io.bitsquare.payment.PaymentAccount; import io.bitsquare.payment.PaymentAccount;
import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.payment.PaymentAccountContractData;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
@ -53,9 +54,9 @@ abstract class BankForm extends PaymentMethodForm {
static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) { static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
BankAccountContractData bankAccountContractData = (BankAccountContractData) paymentAccountContractData; BankAccountContractData bankAccountContractData = (BankAccountContractData) paymentAccountContractData;
if (bankAccountContractData.getHolderId() != null) if (bankAccountContractData.getHolderTaxId() != null)
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name / " + bankAccountContractData.getHolderIdLabel(), addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name / " + bankAccountContractData.getHolderIdLabel(),
bankAccountContractData.getHolderName() + " / " + bankAccountContractData.getHolderId()); bankAccountContractData.getHolderName() + " / " + bankAccountContractData.getHolderTaxId());
else else
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name:", bankAccountContractData.getHolderName()); addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name:", bankAccountContractData.getHolderName());
@ -112,10 +113,10 @@ abstract class BankForm extends PaymentMethodForm {
countryComboBox.setOnAction(e -> { countryComboBox.setOnAction(e -> {
Country selectedItem = countryComboBox.getSelectionModel().getSelectedItem(); Country selectedItem = countryComboBox.getSelectionModel().getSelectedItem();
if (selectedItem != null) { if (selectedItem != null) {
paymentAccount.setCountry(selectedItem); getCountryBasedPaymentAccount().setCountry(selectedItem);
String countryCode = selectedItem.code; String countryCode = selectedItem.code;
TradeCurrency currency = CurrencyUtil.getCurrencyByCountryCode(countryCode); TradeCurrency currency = CurrencyUtil.getCurrencyByCountryCode(countryCode);
paymentAccount.setSingleTradeCurrency(currency); this.paymentAccount.setSingleTradeCurrency(currency);
currencyTextField.setText(currency.getNameAndCode()); currencyTextField.setText(currency.getNameAndCode());
bankIdLabel.setText(BankUtil.getBankCodeLabel(bankAccountContractData.getCountryCode())); bankIdLabel.setText(BankUtil.getBankCodeLabel(bankAccountContractData.getCountryCode()));
@ -203,6 +204,10 @@ abstract class BankForm extends PaymentMethodForm {
updateFromInputs(); updateFromInputs();
} }
private CountryBasedPaymentAccount getCountryBasedPaymentAccount() {
return (CountryBasedPaymentAccount) this.paymentAccount;
}
protected void onCountryChanged() { protected void onCountryChanged() {
} }
@ -226,7 +231,7 @@ abstract class BankForm extends PaymentMethodForm {
holderIdInputTextField.setManaged(false); holderIdInputTextField.setManaged(false);
holderIdInputTextField.setValidator(inputValidator); holderIdInputTextField.setValidator(inputValidator);
holderIdInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { holderIdInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
bankAccountContractData.setHolderId(newValue); bankAccountContractData.setHolderTaxId(newValue);
updateFromInputs(); updateFromInputs();
}); });
} }
@ -253,9 +258,9 @@ abstract class BankForm extends PaymentMethodForm {
@Override @Override
public void updateAllInputsValid() { public void updateAllInputsValid() {
boolean holderIdValid = true; boolean holderIdValid = true;
if (paymentAccount.getCountry() != null) { if (getCountryBasedPaymentAccount().getCountry() != null) {
if (BankUtil.requiresHolderId(paymentAccount.getCountry().code)) if (BankUtil.requiresHolderId(getCountryBasedPaymentAccount().getCountry().code))
holderIdValid = inputValidator.validate(bankAccountContractData.getHolderId()).isValid; holderIdValid = inputValidator.validate(bankAccountContractData.getHolderTaxId()).isValid;
} }
allInputsValid.set(isAccountNameValid() allInputsValid.set(isAccountNameValid()
@ -265,7 +270,7 @@ abstract class BankForm extends PaymentMethodForm {
&& inputValidator.validate(bankAccountContractData.getAccountNr()).isValid && inputValidator.validate(bankAccountContractData.getAccountNr()).isValid
&& holderIdValid && holderIdValid
&& paymentAccount.getSingleTradeCurrency() != null && paymentAccount.getSingleTradeCurrency() != null
&& paymentAccount.getCountry() != null); && getCountryBasedPaymentAccount().getCountry() != null);
} }
@Override @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, "Account name:", paymentAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccount.getPaymentMethod().getId())); 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()); addLabelTextField(gridPane, ++gridRow, "Currency:", paymentAccount.getSingleTradeCurrency().getNameAndCode());
addAcceptedBanksForDisplayAccount(); addAcceptedBanksForDisplayAccount();
addHolderNameAndIdForDisplayAccount(); addHolderNameAndIdForDisplayAccount();
@ -293,7 +298,7 @@ abstract class BankForm extends PaymentMethodForm {
TextField holderNameTextField = tuple.second; TextField holderNameTextField = tuple.second;
holderNameTextField.setText(bankAccountContractData.getHolderName()); holderNameTextField.setText(bankAccountContractData.getHolderName());
holderNameTextField.setMinWidth(300); holderNameTextField.setMinWidth(300);
tuple.forth.setText(bankAccountContractData.getHolderId()); tuple.forth.setText(bankAccountContractData.getHolderTaxId());
} else { } else {
addLabelTextField(gridPane, ++gridRow, "Account holder name:", bankAccountContractData.getHolderName()); 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.BSResources;
import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.locale.TradeCurrency; import io.bitsquare.locale.TradeCurrency;
import io.bitsquare.payment.BlockChainAccount; import io.bitsquare.payment.CryptoCurrencyAccount;
import io.bitsquare.payment.BlockChainAccountContractData; import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccount; import io.bitsquare.payment.PaymentAccount;
import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.payment.PaymentAccountContractData;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
@ -42,16 +42,16 @@ import static io.bitsquare.gui.util.FormBuilder.*;
public class BlockChainForm extends PaymentMethodForm { public class BlockChainForm extends PaymentMethodForm {
private static final Logger log = LoggerFactory.getLogger(BlockChainForm.class); private static final Logger log = LoggerFactory.getLogger(BlockChainForm.class);
private final BlockChainAccount blockChainAccount; private final CryptoCurrencyAccount cryptoCurrencyAccount;
private final AltCoinAddressValidator altCoinAddressValidator; private final AltCoinAddressValidator altCoinAddressValidator;
private InputTextField addressInputTextField; private InputTextField addressInputTextField;
private ComboBox<TradeCurrency> currencyComboBox; private ComboBox<TradeCurrency> currencyComboBox;
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) { public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Cryptocurrency address:", ((BlockChainAccountContractData) paymentAccountContractData).getAddress()); addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Cryptocurrency address:", ((CryptoCurrencyAccountContractData) paymentAccountContractData).getAddress());
if (((BlockChainAccountContractData) paymentAccountContractData).getPaymentId() != null) if (((CryptoCurrencyAccountContractData) paymentAccountContractData).getPaymentId() != null)
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Payment ID:", ((BlockChainAccountContractData) paymentAccountContractData).getPaymentId()); addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Payment ID:", ((CryptoCurrencyAccountContractData) paymentAccountContractData).getPaymentId());
return gridRow; return gridRow;
} }
@ -59,7 +59,7 @@ public class BlockChainForm extends PaymentMethodForm {
public BlockChainForm(PaymentAccount paymentAccount, AltCoinAddressValidator altCoinAddressValidator, InputValidator inputValidator, GridPane gridPane, public BlockChainForm(PaymentAccount paymentAccount, AltCoinAddressValidator altCoinAddressValidator, InputValidator inputValidator, GridPane gridPane,
int gridRow) { int gridRow) {
super(paymentAccount, inputValidator, gridPane, gridRow); super(paymentAccount, inputValidator, gridPane, gridRow);
this.blockChainAccount = (BlockChainAccount) paymentAccount; this.cryptoCurrencyAccount = (CryptoCurrencyAccount) paymentAccount;
this.altCoinAddressValidator = altCoinAddressValidator; this.altCoinAddressValidator = altCoinAddressValidator;
} }
@ -73,7 +73,7 @@ public class BlockChainForm extends PaymentMethodForm {
addressInputTextField.setValidator(altCoinAddressValidator); addressInputTextField.setValidator(altCoinAddressValidator);
addressInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { addressInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
blockChainAccount.setAddress(newValue); cryptoCurrencyAccount.setAddress(newValue);
updateFromInputs(); updateFromInputs();
}); });
@ -95,19 +95,19 @@ public class BlockChainForm extends PaymentMethodForm {
@Override @Override
public void addFormForDisplayAccount() { public void addFormForDisplayAccount() {
gridRowFrom = gridRow; gridRowFrom = gridRow;
addLabelTextField(gridPane, gridRow, "Account name:", blockChainAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); addLabelTextField(gridPane, gridRow, "Account name:", cryptoCurrencyAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(blockChainAccount.getPaymentMethod().getId())); addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(cryptoCurrencyAccount.getPaymentMethod().getId()));
TextField field = addLabelTextField(gridPane, ++gridRow, "Cryptocurrency address:", blockChainAccount.getAddress()).second; TextField field = addLabelTextField(gridPane, ++gridRow, "Cryptocurrency address:", cryptoCurrencyAccount.getAddress()).second;
field.setMouseTransparent(false); field.setMouseTransparent(false);
addLabelTextField(gridPane, ++gridRow, "Cryptocurrency:", blockChainAccount.getSingleTradeCurrency().getNameAndCode()); addLabelTextField(gridPane, ++gridRow, "Cryptocurrency:", cryptoCurrencyAccount.getSingleTradeCurrency().getNameAndCode());
addAllowedPeriod(); addAllowedPeriod();
} }
@Override @Override
public void updateAllInputsValid() { public void updateAllInputsValid() {
allInputsValid.set(isAccountNameValid() allInputsValid.set(isAccountNameValid()
&& altCoinAddressValidator.validate(blockChainAccount.getAddress()).isValid && altCoinAddressValidator.validate(cryptoCurrencyAccount.getAddress()).isValid
&& blockChainAccount.getSingleTradeCurrency() != null); && cryptoCurrencyAccount.getSingleTradeCurrency() != null);
} }
@Override @Override

View file

@ -20,6 +20,7 @@ package io.bitsquare.gui.components.paymentmethods;
import io.bitsquare.common.util.Tuple2; import io.bitsquare.common.util.Tuple2;
import io.bitsquare.gui.components.InputTextField; import io.bitsquare.gui.components.InputTextField;
import io.bitsquare.gui.util.validation.InputValidator; import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.payment.CountryBasedPaymentAccount;
import io.bitsquare.payment.PaymentAccount; import io.bitsquare.payment.PaymentAccount;
import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.payment.PaymentAccountContractData;
import javafx.scene.control.Label; import javafx.scene.control.Label;
@ -63,7 +64,7 @@ public class SameBankForm extends BankForm {
&& inputValidator.validate(bankAccountContractData.getBranchId()).isValid && inputValidator.validate(bankAccountContractData.getBranchId()).isValid
&& inputValidator.validate(bankAccountContractData.getAccountNr()).isValid && inputValidator.validate(bankAccountContractData.getAccountNr()).isValid
&& paymentAccount.getSingleTradeCurrency() != null && paymentAccount.getSingleTradeCurrency() != null
&& paymentAccount.getCountry() != null); && ((CountryBasedPaymentAccount) paymentAccount).getCountry() != null);
} }
@Override @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.IBANValidator;
import io.bitsquare.gui.util.validation.InputValidator; import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.locale.*; import io.bitsquare.locale.*;
import io.bitsquare.payment.PaymentAccount; import io.bitsquare.payment.*;
import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.payment.SepaAccount;
import io.bitsquare.payment.SepaAccountContractData;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.geometry.VPos; import javafx.geometry.VPos;
@ -59,7 +56,7 @@ public class SepaForm extends PaymentMethodForm {
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) { public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name:", ((SepaAccountContractData) paymentAccountContractData).getHolderName()); 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, "IBAN:", ((SepaAccountContractData) paymentAccountContractData).getIban());
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "BIC/SWIFT:", ((SepaAccountContractData) paymentAccountContractData).getBic()); addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "BIC/SWIFT:", ((SepaAccountContractData) paymentAccountContractData).getBic());
return gridRow; return gridRow;
@ -228,7 +225,7 @@ public class SepaForm extends PaymentMethodForm {
if (iban.length() > 5) if (iban.length() > 5)
iban = StringUtils.abbreviate(iban, 5); iban = StringUtils.abbreviate(iban, 5);
String method = BSResources.get(paymentAccount.getPaymentMethod().getId()); 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() : "?"; String currency = paymentAccount.getSingleTradeCurrency() != null ? paymentAccount.getSingleTradeCurrency().getCode() : "?";
accountNameTextField.setText(method.concat(", ").concat(currency).concat(", ").concat(country).concat(", ").concat(iban)); 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.TacWindow;
import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow; import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.CountryUtil;
import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.P2PService;
import io.bitsquare.p2p.P2PServiceListener; import io.bitsquare.p2p.P2PServiceListener;
@ -735,7 +734,6 @@ public class MainViewModel implements ViewModel {
okPayAccount.setAccountNr("dummy"); okPayAccount.setAccountNr("dummy");
okPayAccount.setAccountName("OKPay dummy"); okPayAccount.setAccountName("OKPay dummy");
okPayAccount.setSelectedTradeCurrency(CurrencyUtil.getDefaultTradeCurrency()); okPayAccount.setSelectedTradeCurrency(CurrencyUtil.getDefaultTradeCurrency());
okPayAccount.setCountry(CountryUtil.getDefaultCountry());
user.addPaymentAccount(okPayAccount); 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.popups.Popup;
import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow; import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.TradeCurrency; import io.bitsquare.locale.TradeCurrency;
import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.P2PService;
import io.bitsquare.payment.PaymentAccount; import io.bitsquare.payment.*;
import io.bitsquare.payment.SameBankAccount;
import io.bitsquare.payment.SepaAccount;
import io.bitsquare.payment.SpecificBankAccount;
import io.bitsquare.trade.handlers.TransactionResultHandler; import io.bitsquare.trade.handlers.TransactionResultHandler;
import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.offer.Offer;
import io.bitsquare.trade.offer.OpenOfferManager; import io.bitsquare.trade.offer.OpenOfferManager;
@ -242,18 +238,27 @@ class CreateOfferDataModel extends ActivatableDataModel {
long amount = amountAsCoin.get() != null ? amountAsCoin.get().getValue() : 0L; long amount = amountAsCoin.get() != null ? amountAsCoin.get().getValue() : 0L;
long minAmount = minAmountAsCoin.get() != null ? minAmountAsCoin.get().getValue() : 0L; long minAmount = minAmountAsCoin.get() != null ? minAmountAsCoin.get().getValue() : 0L;
ArrayList<String> acceptedCountryCodes = new ArrayList<>(); ArrayList<String> acceptedCountryCodes = null;
if (paymentAccount instanceof SepaAccount) if (paymentAccount instanceof SepaAccount) {
acceptedCountryCodes = new ArrayList<>();
acceptedCountryCodes.addAll(((SepaAccount) paymentAccount).getAcceptedCountryCodes()); acceptedCountryCodes.addAll(((SepaAccount) paymentAccount).getAcceptedCountryCodes());
} else if (paymentAccount instanceof CountryBasedPaymentAccount) {
acceptedCountryCodes = new ArrayList<>();
acceptedCountryCodes.add(((CountryBasedPaymentAccount) paymentAccount).getCountry().code);
}
ArrayList<String> acceptedBanks = new ArrayList<>(); ArrayList<String> acceptedBanks = null;
if (paymentAccount instanceof SpecificBankAccount) if (paymentAccount instanceof SpecificBanksAccount) {
acceptedBanks.addAll(((SpecificBankAccount) paymentAccount).getAcceptedBanks()); acceptedBanks = new ArrayList<>(((SpecificBanksAccount) paymentAccount).getAcceptedBanks());
else if (paymentAccount instanceof SameBankAccount) } else if (paymentAccount instanceof SameBankAccount) {
acceptedBanks.add(((SameBankAccount) paymentAccount).getAcceptedBank()); 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,...) // 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"); checkNotNull(p2PService.getAddress(), "Address must not be null");
return new Offer(offerId, return new Offer(offerId,
@ -263,12 +268,13 @@ class CreateOfferDataModel extends ActivatableDataModel {
fiatPrice, fiatPrice,
amount, amount,
minAmount, minAmount,
paymentAccount.getPaymentMethod().getId(),
tradeCurrencyCode.get(), tradeCurrencyCode.get(),
country,
paymentAccount.getId(),
new ArrayList<>(user.getAcceptedArbitratorAddresses()), new ArrayList<>(user.getAcceptedArbitratorAddresses()),
paymentAccount.getPaymentMethod().getId(),
paymentAccount.getId(),
countryCode,
acceptedCountryCodes, acceptedCountryCodes,
bankId,
acceptedBanks); acceptedBanks);
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -220,7 +220,16 @@ public abstract class Overlay<T extends Overlay> {
public T instruction(String message) { public T instruction(String message) {
type = Type.Instruction; type = Type.Instruction;
if (headLine == null) 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; this.message = message;
setTruncatedMessage(); setTruncatedMessage();
return (T) this; return (T) this;
@ -238,7 +247,7 @@ public abstract class Overlay<T extends Overlay> {
public T feedback(String message) { public T feedback(String message) {
type = Type.Feedback; type = Type.Feedback;
if (headLine == null) if (headLine == null)
this.headLine = "Feedback"; this.headLine = "Completed";
this.message = message; this.message = message;
setTruncatedMessage(); setTruncatedMessage();
return (T) this; return (T) this;

View file

@ -24,7 +24,7 @@ import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.Layout; import io.bitsquare.gui.util.Layout;
import io.bitsquare.locale.BSResources; import io.bitsquare.locale.BSResources;
import io.bitsquare.locale.CountryUtil; import io.bitsquare.locale.CountryUtil;
import io.bitsquare.payment.BlockChainAccountContractData; import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.payment.PaymentMethod; import io.bitsquare.payment.PaymentMethod;
import io.bitsquare.trade.Contract; import io.bitsquare.trade.Contract;
@ -88,7 +88,7 @@ public class ContractWindow extends Overlay<ContractWindow> {
Contract contract = dispute.getContract(); Contract contract = dispute.getContract();
Offer offer = contract.offer; Offer offer = contract.offer;
List<String> acceptedBanks = offer.getAcceptedBanks(); List<String> acceptedBanks = offer.getAcceptedBankIds();
boolean showAcceptedBanks = acceptedBanks != null && !acceptedBanks.isEmpty(); boolean showAcceptedBanks = acceptedBanks != null && !acceptedBanks.isEmpty();
List<String> acceptedCountryCodes = offer.getAcceptedCountryCodes(); List<String> acceptedCountryCodes = offer.getAcceptedCountryCodes();
boolean showAcceptedCountryCodes = acceptedCountryCodes != null && !acceptedCountryCodes.isEmpty(); boolean showAcceptedCountryCodes = acceptedCountryCodes != null && !acceptedCountryCodes.isEmpty();
@ -105,8 +105,8 @@ public class ContractWindow extends Overlay<ContractWindow> {
boolean isPaymentIdAvailable = false; boolean isPaymentIdAvailable = false;
PaymentAccountContractData sellerPaymentAccountContractData = contract.getSellerPaymentAccountContractData(); PaymentAccountContractData sellerPaymentAccountContractData = contract.getSellerPaymentAccountContractData();
if (sellerPaymentAccountContractData instanceof BlockChainAccountContractData && if (sellerPaymentAccountContractData instanceof CryptoCurrencyAccountContractData &&
((BlockChainAccountContractData) sellerPaymentAccountContractData).getPaymentId() != null) { ((CryptoCurrencyAccountContractData) sellerPaymentAccountContractData).getPaymentId() != null) {
rows++; rows++;
isPaymentIdAvailable = true; isPaymentIdAvailable = true;
} }
@ -133,7 +133,7 @@ public class ContractWindow extends Overlay<ContractWindow> {
BSResources.get(sellerPaymentAccountContractData.getPaymentDetails())).second.setMouseTransparent(false); BSResources.get(sellerPaymentAccountContractData.getPaymentDetails())).second.setMouseTransparent(false);
if (isPaymentIdAvailable) if (isPaymentIdAvailable)
addLabelTextField(gridPane, ++rowIndex, "Seller payment ID:", addLabelTextField(gridPane, ++rowIndex, "Seller payment ID:",
((BlockChainAccountContractData) sellerPaymentAccountContractData).getPaymentId()); ((CryptoCurrencyAccountContractData) sellerPaymentAccountContractData).getPaymentId());
if (showAcceptedCountryCodes) { if (showAcceptedCountryCodes) {
String countries; 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;"); headLineLabel.setStyle("-fx-text-fill: -fx-accent; -fx-font-weight: bold; -fx-font-size: 22;");
String url = "https://github.com/bitsquare/bitsquare/releases"; String url = "https://github.com/bitsquare/bitsquare/releases";
HyperlinkWithIcon download = addLabelHyperlinkWithIcon(gridPane, ++rowIndex, "Download:", url).second; HyperlinkWithIcon download = addLabelHyperlinkWithIcon(gridPane, ++rowIndex, "Download:", url).second;
download.setMaxWidth(350); download.setMaxWidth(550);
download.setOnAction(e -> Utilities.openWebPage(url)); download.setOnAction(e -> Utilities.openWebPage(url));
} else { } else {
headLine = "Important information!"; headLine = "Important information!";

View file

@ -392,7 +392,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
if (!finalPeersDispute.isClosed()) if (!finalPeersDispute.isClosed())
UserThread.runAfter(() -> 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); Transitions.DEFAULT_DURATION, TimeUnit.MILLISECONDS);
hide(); hide();

View file

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

View file

@ -186,7 +186,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
if (item != null) { if (item != null) {
Offer offer = item.getTrade().getOffer(); Offer offer = item.getTrade().getOffer();
String method = BSResources.get(offer.getPaymentMethod().getId() + "_SHORT"); String method = BSResources.get(offer.getPaymentMethod().getId() + "_SHORT");
String methodCountryCode = offer.getPaymentMethodCountryCode(); String methodCountryCode = offer.getCountryCode();
if (methodCountryCode != null) if (methodCountryCode != null)
result = method + " (" + methodCountryCode + ")"; 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.gui.util.Layout;
import io.bitsquare.locale.BSResources; import io.bitsquare.locale.BSResources;
import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.payment.BlockChainAccountContractData; import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.payment.PaymentMethod; import io.bitsquare.payment.PaymentMethod;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
@ -66,7 +66,7 @@ public class BuyerStep2View extends TradeStepView {
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData(); PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
String key = "startPayment" + trade.getId(); String key = "startPayment" + trade.getId();
String message = ""; String message = "";
if (paymentAccountContractData instanceof BlockChainAccountContractData) if (paymentAccountContractData instanceof CryptoCurrencyAccountContractData)
message = "Your trade has reached at least one blockchain confirmation.\n" + 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" + "(You can wait for more confirmations if you want - 6 confirmations are considered as very secure.)\n\n" +
"Please transfer from your external " + "Please transfer from your external " +
@ -91,7 +91,7 @@ public class BuyerStep2View extends TradeStepView {
if (preferences.showAgain(key)) { if (preferences.showAgain(key)) {
preferences.dontShowAgain(key, true); preferences.dontShowAgain(key, true);
new Popup().headLine("Attention required for trade with ID " + trade.getShortId()) new Popup().headLine("Attention required for trade with ID " + trade.getShortId())
.instruction(message) .attention(message)
.show(); .show();
} }
} else if (state == Trade.State.BUYER_CONFIRMED_FIAT_PAYMENT_INITIATED) { } 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); log.error("Not supported PaymentMethod: " + paymentMethodName);
} }
if (!(paymentAccountContractData instanceof BlockChainAccountContractData)) if (!(paymentAccountContractData instanceof CryptoCurrencyAccountContractData))
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Reference text:", model.dataModel.getReference()); addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Reference text:", model.dataModel.getReference());
GridPane.setRowSpan(accountTitledGroupBg, gridRow - 3); 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.main.portfolio.pendingtrades.steps.TradeStepView;
import io.bitsquare.gui.util.Layout; import io.bitsquare.gui.util.Layout;
import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.payment.BlockChainAccountContractData; import io.bitsquare.payment.CryptoCurrencyAccountContractData;
import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.trade.Contract; import io.bitsquare.trade.Contract;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
@ -68,8 +68,8 @@ public class SellerStep3View extends TradeStepView {
String message; String message;
String tradeAmountWithCode = model.formatter.formatFiatWithCode(trade.getTradeVolume()); String tradeAmountWithCode = model.formatter.formatFiatWithCode(trade.getTradeVolume());
String currencyName = CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode()); String currencyName = CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode());
if (paymentAccountContractData instanceof BlockChainAccountContractData) { if (paymentAccountContractData instanceof CryptoCurrencyAccountContractData) {
String address = ((BlockChainAccountContractData) paymentAccountContractData).getAddress(); String address = ((CryptoCurrencyAccountContractData) paymentAccountContractData).getAddress();
message = "Your trading partner has confirmed that he initiated the " + currencyName + " payment.\n\n" + message = "Your trading partner has confirmed that he initiated the " + currencyName + " payment.\n\n" +
"Please check on your favorite " + currencyName + "Please check on your favorite " + currencyName +
" blockchain explorer if the transaction to your receiving address\n" + " blockchain explorer if the transaction to your receiving address\n" +
@ -87,7 +87,7 @@ public class SellerStep3View extends TradeStepView {
if (preferences.showAgain(key)) { if (preferences.showAgain(key)) {
preferences.dontShowAgain(key, true); preferences.dontShowAgain(key, true);
new Popup().headLine("Attention required for trade with ID " + trade.getShortId()) new Popup().headLine("Attention required for trade with ID " + trade.getShortId())
.instruction(message) .attention(message)
.show(); .show();
} }
@ -134,8 +134,8 @@ public class SellerStep3View extends TradeStepView {
Contract contract = trade.getContract(); Contract contract = trade.getContract();
if (contract != null) { if (contract != null) {
PaymentAccountContractData paymentAccountContractData = contract.getSellerPaymentAccountContractData(); PaymentAccountContractData paymentAccountContractData = contract.getSellerPaymentAccountContractData();
if (paymentAccountContractData instanceof BlockChainAccountContractData) { if (paymentAccountContractData instanceof CryptoCurrencyAccountContractData) {
paymentDetails = ((BlockChainAccountContractData) paymentAccountContractData).getAddress(); paymentDetails = ((CryptoCurrencyAccountContractData) paymentAccountContractData).getAddress();
title = "Your " + nameByCode + " address:"; title = "Your " + nameByCode + " address:";
isBlockChain = true; isBlockChain = true;
} else { } else {

View file

@ -164,4 +164,4 @@ FED_WIRE_SHORT=Fed Wire
SWISH_SHORT= Swish SWISH_SHORT= Swish
TRANSFER_WISE_SHORT=TransferWise TRANSFER_WISE_SHORT=TransferWise
US_POSTAL_MONEY_ORDER_SHORT=Money order 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) { if (!stopped) {
try { try {
Log.traceCall(); Log.traceCall();
// Throttle outgoing messages // Throttle outbound messages
if (System.currentTimeMillis() - lastSendTimeStamp < 20) { if (System.currentTimeMillis() - lastSendTimeStamp < 20) {
log.info("We got 2 sendMessage requests in less then 20 ms. We set the thread to sleep " + 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={}", "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 final MessageListener messageListener;
private volatile boolean stopped; private volatile boolean stopped;
private long lastReadTimeStamp;
public InputHandler(SharedModel sharedModel, ObjectInputStream objectInputStream, String portInfo, MessageListener messageListener) { public InputHandler(SharedModel sharedModel, ObjectInputStream objectInputStream, String portInfo, MessageListener messageListener) {
this.sharedModel = sharedModel; this.sharedModel = sharedModel;
@ -619,6 +620,16 @@ public class Connection implements MessageListener {
log.trace("InputHandler waiting for incoming messages.\n\tConnection=" + sharedModel.connection); log.trace("InputHandler waiting for incoming messages.\n\tConnection=" + sharedModel.connection);
Object rawInputObject = objectInputStream.readObject(); 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; int size = ByteArrayUtils.objectToByteArray(rawInputObject).length;
boolean doPrintLogs = true; boolean doPrintLogs = true;
if (rawInputObject instanceof Message) { if (rawInputObject instanceof Message) {