mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 07:07:43 +01:00
Merge branch 'Development' into issue544-api
# Conflicts: # pom.xml
This commit is contained in:
commit
b040582f87
98 changed files with 1304 additions and 601 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -19,3 +19,9 @@ build
|
||||||
.project
|
.project
|
||||||
.settings
|
.settings
|
||||||
*.java.hsp
|
*.java.hsp
|
||||||
|
*.~ava
|
||||||
|
/bundles
|
||||||
|
/Bitsquare*
|
||||||
|
desktop.ini
|
||||||
|
*.bat
|
||||||
|
!package/windows/*bit*.bat
|
||||||
|
|
|
@ -24,9 +24,9 @@ public class Version {
|
||||||
private static final Logger log = LoggerFactory.getLogger(Version.class);
|
private static final Logger log = LoggerFactory.getLogger(Version.class);
|
||||||
|
|
||||||
// The application versions
|
// The application versions
|
||||||
public static final String VERSION = "0.4.9.6";
|
public static final String VERSION = "0.4.9.6";
|
||||||
|
|
||||||
// The version nr. for the objects sent over the network. A change will break the serialization of old objects.
|
// The version no. for the objects sent over the network. A change will break the serialization of old objects.
|
||||||
// If objects are used for both network and database the network version is applied.
|
// If objects are used for both network and database the network version is applied.
|
||||||
// VERSION = 0.3.4 -> P2P_NETWORK_VERSION = 1
|
// VERSION = 0.3.4 -> P2P_NETWORK_VERSION = 1
|
||||||
// VERSION = 0.3.5 -> P2P_NETWORK_VERSION = 2
|
// VERSION = 0.3.5 -> P2P_NETWORK_VERSION = 2
|
||||||
|
@ -34,14 +34,14 @@ public class Version {
|
||||||
// VERSION = 0.4.2 -> P2P_NETWORK_VERSION = 4
|
// VERSION = 0.4.2 -> P2P_NETWORK_VERSION = 4
|
||||||
public static final int P2P_NETWORK_VERSION = DevFlags.STRESS_TEST_MODE ? 100 : 4;
|
public static final int P2P_NETWORK_VERSION = DevFlags.STRESS_TEST_MODE ? 100 : 4;
|
||||||
|
|
||||||
// The version nr. of the serialized data stored to disc. A change will break the serialization of old objects.
|
// The version no. of the serialized data stored to disc. A change will break the serialization of old objects.
|
||||||
// VERSION = 0.3.4 -> LOCAL_DB_VERSION = 1
|
// VERSION = 0.3.4 -> LOCAL_DB_VERSION = 1
|
||||||
// VERSION = 0.3.5 -> LOCAL_DB_VERSION = 2
|
// VERSION = 0.3.5 -> LOCAL_DB_VERSION = 2
|
||||||
// VERSION = 0.4.0 -> LOCAL_DB_VERSION = 3
|
// VERSION = 0.4.0 -> LOCAL_DB_VERSION = 3
|
||||||
// VERSION = 0.4.2 -> LOCAL_DB_VERSION = 4
|
// VERSION = 0.4.2 -> LOCAL_DB_VERSION = 4
|
||||||
public static final int LOCAL_DB_VERSION = 4;
|
public static final int LOCAL_DB_VERSION = 4;
|
||||||
|
|
||||||
// The version nr. of the current protocol. The offer holds that version.
|
// The version no. of the current protocol. The offer holds that version.
|
||||||
// A taker will check the version of the offers to see if his version is compatible.
|
// A taker will check the version of the offers to see if his version is compatible.
|
||||||
public static final int TRADE_PROTOCOL_VERSION = 1;
|
public static final int TRADE_PROTOCOL_VERSION = 1;
|
||||||
private static int p2pMessageVersion;
|
private static int p2pMessageVersion;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package io.bitsquare.common;
|
package io.bitsquare.common;
|
||||||
|
|
||||||
|
import io.bitsquare.io.LookAheadObjectInputStream;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -26,15 +27,16 @@ public class ByteArrayUtils {
|
||||||
private static final Logger log = LoggerFactory.getLogger(ByteArrayUtils.class);
|
private static final Logger log = LoggerFactory.getLogger(ByteArrayUtils.class);
|
||||||
private static long lastTimeStamp = System.currentTimeMillis();
|
private static long lastTimeStamp = System.currentTimeMillis();
|
||||||
|
|
||||||
public static <T> T byteArrayToObject(byte[] data) {
|
public static <T> T byteArrayToObject(byte[] data) throws IOException, ClassNotFoundException {
|
||||||
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
||||||
ObjectInput in = null;
|
ObjectInput in = null;
|
||||||
Object result = null;
|
Object result = null;
|
||||||
try {
|
try {
|
||||||
in = new ObjectInputStream(bis);
|
in = new LookAheadObjectInputStream(bis, true);
|
||||||
result = in.readObject();
|
result = in.readObject();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
bis.close();
|
bis.close();
|
||||||
|
|
|
@ -210,7 +210,7 @@ public class Encryption {
|
||||||
// Create a symmetric key
|
// Create a symmetric key
|
||||||
SecretKey secretKey = generateSecretKey();
|
SecretKey secretKey = generateSecretKey();
|
||||||
|
|
||||||
// Encrypt secretKey with receivers publicKey
|
// Encrypt secretKey with receiver's publicKey
|
||||||
byte[] encryptedSecretKey = encryptSecretKey(secretKey, encryptionPublicKey);
|
byte[] encryptedSecretKey = encryptSecretKey(secretKey, encryptionPublicKey);
|
||||||
|
|
||||||
// Encrypt with sym key payload with appended hmac
|
// Encrypt with sym key payload with appended hmac
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class Profiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String printSystemLoadString() {
|
public static String printSystemLoadString() {
|
||||||
return "System load: Memory (MB)): " + getUsedMemoryInMB() + " / Nr. of threads: " + Thread.activeCount();
|
return "System load: Memory (MB)): " + getUsedMemoryInMB() + " / No. of threads: " + Thread.activeCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getUsedMemoryInMB() {
|
public static long getUsedMemoryInMB() {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
import com.google.common.util.concurrent.MoreExecutors;
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
|
import io.bitsquare.io.LookAheadObjectInputStream;
|
||||||
import javafx.scene.input.Clipboard;
|
import javafx.scene.input.Clipboard;
|
||||||
import javafx.scene.input.ClipboardContent;
|
import javafx.scene.input.ClipboardContent;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -210,7 +211,7 @@ public class Utilities {
|
||||||
long free = runtime.freeMemory() / 1024 / 1024;
|
long free = runtime.freeMemory() / 1024 / 1024;
|
||||||
long total = runtime.totalMemory() / 1024 / 1024;
|
long total = runtime.totalMemory() / 1024 / 1024;
|
||||||
long used = total - free;
|
long used = total - free;
|
||||||
log.info("System load (nr. threads/used memory (MB)): " + Thread.activeCount() + "/" + used);
|
log.info("System load (no. threads/used memory (MB)): " + Thread.activeCount() + "/" + used);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copyToClipboard(String content) {
|
public static void copyToClipboard(String content) {
|
||||||
|
@ -254,8 +255,8 @@ public class Utilities {
|
||||||
try {
|
try {
|
||||||
ByteArrayInputStream byteInputStream =
|
ByteArrayInputStream byteInputStream =
|
||||||
new ByteArrayInputStream(org.bitcoinj.core.Utils.parseAsHexOrBase58(serializedHexString));
|
new ByteArrayInputStream(org.bitcoinj.core.Utils.parseAsHexOrBase58(serializedHexString));
|
||||||
|
|
||||||
try (ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream)) {
|
try (ObjectInputStream objectInputStream = new LookAheadObjectInputStream(byteInputStream)) {
|
||||||
result = objectInputStream.readObject();
|
result = objectInputStream.readObject();
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -293,7 +294,7 @@ public class Utilities {
|
||||||
ObjectInput in = null;
|
ObjectInput in = null;
|
||||||
Object result = null;
|
Object result = null;
|
||||||
try {
|
try {
|
||||||
in = new ObjectInputStream(bis);
|
in = new LookAheadObjectInputStream(bis, true);
|
||||||
result = in.readObject();
|
result = in.readObject();
|
||||||
if (!(result instanceof Serializable))
|
if (!(result instanceof Serializable))
|
||||||
throw new RuntimeException("Object not of type Serializable");
|
throw new RuntimeException("Object not of type Serializable");
|
||||||
|
@ -356,8 +357,7 @@ public class Utilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Object copy(Serializable orig) {
|
public static Object copy(Serializable orig) throws IOException, ClassNotFoundException {
|
||||||
Object obj = null;
|
|
||||||
try {
|
try {
|
||||||
// Write the object out to a byte array
|
// Write the object out to a byte array
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
@ -368,12 +368,13 @@ public class Utilities {
|
||||||
|
|
||||||
// Make an input stream from the byte array and read
|
// Make an input stream from the byte array and read
|
||||||
// a copy of the object back in.
|
// a copy of the object back in.
|
||||||
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
|
ObjectInputStream in = new LookAheadObjectInputStream(new ByteArrayInputStream(bos.toByteArray()), true);
|
||||||
obj = in.readObject();
|
Object obj = in.readObject();
|
||||||
|
return obj;
|
||||||
} catch (IOException | ClassNotFoundException e) {
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String readTextFileFromServer(String url, String userAgent) throws IOException {
|
public static String readTextFileFromServer(String url, String userAgent) throws IOException {
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
* 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.io;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on https://github.com/ikkisoft/SerialKiller but we removed the support for a config file as
|
||||||
|
* that introduced many dependencies (like the vulnerable commons collections).
|
||||||
|
*/
|
||||||
|
public class LookAheadObjectInputStream extends ObjectInputStream {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(LookAheadObjectInputStream.class);
|
||||||
|
|
||||||
|
// Covers classes used in the objects sent over the P2P network.
|
||||||
|
// We don't add all particular classes as the risk to miss one (specially at updates) is too high and a package
|
||||||
|
// based filter gives us sufficient security.
|
||||||
|
// This white list is not sufficient for the objects used for local persistence! We don't use any white list for those.
|
||||||
|
private static final Pattern[] whiteListP2PNetwork = {
|
||||||
|
Pattern.compile("io\\.bitsquare\\..*$"),
|
||||||
|
Pattern.compile("org\\.bitcoinj\\..*$"),
|
||||||
|
|
||||||
|
Pattern.compile("java\\.lang\\.Boolean$"),
|
||||||
|
Pattern.compile("java\\.lang\\.Enum$"),
|
||||||
|
Pattern.compile("java\\.lang\\.Integer$"),
|
||||||
|
Pattern.compile("java\\.lang\\.Long$"),
|
||||||
|
Pattern.compile("java\\.lang\\.Double$"),
|
||||||
|
Pattern.compile("java\\.lang\\.Number$"),
|
||||||
|
|
||||||
|
Pattern.compile("java\\.util\\.ArrayList$"),
|
||||||
|
Pattern.compile("java\\.util\\.Date$"),
|
||||||
|
Pattern.compile("java\\.util\\.HashSet$"),
|
||||||
|
Pattern.compile("java\\.util\\.HashMap$"),
|
||||||
|
|
||||||
|
// Type Signatures
|
||||||
|
// https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html
|
||||||
|
Pattern.compile("\\[B$") // byte array
|
||||||
|
};
|
||||||
|
|
||||||
|
private final static Pattern[] blackList = {
|
||||||
|
Pattern.compile("bsh\\.XThis$"),
|
||||||
|
Pattern.compile("bsh\\.Interpreter$"),
|
||||||
|
Pattern.compile("com\\.mchange\\.v2\\.c3p0\\.impl\\.PoolBackedDataSourceBase$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.beanutils\\.BeanComparator$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.collections\\.Transformer$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.collections\\.functors\\.InvokerTransformer$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.collections\\.functors\\.ChainedTransformer$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.collections\\.functors\\.ConstantTransformer$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.collections\\.functors\\.InstantiateTransformer$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.collections4\\.functors\\.InvokerTransformer$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.collections4\\.functors\\.ChainedTransformer$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.collections4\\.functors\\.ConstantTransformer$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.collections4\\.functors\\.InstantiateTransformer$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.collections4\\.comparators\\.TransformingComparator$"),
|
||||||
|
Pattern.compile("org\\.apache\\.commons\\.fileupload\\.disk\\.DiskFileItem$"),
|
||||||
|
Pattern.compile("org\\.apache\\.wicket\\.util\\.upload\\.DiskFileItem$"),
|
||||||
|
Pattern.compile("org\\.codehaus\\.groovy\\.runtime\\.ConvertedClosure$"),
|
||||||
|
Pattern.compile("org\\.codehaus\\.groovy\\.runtime\\.MethodClosure$"),
|
||||||
|
Pattern.compile("org\\.hibernate\\.engine\\.spi\\.TypedValue$"),
|
||||||
|
Pattern.compile("org\\.hibernate\\.tuple\\.component\\.AbstractComponentTuplizer$"),
|
||||||
|
Pattern.compile("org\\.hibernate\\.tuple\\.component\\.PojoComponentTuplizer$"),
|
||||||
|
Pattern.compile("org\\.hibernate\\.type\\.AbstractType$"),
|
||||||
|
Pattern.compile("org\\.hibernate\\.type\\.ComponentType$"),
|
||||||
|
Pattern.compile("org\\.hibernate\\.type\\.Type$"),
|
||||||
|
Pattern.compile("com\\.sun\\.rowset\\.JdbcRowSetImpl$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.builder\\.InterceptionModelBuilder$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.builder\\.MethodReference$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.proxy\\.DefaultInvocationContextFactory$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.proxy\\.InterceptorMethodHandler$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.reader\\.ClassMetadataInterceptorReference$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.reader\\.DefaultMethodMetadata$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.reader\\.ReflectiveClassMetadata$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.reader\\.SimpleInterceptorMetadata$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.spi\\.instance\\.InterceptorInstantiator$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.spi\\.metadata\\.InterceptorReference$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.spi\\.metadata\\.MethodMetadata$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.spi\\.model\\.InterceptionModel$"),
|
||||||
|
Pattern.compile("org\\.jboss\\.(weld\\.)?interceptor\\.spi\\.model\\.InterceptionType$"),
|
||||||
|
Pattern.compile("java\\.rmi\\.registry\\.Registry$"),
|
||||||
|
Pattern.compile("java\\.rmi\\.server\\.ObjID$"),
|
||||||
|
Pattern.compile("java\\.rmi\\.server\\.RemoteObjectInvocationHandler$"),
|
||||||
|
Pattern.compile("net\\.sf\\.json\\.JSONObject$"),
|
||||||
|
Pattern.compile("javax\\.xml\\.transform\\.Templates$"),
|
||||||
|
Pattern.compile("org\\.python\\.core\\.PyObject$"),
|
||||||
|
Pattern.compile("org\\.python\\.core\\.PyBytecode$"),
|
||||||
|
Pattern.compile("org\\.python\\.core\\.PyFunction$"),
|
||||||
|
Pattern.compile("org\\.mozilla\\.javascript\\..*$"),
|
||||||
|
Pattern.compile("org\\.apache\\.myfaces\\.context\\.servlet\\.FacesContextImpl$"),
|
||||||
|
Pattern.compile("org\\.apache\\.myfaces\\.context\\.servlet\\.FacesContextImplBase$"),
|
||||||
|
Pattern.compile("org\\.apache\\.myfaces\\.el\\.CompositeELResolver$"),
|
||||||
|
Pattern.compile("org\\.apache\\.myfaces\\.el\\.unified\\.FacesELContext$"),
|
||||||
|
Pattern.compile("org\\.apache\\.myfaces\\.view\\.facelets\\.el\\.ValueExpressionMethodExpression$"),
|
||||||
|
Pattern.compile("com\\.sun\\.syndication\\.feed\\.impl\\.ObjectBean$"),
|
||||||
|
Pattern.compile("org\\.springframework\\.beans\\.factory\\.ObjectFactory$"),
|
||||||
|
Pattern.compile("org\\.springframework\\.core\\.SerializableTypeWrapper\\$MethodInvokeTypeProvider$"),
|
||||||
|
Pattern.compile("org\\.springframework\\.aop\\.framework\\.AdvisedSupport$"),
|
||||||
|
Pattern.compile("org\\.springframework\\.aop\\.target\\.SingletonTargetSource$"),
|
||||||
|
Pattern.compile("org\\.springframework\\.aop\\.framework\\.JdkDynamicAopProxy$"),
|
||||||
|
Pattern.compile("org\\.springframework\\.core\\.SerializableTypeWrapper\\$TypeProvider$"),
|
||||||
|
Pattern.compile("java\\.util\\.PriorityQueue$"),
|
||||||
|
Pattern.compile("java\\.lang\\.reflect\\.Proxy$"),
|
||||||
|
Pattern.compile("java\\.util\\.Comparator$"),
|
||||||
|
Pattern.compile("org\\.reflections\\.Reflections$"),
|
||||||
|
|
||||||
|
Pattern.compile("com\\.sun\\.org\\.apache\\.xalan\\.internal\\.xsltc\\.trax\\.TemplatesImpl$"),
|
||||||
|
};
|
||||||
|
private boolean useWhiteList;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param inputStream The original inputStream
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
|
||||||
|
this(inputStream, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param inputStream The original inputStream
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public LookAheadObjectInputStream(InputStream inputStream, boolean useWhiteList) throws IOException {
|
||||||
|
super(inputStream);
|
||||||
|
|
||||||
|
this.useWhiteList = useWhiteList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
||||||
|
String name = desc.getName();
|
||||||
|
// log.error("resolveClass " + name);
|
||||||
|
|
||||||
|
for (Pattern pattern : blackList) {
|
||||||
|
if (pattern.matcher(name).find()) {
|
||||||
|
String msg = "We received a blacklisted class at Java deserialization: '" + name + "'" + "(regex pattern: " + pattern.toString() + ")";
|
||||||
|
log.error(msg);
|
||||||
|
throw new InvalidClassException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useWhiteList) {
|
||||||
|
boolean whiteListed = false;
|
||||||
|
for (Pattern pattern : whiteListP2PNetwork) {
|
||||||
|
if (pattern.matcher(name).find())
|
||||||
|
whiteListed = true;
|
||||||
|
}
|
||||||
|
if (!whiteListed) {
|
||||||
|
String msg = "We received a non-whitelisted class at Java deserialization: '" + name + "'";
|
||||||
|
log.error(msg);
|
||||||
|
throw new InvalidClassException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.resolveClass(desc);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ package io.bitsquare.storage;
|
||||||
|
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.common.UserThread;
|
||||||
import io.bitsquare.common.util.Utilities;
|
import io.bitsquare.common.util.Utilities;
|
||||||
|
import io.bitsquare.io.LookAheadObjectInputStream;
|
||||||
import org.bitcoinj.core.Utils;
|
import org.bitcoinj.core.Utils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -103,7 +104,7 @@ public class FileManager<T> {
|
||||||
public synchronized T read(File file) throws IOException, ClassNotFoundException {
|
public synchronized T read(File file) throws IOException, ClassNotFoundException {
|
||||||
log.debug("read" + file);
|
log.debug("read" + file);
|
||||||
try (final FileInputStream fileInputStream = new FileInputStream(file);
|
try (final FileInputStream fileInputStream = new FileInputStream(file);
|
||||||
final ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
|
final ObjectInputStream objectInputStream = new LookAheadObjectInputStream(fileInputStream, false)) {
|
||||||
return (T) objectInputStream.readObject();
|
return (T) objectInputStream.readObject();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
log.error("Exception at read: " + t.getMessage());
|
log.error("Exception at read: " + t.getMessage());
|
||||||
|
|
|
@ -105,7 +105,7 @@ public abstract class BitsquareExecutable {
|
||||||
parser.accepts(CoreOptionKeys.APP_DATA_DIR_KEY, description("Application data directory", DEFAULT_APP_DATA_DIR))
|
parser.accepts(CoreOptionKeys.APP_DATA_DIR_KEY, description("Application data directory", DEFAULT_APP_DATA_DIR))
|
||||||
.withRequiredArg();
|
.withRequiredArg();
|
||||||
parser.accepts(CoreOptionKeys.IGNORE_DEV_MSG_KEY, description("If set to true all signed messages from Bitsquare developers are ignored " +
|
parser.accepts(CoreOptionKeys.IGNORE_DEV_MSG_KEY, description("If set to true all signed messages from Bitsquare developers are ignored " +
|
||||||
"(Global alert, Version update alert, Filters for offers, nodes or payment account data)", false))
|
"(Global alert, Version update alert, Filters for offers, nodes or trading account data)", false))
|
||||||
.withRequiredArg()
|
.withRequiredArg()
|
||||||
.ofType(boolean.class);
|
.ofType(boolean.class);
|
||||||
parser.accepts(CoreOptionKeys.DUMP_STATISTICS, description("If set to true the trade statistics are stored as json file in the data dir.", false))
|
parser.accepts(CoreOptionKeys.DUMP_STATISTICS, description("If set to true the trade statistics are stored as json file in the data dir.", false))
|
||||||
|
|
|
@ -163,11 +163,19 @@ public class DisputeManager {
|
||||||
else
|
else
|
||||||
openDisputes.put(dispute.getTradeId(), dispute);
|
openDisputes.put(dispute.getTradeId(), dispute);
|
||||||
});
|
});
|
||||||
openDisputes.entrySet().stream().forEach(stringDisputeEntry -> {
|
|
||||||
if (closedDisputes.containsKey(stringDisputeEntry.getKey())) {
|
// If we have duplicate disputes we close the second one (might happen if both traders opened a dispute and arbitrator
|
||||||
final Dispute dispute = stringDisputeEntry.getValue();
|
// was offline, so could not forward msg to other peer, then the arbitrator might have 4 disputes open for 1 trade)
|
||||||
dispute.setIsClosed(true);
|
openDisputes.entrySet().stream().forEach(openDisputeEntry -> {
|
||||||
tradeManager.closeDisputedTrade(dispute.getTradeId());
|
String key = openDisputeEntry.getKey();
|
||||||
|
if (closedDisputes.containsKey(key)) {
|
||||||
|
final Dispute closedDispute = closedDisputes.get(key);
|
||||||
|
final Dispute openDispute = openDisputeEntry.getValue();
|
||||||
|
// We need to check if is from the same peer, we don't want to close the peers dispute
|
||||||
|
if (closedDispute.getTraderId() == openDispute.getTraderId()) {
|
||||||
|
openDispute.setIsClosed(true);
|
||||||
|
tradeManager.closeDisputedTrade(openDispute.getTradeId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -557,10 +565,22 @@ public class DisputeManager {
|
||||||
final Contract contract = dispute.getContract();
|
final Contract contract = dispute.getContract();
|
||||||
|
|
||||||
boolean isBuyer = keyRing.getPubKeyRing().equals(contract.getBuyerPubKeyRing());
|
boolean isBuyer = keyRing.getPubKeyRing().equals(contract.getBuyerPubKeyRing());
|
||||||
if ((isBuyer && disputeResult.getWinner() == DisputeResult.Winner.BUYER)
|
DisputeResult.Winner publisher = disputeResult.getWinner();
|
||||||
|| (!isBuyer && disputeResult.getWinner() == DisputeResult.Winner.SELLER)
|
|
||||||
|| (isBuyer && disputeResult.getWinner() == DisputeResult.Winner.STALE_MATE)) {
|
|
||||||
|
|
||||||
|
// Sometimes the user who receives the trade amount is never online, so we might want to
|
||||||
|
// let the loser publish the tx. When the winner comes online he gets his funds as it was published by the other peer.
|
||||||
|
// Default isLoserPublisher is set to false
|
||||||
|
if (disputeResult.isLoserPublisher()) {
|
||||||
|
// we invert the logic
|
||||||
|
if (publisher == DisputeResult.Winner.BUYER)
|
||||||
|
publisher = DisputeResult.Winner.SELLER;
|
||||||
|
else if (publisher == DisputeResult.Winner.SELLER)
|
||||||
|
publisher = DisputeResult.Winner.BUYER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((isBuyer && publisher == DisputeResult.Winner.BUYER)
|
||||||
|
|| (!isBuyer && publisher == DisputeResult.Winner.SELLER)
|
||||||
|
|| (isBuyer && publisher == DisputeResult.Winner.STALE_MATE)) {
|
||||||
|
|
||||||
final Optional<Trade> tradeOptional = tradeManager.getTradeById(tradeId);
|
final Optional<Trade> tradeOptional = tradeManager.getTradeById(tradeId);
|
||||||
Transaction payoutTx = null;
|
Transaction payoutTx = null;
|
||||||
|
@ -636,7 +656,7 @@ public class DisputeManager {
|
||||||
} else {
|
} else {
|
||||||
log.debug("We got a dispute result msg but we don't have a matching dispute. " +
|
log.debug("We got a dispute result msg but we don't have a matching dispute. " +
|
||||||
"That might happen when we get the disputeResultMessage before the dispute was created. " +
|
"That might happen when we get the disputeResultMessage before the dispute was created. " +
|
||||||
"We try again after 1 sec. to apply the disputeResultMessage. TradeId = " + tradeId);
|
"We try again after 2 sec. to apply the disputeResultMessage. TradeId = " + tradeId);
|
||||||
if (!delayMsgMap.containsKey(uid)) {
|
if (!delayMsgMap.containsKey(uid)) {
|
||||||
// We delay2 sec. to be sure the comm. msg gets added first
|
// We delay2 sec. to be sure the comm. msg gets added first
|
||||||
Timer timer = UserThread.runAfter(() -> onDisputeResultMessage(disputeResultMessage), 2);
|
Timer timer = UserThread.runAfter(() -> onDisputeResultMessage(disputeResultMessage), 2);
|
||||||
|
|
|
@ -81,6 +81,7 @@ public final class DisputeResult implements Payload {
|
||||||
private String arbitratorAddressAsString;
|
private String arbitratorAddressAsString;
|
||||||
private byte[] arbitratorPubKey;
|
private byte[] arbitratorPubKey;
|
||||||
private long closeDate;
|
private long closeDate;
|
||||||
|
private boolean isLoserPublisher;
|
||||||
|
|
||||||
transient private BooleanProperty tamperProofEvidenceProperty = new SimpleBooleanProperty();
|
transient private BooleanProperty tamperProofEvidenceProperty = new SimpleBooleanProperty();
|
||||||
transient private BooleanProperty idVerificationProperty = new SimpleBooleanProperty();
|
transient private BooleanProperty idVerificationProperty = new SimpleBooleanProperty();
|
||||||
|
@ -245,6 +246,14 @@ public final class DisputeResult implements Payload {
|
||||||
return winner;
|
return winner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLoserIsPublisher(boolean loserPublisher) {
|
||||||
|
this.isLoserPublisher = loserPublisher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLoserPublisher() {
|
||||||
|
return isLoserPublisher;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|
|
@ -275,7 +275,7 @@ public class TradeWalletService {
|
||||||
* @param takerRawTransactionInputs Raw data for the connected outputs for all inputs of the taker (normally 1 input)
|
* @param takerRawTransactionInputs Raw data for the connected outputs for all inputs of the taker (normally 1 input)
|
||||||
* @param takerChangeOutputValue Optional taker change output value
|
* @param takerChangeOutputValue Optional taker change output value
|
||||||
* @param takerChangeAddressString Optional taker change address
|
* @param takerChangeAddressString Optional taker change address
|
||||||
* @param offererAddressEntry The offerers address entry.
|
* @param offererAddressEntry The offerer's address entry.
|
||||||
* @param buyerPubKey The public key of the buyer.
|
* @param buyerPubKey The public key of the buyer.
|
||||||
* @param sellerPubKey The public key of the seller.
|
* @param sellerPubKey The public key of the seller.
|
||||||
* @param arbitratorPubKey The public key of the arbitrator.
|
* @param arbitratorPubKey The public key of the arbitrator.
|
||||||
|
@ -452,10 +452,10 @@ public class TradeWalletService {
|
||||||
checkArgument(!buyerInputs.isEmpty());
|
checkArgument(!buyerInputs.isEmpty());
|
||||||
checkArgument(!sellerInputs.isEmpty());
|
checkArgument(!sellerInputs.isEmpty());
|
||||||
|
|
||||||
// Check if offerers Multisig script is identical to the takers
|
// Check if offerer's Multisig script is identical to the takers
|
||||||
Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
|
Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
|
||||||
if (!offerersDepositTx.getOutput(0).getScriptPubKey().equals(p2SHMultiSigOutputScript))
|
if (!offerersDepositTx.getOutput(0).getScriptPubKey().equals(p2SHMultiSigOutputScript))
|
||||||
throw new TransactionVerificationException("Offerers p2SHMultiSigOutputScript does not match to takers p2SHMultiSigOutputScript");
|
throw new TransactionVerificationException("Offerer's p2SHMultiSigOutputScript does not match to takers p2SHMultiSigOutputScript");
|
||||||
|
|
||||||
// The outpoints are not available from the serialized offerersDepositTx, so we cannot use that tx directly, but we use it to construct a new
|
// The outpoints are not available from the serialized offerersDepositTx, so we cannot use that tx directly, but we use it to construct a new
|
||||||
// depositTx
|
// depositTx
|
||||||
|
@ -489,7 +489,7 @@ public class TradeWalletService {
|
||||||
TransactionOutput offerersContractHashOutput = offerersDepositTx.getOutputs().get(1);
|
TransactionOutput offerersContractHashOutput = offerersDepositTx.getOutputs().get(1);
|
||||||
log.debug("offerersContractHashOutput " + offerersContractHashOutput);
|
log.debug("offerersContractHashOutput " + offerersContractHashOutput);
|
||||||
if (!offerersContractHashOutput.getScriptPubKey().equals(contractHashOutput.getScriptPubKey()))
|
if (!offerersContractHashOutput.getScriptPubKey().equals(contractHashOutput.getScriptPubKey()))
|
||||||
throw new TransactionVerificationException("Offerers transaction output for the contract hash is not matching takers version.");
|
throw new TransactionVerificationException("Offerer's transaction output for the contract hash is not matching takers version.");
|
||||||
|
|
||||||
// Add all outputs from offerersDepositTx to depositTx
|
// Add all outputs from offerersDepositTx to depositTx
|
||||||
offerersDepositTx.getOutputs().forEach(depositTx::addOutput);
|
offerersDepositTx.getOutputs().forEach(depositTx::addOutput);
|
||||||
|
|
|
@ -257,9 +257,9 @@ public class WalletService {
|
||||||
walletAppKit.setLookaheadSize(500);
|
walletAppKit.setLookaheadSize(500);
|
||||||
|
|
||||||
// Calculation is derived from: https://www.reddit.com/r/Bitcoin/comments/2vrx6n/privacy_in_bitcoinj_android_wallet_multibit_hive/coknjuz
|
// Calculation is derived from: https://www.reddit.com/r/Bitcoin/comments/2vrx6n/privacy_in_bitcoinj_android_wallet_multibit_hive/coknjuz
|
||||||
// Nr of false positives (56M keys in the blockchain):
|
// No. of false positives (56M keys in the blockchain):
|
||||||
// First attempt for FP rate:
|
// First attempt for FP rate:
|
||||||
// FP rate = 0,0001; Nr of false positives: 0,0001 * 56 000 000 = 5600
|
// FP rate = 0,0001; No. of false positives: 0,0001 * 56 000 000 = 5600
|
||||||
// We have 1333keys: 1333 / (5600 + 1333) = 0.19 -> 19 % probability that a pub key is in our wallet
|
// We have 1333keys: 1333 / (5600 + 1333) = 0.19 -> 19 % probability that a pub key is in our wallet
|
||||||
// After tests I found out that the bandwidth consumption varies widely related to the generated filter.
|
// After tests I found out that the bandwidth consumption varies widely related to the generated filter.
|
||||||
// About 20- 40 MB for upload and 30-130 MB for download at first start up (spv chain).
|
// About 20- 40 MB for upload and 30-130 MB for download at first start up (spv chain).
|
||||||
|
@ -270,7 +270,7 @@ public class WalletService {
|
||||||
// consumption.
|
// consumption.
|
||||||
|
|
||||||
// For now to reduce risks with high bandwidth consumption we reduce the FP rate by half.
|
// For now to reduce risks with high bandwidth consumption we reduce the FP rate by half.
|
||||||
// FP rate = 0,00005; Nr of false positives: 0,00005 * 56 000 000 = 2800
|
// FP rate = 0,00005; No. of false positives: 0,00005 * 56 000 000 = 2800
|
||||||
// 1333 / (2800 + 1333) = 0.32 -> 32 % probability that a pub key is in our wallet
|
// 1333 / (2800 + 1333) = 0.32 -> 32 % probability that a pub key is in our wallet
|
||||||
walletAppKit.setBloomFilterFalsePositiveRate(0.00005);
|
walletAppKit.setBloomFilterFalsePositiveRate(0.00005);
|
||||||
|
|
||||||
|
@ -714,7 +714,7 @@ public class WalletService {
|
||||||
public void doubleSpendTransaction(Transaction txToDoubleSpend, Address toAddress, Runnable resultHandler, ErrorMessageHandler errorMessageHandler) throws InsufficientMoneyException, AddressFormatException, AddressEntryException {
|
public void doubleSpendTransaction(Transaction txToDoubleSpend, Address toAddress, Runnable resultHandler, ErrorMessageHandler errorMessageHandler) throws InsufficientMoneyException, AddressFormatException, AddressEntryException {
|
||||||
final TransactionConfidence.ConfidenceType confidenceType = txToDoubleSpend.getConfidence().getConfidenceType();
|
final TransactionConfidence.ConfidenceType confidenceType = txToDoubleSpend.getConfidence().getConfidenceType();
|
||||||
if (confidenceType == TransactionConfidence.ConfidenceType.PENDING) {
|
if (confidenceType == TransactionConfidence.ConfidenceType.PENDING) {
|
||||||
log.debug("txToDoubleSpend nr. of inputs " + txToDoubleSpend.getInputs().size());
|
log.debug("txToDoubleSpend no. of inputs " + txToDoubleSpend.getInputs().size());
|
||||||
|
|
||||||
Transaction newTransaction = new Transaction(params);
|
Transaction newTransaction = new Transaction(params);
|
||||||
txToDoubleSpend.getInputs().stream().forEach(input -> {
|
txToDoubleSpend.getInputs().stream().forEach(input -> {
|
||||||
|
@ -739,7 +739,7 @@ public class WalletService {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
log.debug("newTransaction nr. of inputs " + newTransaction.getInputs().size());
|
log.debug("newTransaction no. of inputs " + newTransaction.getInputs().size());
|
||||||
log.debug("newTransaction size in kB " + newTransaction.bitcoinSerialize().length / 1024);
|
log.debug("newTransaction size in kB " + newTransaction.bitcoinSerialize().length / 1024);
|
||||||
|
|
||||||
if (!newTransaction.getInputs().isEmpty()) {
|
if (!newTransaction.getInputs().isEmpty()) {
|
||||||
|
@ -1031,7 +1031,7 @@ public class WalletService {
|
||||||
Wallet.SendRequest sendRequestForMultipleAddresses = getSendRequestForMultipleAddresses(fromAddresses, toAddress, amount, null, aesKey);
|
Wallet.SendRequest sendRequestForMultipleAddresses = getSendRequestForMultipleAddresses(fromAddresses, toAddress, amount, null, aesKey);
|
||||||
Transaction tx = sendRequestForMultipleAddresses.tx;
|
Transaction tx = sendRequestForMultipleAddresses.tx;
|
||||||
wallet.completeTx(sendRequestForMultipleAddresses);
|
wallet.completeTx(sendRequestForMultipleAddresses);
|
||||||
log.debug("Nr of inputs: " + tx.getInputs().size());
|
log.debug("No. of inputs: " + tx.getInputs().size());
|
||||||
int size = tx.bitcoinSerialize().length;
|
int size = tx.bitcoinSerialize().length;
|
||||||
log.debug("Tx size: " + size);
|
log.debug("Tx size: " + size);
|
||||||
return size;
|
return size;
|
||||||
|
|
|
@ -179,7 +179,7 @@ public class PriceFeedService {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
String errorMessage = "We don't have a price for currencyCode " + currencyCode;
|
String errorMessage = "We don't have a price for " + currencyCode;
|
||||||
log.debug(errorMessage);
|
log.debug(errorMessage);
|
||||||
faultHandler.handleFault(errorMessage, new PriceRequestException(errorMessage));
|
faultHandler.handleFault(errorMessage, new PriceRequestException(errorMessage));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package io.bitsquare.btc.pricefeed.providers;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import com.google.gson.internal.LinkedTreeMap;
|
||||||
|
import io.bitsquare.btc.pricefeed.MarketPrice;
|
||||||
|
import io.bitsquare.http.HttpClient;
|
||||||
|
import io.bitsquare.http.HttpException;
|
||||||
|
import io.bitsquare.user.Preferences;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// Using new BitcoinAverage API but we wait for an optimisation as the call contains much more data as we need and
|
||||||
|
// the json is about 300kb instead od 30 kb in the old API.
|
||||||
|
public class BitcoinAverage2PriceProvider extends PriceProvider {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(BitcoinAverage2PriceProvider.class);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public BitcoinAverage2PriceProvider(HttpClient httpClient, Preferences preferences) {
|
||||||
|
super(httpClient, preferences, "https://apiv2.bitcoinaverage.com/indices/global/ticker/", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, MarketPrice> getAllPrices() throws IOException, HttpException {
|
||||||
|
Map<String, MarketPrice> marketPriceMap = new HashMap<>();
|
||||||
|
LinkedTreeMap<String, Object> treeMap = new Gson().<LinkedTreeMap<String, Object>>fromJson(httpClient.requestWithGET("all"), LinkedTreeMap.class);
|
||||||
|
Map<String, String> temp = new HashMap<>();
|
||||||
|
treeMap.entrySet().stream().forEach(e -> {
|
||||||
|
Object value = e.getValue();
|
||||||
|
|
||||||
|
// We need to check the type as we get an unexpected "timestamp" object at the end:
|
||||||
|
if (value instanceof LinkedTreeMap) {
|
||||||
|
LinkedTreeMap<String, Object> treeMap2 = (LinkedTreeMap) value;
|
||||||
|
temp.clear();
|
||||||
|
treeMap2.entrySet().stream().forEach(e2 -> temp.put(e2.getKey(), e2.getValue().toString()));
|
||||||
|
String key = e.getKey().replace("BTC", "");
|
||||||
|
marketPriceMap.put(key,
|
||||||
|
new MarketPrice(key, temp.get("ask"), temp.get("bid"), temp.get("last")));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return marketPriceMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MarketPrice getPrice(String currencyCode) throws IOException, HttpException {
|
||||||
|
//Log.traceCall("currencyCode=" + currencyCode);
|
||||||
|
JsonObject jsonObject = new JsonParser()
|
||||||
|
.parse(httpClient.requestWithGET("BTC" + currencyCode))
|
||||||
|
.getAsJsonObject();
|
||||||
|
return new MarketPrice(currencyCode,
|
||||||
|
jsonObject.get("ask").getAsString(),
|
||||||
|
jsonObject.get("bid").getAsString(),
|
||||||
|
jsonObject.get("last").getAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BitcoinAveragePriceProvider";
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,6 @@ import java.security.PublicKey;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public final class Filter implements StoragePayload {
|
public final class Filter implements StoragePayload {
|
||||||
|
@ -38,23 +37,20 @@ public final class Filter implements StoragePayload {
|
||||||
private static final Logger log = LoggerFactory.getLogger(Filter.class);
|
private static final Logger log = LoggerFactory.getLogger(Filter.class);
|
||||||
private static final long TTL = TimeUnit.DAYS.toMillis(21);
|
private static final long TTL = TimeUnit.DAYS.toMillis(21);
|
||||||
|
|
||||||
public final List<String> bannedNodeAddress;
|
public final ArrayList<String> bannedNodeAddress;
|
||||||
public final List<String> bannedOfferIds;
|
public final ArrayList<String> bannedOfferIds;
|
||||||
public final List<PaymentAccountFilter> bannedPaymentAccounts;
|
public final ArrayList<PaymentAccountFilter> bannedPaymentAccounts;
|
||||||
private String signatureAsBase64;
|
private String signatureAsBase64;
|
||||||
private transient PublicKey publicKey;
|
|
||||||
private byte[] publicKeyBytes;
|
private byte[] publicKeyBytes;
|
||||||
|
|
||||||
public Filter(List<String> bannedOfferIds, List<String> bannedNodeAddress, List<PaymentAccountFilter> bannedPaymentAccounts) {
|
private transient PublicKey publicKey;
|
||||||
|
|
||||||
|
public Filter(ArrayList<String> bannedOfferIds, ArrayList<String> bannedNodeAddress, ArrayList<PaymentAccountFilter> bannedPaymentAccounts) {
|
||||||
this.bannedOfferIds = bannedOfferIds;
|
this.bannedOfferIds = bannedOfferIds;
|
||||||
this.bannedNodeAddress = bannedNodeAddress;
|
this.bannedNodeAddress = bannedNodeAddress;
|
||||||
this.bannedPaymentAccounts = bannedPaymentAccounts;
|
this.bannedPaymentAccounts = bannedPaymentAccounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Filter() {
|
|
||||||
this(new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||||
try {
|
try {
|
||||||
in.defaultReadObject();
|
in.defaultReadObject();
|
||||||
|
|
|
@ -10,6 +10,7 @@ public class PaymentAccountFilter implements Serializable {
|
||||||
// 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 static final Logger log = LoggerFactory.getLogger(PaymentAccountFilter.class);
|
private static final Logger log = LoggerFactory.getLogger(PaymentAccountFilter.class);
|
||||||
|
|
||||||
public final String paymentMethodId;
|
public final String paymentMethodId;
|
||||||
public final String getMethodName;
|
public final String getMethodName;
|
||||||
public final String value;
|
public final String value;
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class BankUtil {
|
||||||
case "CA":
|
case "CA":
|
||||||
return "Transit Number:";
|
return "Transit Number:";
|
||||||
default:
|
default:
|
||||||
return isBranchIdRequired(countryCode) ? "Branch nr.:" : "Branch nr. (optional):";
|
return isBranchIdRequired(countryCode) ? "Branch no.:" : "Branch no. (optional):";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ public class BankUtil {
|
||||||
case "MX":
|
case "MX":
|
||||||
return "CLABE:";
|
return "CLABE:";
|
||||||
default:
|
default:
|
||||||
return "Account nr. (e.g. IBAN):";
|
return "Account no. (e.g. IBAN):";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,20 +140,17 @@ public class CountryUtil {
|
||||||
return allCountries;
|
return allCountries;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use getAvailableLocales as we depend on display names (would be a bit painful with translations if handled
|
|
||||||
// from a static list -or we find something ready made?).
|
|
||||||
private static List<Locale> getAllCountryLocales() {
|
private static List<Locale> getAllCountryLocales() {
|
||||||
List<Locale> allLocales = Arrays.asList(Locale.getAvailableLocales());
|
List<Locale> allLocales = LocaleUtil.getAllLocales();
|
||||||
Set<Locale> allLocalesAsSet = allLocales.stream().filter(locale -> !"".equals(locale.getCountry()))
|
|
||||||
.map(locale -> new Locale("", locale.getCountry(), ""))
|
// Filter duplicate locale entries
|
||||||
|
Set<Locale> allLocalesAsSet = allLocales.stream().filter(locale -> !locale.getCountry().isEmpty())
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
allLocales = new ArrayList<>();
|
List<Locale> allCountryLocales = new ArrayList<>();
|
||||||
allLocales.addAll(allLocalesAsSet);
|
allCountryLocales.addAll(allLocalesAsSet);
|
||||||
allLocales.add(new Locale("", "MD", "")); // Moldava
|
allCountryLocales.sort((locale1, locale2) -> locale1.getDisplayCountry().compareTo(locale2.getDisplayCountry()));
|
||||||
allLocales.add(new Locale("", "KH", "")); // Cambodia
|
return allCountryLocales;
|
||||||
allLocales.sort((locale1, locale2) -> locale1.getDisplayCountry().compareTo(locale2.getDisplayCountry()));
|
|
||||||
return allLocales;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> getNamesByCodes(List<String> countryCodes) {
|
private static List<String> getNamesByCodes(List<String> countryCodes) {
|
||||||
|
@ -164,7 +161,7 @@ public class CountryUtil {
|
||||||
private static final String[] countryCodes = new String[]{"AE", "AL", "AR", "AT", "AU", "BA", "BE", "BG", "BH",
|
private static final String[] countryCodes = new String[]{"AE", "AL", "AR", "AT", "AU", "BA", "BE", "BG", "BH",
|
||||||
"BO", "BR", "BY", "CA", "CH", "CL", "CN", "CO", "CR", "CS", "CU", "CY", "CZ", "DE", "DK", "DO", "DZ",
|
"BO", "BR", "BY", "CA", "CH", "CL", "CN", "CO", "CR", "CS", "CU", "CY", "CZ", "DE", "DK", "DO", "DZ",
|
||||||
"EC", "EE", "EG", "ES", "FI", "FR", "GB", "GR", "GT", "HK", "HN", "HR", "HU", "ID", "IE", "IL", "IN",
|
"EC", "EE", "EG", "ES", "FI", "FR", "GB", "GR", "GT", "HK", "HN", "HR", "HU", "ID", "IE", "IL", "IN",
|
||||||
"IQ", "IS", "IT", "JO", "JP", "KH", "KR", "KW", "LB", "LT", "LU", "LV", "LY", "MA", "MD", "ME", "MK", "MT", "MX",
|
"IQ", "IS", "IT", "JO", "JP", "KE", "KH", "KR", "KW", "KZ", "LB", "LT", "LU", "LV", "LY", "MA", "MD", "ME", "MK", "MT", "MX",
|
||||||
"MY", "NI", "NL", "NO", "NZ", "OM", "PA", "PE", "PH", "PL", "PR", "PT", "PY", "QA", "RO", "RS", "RU",
|
"MY", "NI", "NL", "NO", "NZ", "OM", "PA", "PE", "PH", "PL", "PR", "PT", "PY", "QA", "RO", "RS", "RU",
|
||||||
"SA", "SD", "SE", "SG", "SI", "SK", "SV", "SY", "TH", "TN", "TR", "TW", "UA", "US", "UY", "VE", "VN",
|
"SA", "SD", "SE", "SG", "SI", "SK", "SV", "SY", "TH", "TN", "TR", "TW", "UA", "US", "UY", "VE", "VN",
|
||||||
"YE", "ZA"};
|
"YE", "ZA"};
|
||||||
|
@ -173,7 +170,7 @@ public class CountryUtil {
|
||||||
private static final String[] regionCodes = new String[]{"AS", "EU", "SA", "EU", "OC", "EU", "EU", "EU", "AS",
|
private static final String[] regionCodes = new String[]{"AS", "EU", "SA", "EU", "OC", "EU", "EU", "EU", "AS",
|
||||||
"SA", "SA", "EU", "NA", "EU", "SA", "AS", "SA", "NA", "EU", "NA", "EU", "EU", "EU", "EU", "NA", "AF",
|
"SA", "SA", "EU", "NA", "EU", "SA", "AS", "SA", "NA", "EU", "NA", "EU", "EU", "EU", "EU", "NA", "AF",
|
||||||
"SA", "EU", "AF", "EU", "EU", "EU", "EU", "EU", "NA", "AS", "NA", "EU", "EU", "AS", "EU", "AS", "AS",
|
"SA", "EU", "AF", "EU", "EU", "EU", "EU", "EU", "NA", "AS", "NA", "EU", "EU", "AS", "EU", "AS", "AS",
|
||||||
"AS", "EU", "EU", "AS", "AS", "AS", "AS", "AS", "AS", "EU", "EU", "EU", "AF", "AF", "EU", "EU", "EU", "EU", "NA",
|
"AS", "EU", "EU", "AS", "AS", "AF", "AS", "AS", "AS", "AS", "AS", "EU", "EU", "EU", "AF", "AF", "EU", "EU", "EU", "EU", "NA",
|
||||||
"AS", "NA", "EU", "EU", "OC", "AS", "NA", "SA", "AS", "EU", "NA", "EU", "SA", "AS", "EU", "EU", "EU",
|
"AS", "NA", "EU", "EU", "OC", "AS", "NA", "SA", "AS", "EU", "NA", "EU", "SA", "AS", "EU", "EU", "EU",
|
||||||
"AS", "AF", "EU", "AS", "EU", "EU", "NA", "AS", "AS", "AF", "AS", "AS", "EU", "NA", "SA", "SA", "AS",
|
"AS", "AF", "EU", "AS", "EU", "EU", "NA", "AS", "AS", "AF", "AS", "AS", "EU", "NA", "SA", "SA", "AS",
|
||||||
"AS", "AF"};
|
"AS", "AF"};
|
||||||
|
|
|
@ -74,93 +74,113 @@ public class CurrencyUtil {
|
||||||
// https://forum.bitsquare.io/t/how-to-add-your-favorite-altcoin/
|
// https://forum.bitsquare.io/t/how-to-add-your-favorite-altcoin/
|
||||||
public static List<CryptoCurrency> createAllSortedCryptoCurrenciesList() {
|
public static List<CryptoCurrency> createAllSortedCryptoCurrenciesList() {
|
||||||
final List<CryptoCurrency> result = new ArrayList<>();
|
final List<CryptoCurrency> result = new ArrayList<>();
|
||||||
result.add(new CryptoCurrency("XMR", "Monero"));
|
|
||||||
result.add(new CryptoCurrency("SC", "Siacoin"));
|
result.add(new CryptoCurrency("AIB", "Advanced Internet Blocks"));
|
||||||
result.add(new CryptoCurrency("ETH", "Ether"));
|
result.add(new CryptoCurrency("ANTI", "Anti"));
|
||||||
result.add(new CryptoCurrency("ETC", "EtherClassic"));
|
result.add(new CryptoCurrency("ARG", "Argentum"));
|
||||||
result.add(new CryptoCurrency("STEEM", "STEEM"));
|
result.add(new CryptoCurrency("REP", "Augur", true));
|
||||||
result.add(new CryptoCurrency("STEEMUSD", "Steem Dollars", true));
|
result.add(new CryptoCurrency("BATL", "Battlestars"));
|
||||||
result.add(new CryptoCurrency("FLO", "FlorinCoin"));
|
result.add(new CryptoCurrency("BIGUP", "BigUp"));
|
||||||
result.add(new CryptoCurrency("MT", "Mycelium Token", true));
|
result.add(new CryptoCurrency("BITAUD", "BitAUD", true));
|
||||||
result.add(new CryptoCurrency("XEM", "NEM"));
|
result.add(new CryptoCurrency("BITCHF", "BitCHF", true));
|
||||||
result.add(new CryptoCurrency("LTC", "Litecoin"));
|
result.add(new CryptoCurrency("BITCNY", "BitCNY", true));
|
||||||
|
result.add(new CryptoCurrency("BITEUR", "BitEUR", true));
|
||||||
|
result.add(new CryptoCurrency("BITGBP", "BitGBP", true));
|
||||||
|
result.add(new CryptoCurrency("BITHKD", "BitHKD", true));
|
||||||
|
result.add(new CryptoCurrency("BITNZD", "BitNZD", true));
|
||||||
|
result.add(new CryptoCurrency("BITSEK", "BitSEK", true));
|
||||||
|
result.add(new CryptoCurrency("BITSGD", "BitSGD", true));
|
||||||
|
result.add(new CryptoCurrency("SYNQ", "BitSYNQ"));
|
||||||
|
result.add(new CryptoCurrency("BTS", "BitShares"));
|
||||||
|
result.add(new CryptoCurrency("BITUSD", "BitUSD", true));
|
||||||
|
result.add(new CryptoCurrency("BLK", "Blackcoin"));
|
||||||
|
result.add(new CryptoCurrency("BURST", "Burstcoin"));
|
||||||
|
result.add(new CryptoCurrency("CLAM", "Clams"));
|
||||||
|
result.add(new CryptoCurrency("CLOAK", "CloakCoin"));
|
||||||
|
result.add(new CryptoCurrency("CMT", "Comet"));
|
||||||
|
result.add(new CryptoCurrency("XCP", "Counterparty"));
|
||||||
|
result.add(new CryptoCurrency("CRBIT", "Creditbit"));
|
||||||
|
result.add(new CryptoCurrency("CBX", "Crypto Bullion"));
|
||||||
|
result.add(new CryptoCurrency("DAO", "DAO", true));
|
||||||
|
result.add(new CryptoCurrency("DIBC", "DIBCOIN"));
|
||||||
result.add(new CryptoCurrency("DASH", "Dash"));
|
result.add(new CryptoCurrency("DASH", "Dash"));
|
||||||
|
result.add(new CryptoCurrency("DCR", "Decred"));
|
||||||
|
result.add(new CryptoCurrency("DGB", "Digibyte"));
|
||||||
|
result.add(new CryptoCurrency("DRS", "Digital Rupees"));
|
||||||
|
result.add(new CryptoCurrency("DGD", "DigixDAO Tokens", true));
|
||||||
|
result.add(new CryptoCurrency("DOGE", "Dogecoin"));
|
||||||
|
result.add(new CryptoCurrency("DMC", "DynamicCoin"));
|
||||||
|
result.add(new CryptoCurrency("EMC", "Emercoin"));
|
||||||
|
result.add(new CryptoCurrency("EURT", "EUR Tether"));
|
||||||
|
result.add(new CryptoCurrency("ESP", "Espers"));
|
||||||
|
result.add(new CryptoCurrency("ENT", "Eternity"));
|
||||||
|
result.add(new CryptoCurrency("ETH", "Ether"));
|
||||||
|
result.add(new CryptoCurrency("ETC", "Ether Classic"));
|
||||||
|
result.add(new CryptoCurrency("ERC", "Europecoin"));
|
||||||
|
result.add(new CryptoCurrency("EGC", "EverGreenCoin"));
|
||||||
|
result.add(new CryptoCurrency("FCT", "Factom"));
|
||||||
|
result.add(new CryptoCurrency("FAIR", "FairCoin"));
|
||||||
|
result.add(new CryptoCurrency("FLO", "FlorinCoin"));
|
||||||
|
result.add(new CryptoCurrency("GEMZ", "Gemz"));
|
||||||
|
result.add(new CryptoCurrency("GRC", "Gridcoin"));
|
||||||
|
result.add(new CryptoCurrency("GRS", "Groestlcoin"));
|
||||||
|
result.add(new CryptoCurrency("NLG", "Gulden"));
|
||||||
|
result.add(new CryptoCurrency("HODL", "HOdlcoin"));
|
||||||
|
result.add(new CryptoCurrency("HNC", "HunCoin"));
|
||||||
|
result.add(new CryptoCurrency("IOC", "I/O Coin"));
|
||||||
|
result.add(new CryptoCurrency("JPYT", "JPY Tether"));
|
||||||
|
result.add(new CryptoCurrency("JBS", "Jumbucks"));
|
||||||
|
result.add(new CryptoCurrency("LBC", "LBRY Credits"));
|
||||||
|
result.add(new CryptoCurrency("LSK", "Lisk"));
|
||||||
|
result.add(new CryptoCurrency("LTC", "Litecoin"));
|
||||||
|
result.add(new CryptoCurrency("STR", "Lumen"));
|
||||||
|
result.add(new CryptoCurrency("MAID", "MaidSafeCoin"));
|
||||||
|
result.add(new CryptoCurrency("MKR", "Maker", true));
|
||||||
|
result.add(new CryptoCurrency("MXT", "MarteXcoin"));
|
||||||
|
result.add(new CryptoCurrency("MOIN", "Moin"));
|
||||||
|
result.add(new CryptoCurrency("XMR", "Monero"));
|
||||||
|
result.add(new CryptoCurrency("MT", "Mycelium Token", true));
|
||||||
|
result.add(new CryptoCurrency("XMY", "Myriadcoin"));
|
||||||
|
result.add(new CryptoCurrency("NAV", "Nav Coin"));
|
||||||
|
result.add(new CryptoCurrency("XEM", "NEM"));
|
||||||
result.add(new CryptoCurrency("NMC", "Namecoin"));
|
result.add(new CryptoCurrency("NMC", "Namecoin"));
|
||||||
result.add(new CryptoCurrency("NBT", "NuBits"));
|
result.add(new CryptoCurrency("NBT", "NuBits"));
|
||||||
result.add(new CryptoCurrency("NSR", "NuShares"));
|
result.add(new CryptoCurrency("NSR", "NuShares"));
|
||||||
result.add(new CryptoCurrency("SDC", "ShadowCash"));
|
|
||||||
result.add(new CryptoCurrency("BTS", "BitShares"));
|
|
||||||
result.add(new CryptoCurrency("BITUSD", "BitUSD", true));
|
|
||||||
result.add(new CryptoCurrency("BITEUR", "BitEUR", true));
|
|
||||||
result.add(new CryptoCurrency("BITCNY", "BitCNY", true));
|
|
||||||
result.add(new CryptoCurrency("BITCHF", "BitCHF", true));
|
|
||||||
result.add(new CryptoCurrency("BITGBP", "BitGBP", true));
|
|
||||||
result.add(new CryptoCurrency("BITNZD", "BitNZD", true));
|
|
||||||
result.add(new CryptoCurrency("BITAUD", "BitAUD", true));
|
|
||||||
result.add(new CryptoCurrency("BITSGD", "BitSGD", true));
|
|
||||||
result.add(new CryptoCurrency("BITHKD", "BitHKD", true));
|
|
||||||
result.add(new CryptoCurrency("BITSEK", "BitSEK", true));
|
|
||||||
result.add(new CryptoCurrency("PPC", "Peercoin"));
|
|
||||||
result.add(new CryptoCurrency("XPM", "Primecoin"));
|
|
||||||
result.add(new CryptoCurrency("SJCX", "StorjcoinX"));
|
|
||||||
result.add(new CryptoCurrency("GEMZ", "Gemz"));
|
|
||||||
result.add(new CryptoCurrency("DOGE", "Dogecoin"));
|
|
||||||
result.add(new CryptoCurrency("BLK", "Blackcoin"));
|
|
||||||
result.add(new CryptoCurrency("FCT", "Factom"));
|
|
||||||
result.add(new CryptoCurrency("NXT", "Nxt"));
|
result.add(new CryptoCurrency("NXT", "Nxt"));
|
||||||
result.add(new CryptoCurrency("XCP", "Counterparty"));
|
|
||||||
result.add(new CryptoCurrency("XRP", "Ripple"));
|
|
||||||
result.add(new CryptoCurrency("FAIR", "FairCoin"));
|
|
||||||
result.add(new CryptoCurrency("MKR", "Maker", true));
|
|
||||||
result.add(new CryptoCurrency("DGD", "DigixDAO Tokens", true));
|
|
||||||
result.add(new CryptoCurrency("ANTI", "Anti"));
|
|
||||||
result.add(new CryptoCurrency("VPN", "VPNCoin"));
|
|
||||||
result.add(new CryptoCurrency("MAID", "MaidSafeCoin"));
|
|
||||||
result.add(new CryptoCurrency("YBC", "YbCoin"));
|
|
||||||
result.add(new CryptoCurrency("CLOAK", "CloakCoin"));
|
|
||||||
result.add(new CryptoCurrency("EGC", "EverGreenCoin"));
|
|
||||||
result.add(new CryptoCurrency("VRC", "VeriCoin"));
|
|
||||||
result.add(new CryptoCurrency("ESP", "Espers"));
|
|
||||||
result.add(new CryptoCurrency("XVG", "Verge"));
|
|
||||||
result.add(new CryptoCurrency("XMY", "Myriadcoin"));
|
|
||||||
result.add(new CryptoCurrency("MXT", "MarteXcoin"));
|
|
||||||
result.add(new CryptoCurrency("GRS", "Groestlcoin"));
|
|
||||||
result.add(new CryptoCurrency("IOC", "I/O Coin"));
|
|
||||||
result.add(new CryptoCurrency("SIB", "Sibcoin"));
|
|
||||||
result.add(new CryptoCurrency("CRBIT", "Creditbit"));
|
|
||||||
result.add(new CryptoCurrency("BIGUP", "BigUp"));
|
|
||||||
result.add(new CryptoCurrency("XPTX", "PlatinumBar"));
|
|
||||||
result.add(new CryptoCurrency("JBS", "Jumbucks"));
|
|
||||||
result.add(new CryptoCurrency("PINK", "Pinkcoin"));
|
|
||||||
result.add(new CryptoCurrency("OK", "OKCash"));
|
result.add(new CryptoCurrency("OK", "OKCash"));
|
||||||
result.add(new CryptoCurrency("GRC", "Gridcoin"));
|
|
||||||
result.add(new CryptoCurrency("MOIN", "Moin"));
|
|
||||||
result.add(new CryptoCurrency("SLR", "SolarCoin"));
|
|
||||||
result.add(new CryptoCurrency("SHIFT", "Shift"));
|
|
||||||
result.add(new CryptoCurrency("ERC", "Europecoin"));
|
|
||||||
result.add(new CryptoCurrency("POST", "PostCoin"));
|
|
||||||
result.add(new CryptoCurrency("LSK", "Lisk"));
|
|
||||||
result.add(new CryptoCurrency("USDT", "USD Tether"));
|
|
||||||
result.add(new CryptoCurrency("EURT", "EUR Tether"));
|
|
||||||
result.add(new CryptoCurrency("JPYT", "JPY Tether"));
|
|
||||||
result.add(new CryptoCurrency("SYNX", "Syndicate"));
|
|
||||||
result.add(new CryptoCurrency("WDC", "Worldcoin"));
|
|
||||||
result.add(new CryptoCurrency("DAO", "DAO", true));
|
|
||||||
result.add(new CryptoCurrency("CMT", "Comet"));
|
|
||||||
result.add(new CryptoCurrency("SYNQ", "BitSYNQ"));
|
|
||||||
result.add(new CryptoCurrency("LBC", "LBRY Credits"));
|
|
||||||
result.add(new CryptoCurrency("HNC", "HunCoin"));
|
|
||||||
result.add(new CryptoCurrency("UNO", "Unobtanium"));
|
|
||||||
result.add(new CryptoCurrency("DGB", "Digibyte"));
|
|
||||||
result.add(new CryptoCurrency("VCN", "VCoin"));
|
|
||||||
result.add(new CryptoCurrency("DCR", "Decred"));
|
|
||||||
result.add(new CryptoCurrency("CBX", "Crypto Bullion"));
|
|
||||||
result.add(new CryptoCurrency("1CR", "1CRedit"));
|
|
||||||
result.add(new CryptoCurrency("YACC", "YACCoin"));
|
|
||||||
result.add(new CryptoCurrency("AIB", "Advanced Internet Blocks"));
|
|
||||||
result.add(new CryptoCurrency("OPAL", "Opal"));
|
result.add(new CryptoCurrency("OPAL", "Opal"));
|
||||||
|
result.add(new CryptoCurrency("PPC", "Peercoin"));
|
||||||
|
result.add(new CryptoCurrency("PINK", "Pinkcoin"));
|
||||||
|
result.add(new CryptoCurrency("XPTX", "PlatinumBar"));
|
||||||
|
result.add(new CryptoCurrency("PLU", "Plutons", true));
|
||||||
|
result.add(new CryptoCurrency("POST", "PostCoin"));
|
||||||
|
result.add(new CryptoCurrency("XPM", "Primecoin"));
|
||||||
|
result.add(new CryptoCurrency("XRP", "Ripple"));
|
||||||
|
result.add(new CryptoCurrency("STEEM", "STEEM"));
|
||||||
|
result.add(new CryptoCurrency("SDC", "ShadowCash"));
|
||||||
|
result.add(new CryptoCurrency("SHIFT", "Shift"));
|
||||||
|
result.add(new CryptoCurrency("SC", "Siacoin"));
|
||||||
|
result.add(new CryptoCurrency("SF", "Siafund"));
|
||||||
|
result.add(new CryptoCurrency("SIB", "Sibcoin"));
|
||||||
|
result.add(new CryptoCurrency("SLR", "SolarCoin"));
|
||||||
|
result.add(new CryptoCurrency("STEEMUSD", "Steem Dollars", true));
|
||||||
|
result.add(new CryptoCurrency("SJCX", "StorjcoinX"));
|
||||||
|
result.add(new CryptoCurrency("SYNX", "Syndicate"));
|
||||||
result.add(new CryptoCurrency("AMP", "Synereo", true));
|
result.add(new CryptoCurrency("AMP", "Synereo", true));
|
||||||
|
result.add(new CryptoCurrency("TRI", "Triangles"));
|
||||||
|
result.add(new CryptoCurrency("USDT", "USD Tether"));
|
||||||
|
result.add(new CryptoCurrency("UNO", "Unobtanium"));
|
||||||
|
result.add(new CryptoCurrency("VCN", "VCoin"));
|
||||||
|
result.add(new CryptoCurrency("VPN", "VPNCoin"));
|
||||||
|
result.add(new CryptoCurrency("XVC", "Vcash"));
|
||||||
|
result.add(new CryptoCurrency("XVG", "Verge"));
|
||||||
|
result.add(new CryptoCurrency("VRC", "VeriCoin"));
|
||||||
|
result.add(new CryptoCurrency("WDC", "Worldcoin"));
|
||||||
|
result.add(new CryptoCurrency("YACC", "YACCoin"));
|
||||||
|
result.add(new CryptoCurrency("YBC", "YbCoin"));
|
||||||
|
result.add(new CryptoCurrency("ZEC", "Zcash"));
|
||||||
|
result.add(new CryptoCurrency("XZC", "Zcoin"));
|
||||||
|
|
||||||
result.sort(TradeCurrency::compareTo);
|
result.sort(TradeCurrency::compareTo);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -168,11 +188,14 @@ public class CurrencyUtil {
|
||||||
public static List<CryptoCurrency> getMainCryptoCurrencies() {
|
public static List<CryptoCurrency> getMainCryptoCurrencies() {
|
||||||
final List<CryptoCurrency> result = new ArrayList<>();
|
final List<CryptoCurrency> result = new ArrayList<>();
|
||||||
result.add(new CryptoCurrency("XMR", "Monero"));
|
result.add(new CryptoCurrency("XMR", "Monero"));
|
||||||
|
result.add(new CryptoCurrency("ZEC", "Zcash"));
|
||||||
|
result.add(new CryptoCurrency("XZC", "Zcoin"));
|
||||||
result.add(new CryptoCurrency("SC", "Siacoin"));
|
result.add(new CryptoCurrency("SC", "Siacoin"));
|
||||||
result.add(new CryptoCurrency("ETH", "Ether"));
|
result.add(new CryptoCurrency("ETH", "Ether"));
|
||||||
result.add(new CryptoCurrency("ETC", "EtherClassic"));
|
result.add(new CryptoCurrency("ETC", "Ether Classic"));
|
||||||
result.add(new CryptoCurrency("STEEM", "STEEM"));
|
result.add(new CryptoCurrency("STEEM", "STEEM"));
|
||||||
result.add(new CryptoCurrency("MT", "Mycelium Token", true));
|
result.add(new CryptoCurrency("MT", "Mycelium Token", true));
|
||||||
|
result.add(new CryptoCurrency("REP", "Augur", true));
|
||||||
result.add(new CryptoCurrency("FLO", "FlorinCoin"));
|
result.add(new CryptoCurrency("FLO", "FlorinCoin"));
|
||||||
result.add(new CryptoCurrency("LTC", "Litecoin"));
|
result.add(new CryptoCurrency("LTC", "Litecoin"));
|
||||||
result.add(new CryptoCurrency("DASH", "Dash"));
|
result.add(new CryptoCurrency("DASH", "Dash"));
|
||||||
|
|
|
@ -21,22 +21,27 @@ import io.bitsquare.user.Preferences;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class LanguageUtil {
|
public class LanguageUtil {
|
||||||
private static final Logger log = LoggerFactory.getLogger(LanguageUtil.class);
|
private static final Logger log = LoggerFactory.getLogger(LanguageUtil.class);
|
||||||
|
|
||||||
public static List<String> getAllLanguageCodes() {
|
public static List<String> getAllLanguageCodes() {
|
||||||
List<Locale> allLocales = Arrays.asList(Locale.getAvailableLocales());
|
List<Locale> allLocales = LocaleUtil.getAllLocales();
|
||||||
final Set<String> allLocaleCodesAsSet = allLocales.stream()
|
|
||||||
.filter(locale -> !"".equals(locale.getLanguage()) && !"".equals(locale.getDisplayLanguage()))
|
// Filter duplicate locale entries
|
||||||
.map(locale -> new Locale(locale.getLanguage(), "").getLanguage())
|
Set<String> allLocalesAsSet = allLocales.stream().filter(locale -> !locale.getLanguage().isEmpty() && !locale.getDisplayLanguage().isEmpty())
|
||||||
|
.map(locale -> locale.getLanguage())
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
List<String> allLocaleCodes = new ArrayList<>();
|
|
||||||
allLocaleCodes.addAll(allLocaleCodesAsSet);
|
List<String> allLanguageCodes = new ArrayList<>();
|
||||||
allLocaleCodes.sort((o1, o2) -> getDisplayName(o1).compareTo(getDisplayName(o2)));
|
allLanguageCodes.addAll(allLocalesAsSet);
|
||||||
return allLocaleCodes;
|
allLanguageCodes.sort((o1, o2) -> getDisplayName(o1).compareTo(getDisplayName(o2)));
|
||||||
|
return allLanguageCodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDefaultLanguage() {
|
public static String getDefaultLanguage() {
|
||||||
|
|
201
core/src/main/java/io/bitsquare/locale/LocaleUtil.java
Normal file
201
core/src/main/java/io/bitsquare/locale/LocaleUtil.java
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
/*
|
||||||
|
* 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.locale;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class LocaleUtil {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(LocaleUtil.class);
|
||||||
|
|
||||||
|
public static List<Locale> getAllLocales() {
|
||||||
|
|
||||||
|
// derived form Locale.getAvailableLocales() and added some missing locales
|
||||||
|
List<Locale> allLocales = new ArrayList<>();
|
||||||
|
|
||||||
|
allLocales.add(new Locale("bg", "", ""));
|
||||||
|
allLocales.add(new Locale("it", "", ""));
|
||||||
|
allLocales.add(new Locale("ko", "", ""));
|
||||||
|
allLocales.add(new Locale("uk", "", ""));
|
||||||
|
allLocales.add(new Locale("lv", "", ""));
|
||||||
|
allLocales.add(new Locale("pt", "", ""));
|
||||||
|
allLocales.add(new Locale("sk", "", ""));
|
||||||
|
allLocales.add(new Locale("ga", "", ""));
|
||||||
|
allLocales.add(new Locale("et", "", ""));
|
||||||
|
allLocales.add(new Locale("sv", "", ""));
|
||||||
|
allLocales.add(new Locale("cs", "", ""));
|
||||||
|
allLocales.add(new Locale("el", "", ""));
|
||||||
|
allLocales.add(new Locale("hu", "", ""));
|
||||||
|
allLocales.add(new Locale("in", "", ""));
|
||||||
|
allLocales.add(new Locale("be", "", ""));
|
||||||
|
allLocales.add(new Locale("es", "", ""));
|
||||||
|
allLocales.add(new Locale("tr", "", ""));
|
||||||
|
allLocales.add(new Locale("hr", "", ""));
|
||||||
|
allLocales.add(new Locale("lt", "", ""));
|
||||||
|
allLocales.add(new Locale("sq", "", ""));
|
||||||
|
allLocales.add(new Locale("fr", "", ""));
|
||||||
|
allLocales.add(new Locale("ja", "", ""));
|
||||||
|
allLocales.add(new Locale("is", "", ""));
|
||||||
|
allLocales.add(new Locale("de", "", ""));
|
||||||
|
allLocales.add(new Locale("en", "", ""));
|
||||||
|
allLocales.add(new Locale("ca", "", ""));
|
||||||
|
allLocales.add(new Locale("sl", "", ""));
|
||||||
|
allLocales.add(new Locale("fi", "", ""));
|
||||||
|
allLocales.add(new Locale("mk", "", ""));
|
||||||
|
allLocales.add(new Locale("sr", "", ""));
|
||||||
|
allLocales.add(new Locale("th", "", ""));
|
||||||
|
allLocales.add(new Locale("ar", "", ""));
|
||||||
|
allLocales.add(new Locale("ru", "", ""));
|
||||||
|
allLocales.add(new Locale("ms", "", ""));
|
||||||
|
allLocales.add(new Locale("hi", "", ""));
|
||||||
|
allLocales.add(new Locale("nl", "", ""));
|
||||||
|
allLocales.add(new Locale("vi", "", ""));
|
||||||
|
allLocales.add(new Locale("sr", "", ""));
|
||||||
|
allLocales.add(new Locale("mt", "", ""));
|
||||||
|
allLocales.add(new Locale("da", "", ""));
|
||||||
|
allLocales.add(new Locale("ro", "", ""));
|
||||||
|
allLocales.add(new Locale("no", "", ""));
|
||||||
|
allLocales.add(new Locale("pl", "", ""));
|
||||||
|
allLocales.add(new Locale("iw", "", ""));
|
||||||
|
allLocales.add(new Locale("zh", "", ""));
|
||||||
|
allLocales.add(new Locale("ar", "AE", ""));
|
||||||
|
allLocales.add(new Locale("sq", "AL", ""));
|
||||||
|
allLocales.add(new Locale("es", "AR", ""));
|
||||||
|
allLocales.add(new Locale("de", "AT", ""));
|
||||||
|
allLocales.add(new Locale("en", "AU", ""));
|
||||||
|
allLocales.add(new Locale("sr", "BA", ""));
|
||||||
|
allLocales.add(new Locale("sr", "BA", ""));
|
||||||
|
allLocales.add(new Locale("fr", "BE", ""));
|
||||||
|
allLocales.add(new Locale("nl", "BE", ""));
|
||||||
|
allLocales.add(new Locale("bg", "BG", ""));
|
||||||
|
allLocales.add(new Locale("ar", "BH", ""));
|
||||||
|
allLocales.add(new Locale("es", "BO", ""));
|
||||||
|
allLocales.add(new Locale("pt", "BR", ""));
|
||||||
|
allLocales.add(new Locale("be", "BY", ""));
|
||||||
|
allLocales.add(new Locale("fr", "CA", ""));
|
||||||
|
allLocales.add(new Locale("en", "CA", ""));
|
||||||
|
allLocales.add(new Locale("fr", "CH", ""));
|
||||||
|
allLocales.add(new Locale("de", "CH", ""));
|
||||||
|
allLocales.add(new Locale("it", "CH", ""));
|
||||||
|
allLocales.add(new Locale("es", "CL", ""));
|
||||||
|
allLocales.add(new Locale("zh", "CN", ""));
|
||||||
|
allLocales.add(new Locale("es", "CO", ""));
|
||||||
|
allLocales.add(new Locale("es", "CR", ""));
|
||||||
|
allLocales.add(new Locale("sr", "CS", ""));
|
||||||
|
allLocales.add(new Locale("es", "CU", ""));
|
||||||
|
allLocales.add(new Locale("el", "CY", ""));
|
||||||
|
allLocales.add(new Locale("cs", "CZ", ""));
|
||||||
|
allLocales.add(new Locale("de", "DE", ""));
|
||||||
|
allLocales.add(new Locale("da", "DK", ""));
|
||||||
|
allLocales.add(new Locale("es", "DO", ""));
|
||||||
|
allLocales.add(new Locale("ar", "DZ", ""));
|
||||||
|
allLocales.add(new Locale("es", "EC", ""));
|
||||||
|
allLocales.add(new Locale("et", "EE", ""));
|
||||||
|
allLocales.add(new Locale("ar", "EG", ""));
|
||||||
|
allLocales.add(new Locale("ca", "ES", ""));
|
||||||
|
allLocales.add(new Locale("es", "ES", ""));
|
||||||
|
allLocales.add(new Locale("fi", "FI", ""));
|
||||||
|
allLocales.add(new Locale("fr", "FR", ""));
|
||||||
|
allLocales.add(new Locale("en", "GB", ""));
|
||||||
|
allLocales.add(new Locale("el", "GR", ""));
|
||||||
|
allLocales.add(new Locale("de", "GR", ""));
|
||||||
|
allLocales.add(new Locale("es", "GT", ""));
|
||||||
|
allLocales.add(new Locale("zh", "HK", ""));
|
||||||
|
allLocales.add(new Locale("es", "HN", ""));
|
||||||
|
allLocales.add(new Locale("hr", "HR", ""));
|
||||||
|
allLocales.add(new Locale("hu", "HU", ""));
|
||||||
|
allLocales.add(new Locale("in", "ID", ""));
|
||||||
|
allLocales.add(new Locale("ga", "IE", ""));
|
||||||
|
allLocales.add(new Locale("en", "IE", ""));
|
||||||
|
allLocales.add(new Locale("iw", "IL", ""));
|
||||||
|
allLocales.add(new Locale("hi", "IN", ""));
|
||||||
|
allLocales.add(new Locale("en", "IN", ""));
|
||||||
|
allLocales.add(new Locale("ar", "IQ", ""));
|
||||||
|
allLocales.add(new Locale("is", "IS", ""));
|
||||||
|
allLocales.add(new Locale("it", "IT", ""));
|
||||||
|
allLocales.add(new Locale("ar", "JO", ""));
|
||||||
|
allLocales.add(new Locale("ja", "JP", ""));
|
||||||
|
allLocales.add(new Locale("ja", "JP", ""));
|
||||||
|
allLocales.add(new Locale("sw", "KE", ""));
|
||||||
|
allLocales.add(new Locale("km", "KH", ""));
|
||||||
|
allLocales.add(new Locale("ko", "KR", ""));
|
||||||
|
allLocales.add(new Locale("ar", "KW", ""));
|
||||||
|
allLocales.add(new Locale("kk", "KZ", ""));
|
||||||
|
allLocales.add(new Locale("ar", "LB", ""));
|
||||||
|
allLocales.add(new Locale("lt", "LT", ""));
|
||||||
|
allLocales.add(new Locale("fr", "LU", ""));
|
||||||
|
allLocales.add(new Locale("de", "LU", ""));
|
||||||
|
allLocales.add(new Locale("lv", "LV", ""));
|
||||||
|
allLocales.add(new Locale("ar", "LY", ""));
|
||||||
|
allLocales.add(new Locale("ar", "MA", ""));
|
||||||
|
allLocales.add(new Locale("ro", "MD", ""));
|
||||||
|
allLocales.add(new Locale("sr", "ME", ""));
|
||||||
|
allLocales.add(new Locale("sr", "ME", ""));
|
||||||
|
allLocales.add(new Locale("mk", "MK", ""));
|
||||||
|
allLocales.add(new Locale("mt", "MT", ""));
|
||||||
|
allLocales.add(new Locale("en", "MT", ""));
|
||||||
|
allLocales.add(new Locale("es", "MX", ""));
|
||||||
|
allLocales.add(new Locale("ms", "MY", ""));
|
||||||
|
allLocales.add(new Locale("es", "NI", ""));
|
||||||
|
allLocales.add(new Locale("nl", "NL", ""));
|
||||||
|
allLocales.add(new Locale("no", "NO", ""));
|
||||||
|
allLocales.add(new Locale("no", "NO", ""));
|
||||||
|
allLocales.add(new Locale("en", "NZ", ""));
|
||||||
|
allLocales.add(new Locale("ar", "OM", ""));
|
||||||
|
allLocales.add(new Locale("es", "PA", ""));
|
||||||
|
allLocales.add(new Locale("es", "PE", ""));
|
||||||
|
allLocales.add(new Locale("en", "PH", ""));
|
||||||
|
allLocales.add(new Locale("pl", "PL", ""));
|
||||||
|
allLocales.add(new Locale("es", "PR", ""));
|
||||||
|
allLocales.add(new Locale("pt", "PT", ""));
|
||||||
|
allLocales.add(new Locale("es", "PY", ""));
|
||||||
|
allLocales.add(new Locale("ar", "QA", ""));
|
||||||
|
allLocales.add(new Locale("ro", "RO", ""));
|
||||||
|
allLocales.add(new Locale("sr", "RS", ""));
|
||||||
|
allLocales.add(new Locale("sr", "RS", ""));
|
||||||
|
allLocales.add(new Locale("ru", "RU", ""));
|
||||||
|
allLocales.add(new Locale("ar", "SA", ""));
|
||||||
|
allLocales.add(new Locale("ar", "SD", ""));
|
||||||
|
allLocales.add(new Locale("sv", "SE", ""));
|
||||||
|
allLocales.add(new Locale("en", "SG", ""));
|
||||||
|
allLocales.add(new Locale("zh", "SG", ""));
|
||||||
|
allLocales.add(new Locale("sl", "SI", ""));
|
||||||
|
allLocales.add(new Locale("sk", "SK", ""));
|
||||||
|
allLocales.add(new Locale("es", "SV", ""));
|
||||||
|
allLocales.add(new Locale("ar", "SY", ""));
|
||||||
|
allLocales.add(new Locale("th", "TH", ""));
|
||||||
|
allLocales.add(new Locale("th", "TH", ""));
|
||||||
|
allLocales.add(new Locale("ar", "TN", ""));
|
||||||
|
allLocales.add(new Locale("tr", "TR", ""));
|
||||||
|
allLocales.add(new Locale("zh", "TW", ""));
|
||||||
|
allLocales.add(new Locale("uk", "UA", ""));
|
||||||
|
allLocales.add(new Locale("en", "US", ""));
|
||||||
|
allLocales.add(new Locale("es", "US", ""));
|
||||||
|
allLocales.add(new Locale("es", "UY", ""));
|
||||||
|
allLocales.add(new Locale("es", "VE", ""));
|
||||||
|
allLocales.add(new Locale("vi", "VN", ""));
|
||||||
|
allLocales.add(new Locale("ar", "YE", ""));
|
||||||
|
allLocales.add(new Locale("en", "ZA", ""));
|
||||||
|
|
||||||
|
return allLocales;
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,7 +39,7 @@ public final class AliPayAccountContractData extends PaymentAccountContractData
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPaymentDetails() {
|
public String getPaymentDetails() {
|
||||||
return "AliPay - Account nr.: " + accountNr;
|
return "AliPay - Account no.: " + accountNr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -48,12 +48,12 @@ public final class ClearXchangeAccountContractData extends PaymentAccountContrac
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPaymentDetails() {
|
public String getPaymentDetails() {
|
||||||
return "ClearXchange - Holder name: " + holderName + ", email or mobile nr.: " + emailOrMobileNr;
|
return "ClearXchange - Holder name: " + holderName + ", email or mobile no.: " + emailOrMobileNr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPaymentDetailsForTradePopup() {
|
public String getPaymentDetailsForTradePopup() {
|
||||||
return "Holder name: " + holderName + "\n" +
|
return "Holder name: " + holderName + "\n" +
|
||||||
"Email or mobile nr.: " + emailOrMobileNr;
|
"Email or mobile no.: " + emailOrMobileNr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public final class OKPayAccountContractData extends PaymentAccountContractData {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPaymentDetails() {
|
public String getPaymentDetails() {
|
||||||
return "OKPay - Account nr.: " + accountNr;
|
return "OKPay - Account no.: " + accountNr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -70,19 +70,19 @@ public final class PaymentMethod implements Persistable, Comparable {
|
||||||
public static PaymentMethod BLOCK_CHAINS;
|
public static PaymentMethod BLOCK_CHAINS;
|
||||||
|
|
||||||
public static final List<PaymentMethod> ALL_VALUES = new ArrayList<>(Arrays.asList(
|
public static final List<PaymentMethod> ALL_VALUES = new ArrayList<>(Arrays.asList(
|
||||||
OK_PAY = new PaymentMethod(OK_PAY_ID, 0, DAY, Coin.parseCoin("1.5")), // tx instant so min. wait time
|
OK_PAY = new PaymentMethod(OK_PAY_ID, 0, DAY, Coin.parseCoin("2")), // tx instant so min. wait time
|
||||||
SEPA = new PaymentMethod(SEPA_ID, 0, 8 * DAY, Coin.parseCoin("1")), // sepa takes 1-3 business days. We use 8 days to include safety for holidays
|
SEPA = new PaymentMethod(SEPA_ID, 0, 8 * DAY, Coin.parseCoin("1")), // sepa takes 1-3 business days. We use 8 days to include safety for holidays
|
||||||
FASTER_PAYMENTS = new PaymentMethod(FASTER_PAYMENTS_ID, 0, DAY, Coin.parseCoin("1")),
|
FASTER_PAYMENTS = new PaymentMethod(FASTER_PAYMENTS_ID, 0, DAY, Coin.parseCoin("1")),
|
||||||
CLEAR_X_CHANGE = new PaymentMethod(CLEAR_X_CHANGE_ID, 0, 8 * DAY, Coin.parseCoin("0.5")),
|
CLEAR_X_CHANGE = new PaymentMethod(CLEAR_X_CHANGE_ID, 0, 8 * DAY, Coin.parseCoin("1")),
|
||||||
SWISH = new PaymentMethod(SWISH_ID, 0, DAY, Coin.parseCoin("1.5")),
|
SWISH = new PaymentMethod(SWISH_ID, 0, DAY, Coin.parseCoin("2")),
|
||||||
NATIONAL_BANK = new PaymentMethod(NATIONAL_BANK_ID, 0, 4 * DAY, Coin.parseCoin("1")),
|
NATIONAL_BANK = new PaymentMethod(NATIONAL_BANK_ID, 0, 4 * DAY, Coin.parseCoin("1")),
|
||||||
SAME_BANK = new PaymentMethod(SAME_BANK_ID, 0, 2 * DAY, Coin.parseCoin("1")),
|
SAME_BANK = new PaymentMethod(SAME_BANK_ID, 0, 2 * DAY, Coin.parseCoin("1")),
|
||||||
SPECIFIC_BANKS = new PaymentMethod(SPECIFIC_BANKS_ID, 0, 4 * DAY, Coin.parseCoin("1")),
|
SPECIFIC_BANKS = new PaymentMethod(SPECIFIC_BANKS_ID, 0, 4 * DAY, Coin.parseCoin("1")),
|
||||||
PERFECT_MONEY = new PaymentMethod(PERFECT_MONEY_ID, 0, DAY, Coin.parseCoin("1")),
|
PERFECT_MONEY = new PaymentMethod(PERFECT_MONEY_ID, 0, DAY, Coin.parseCoin("1")),
|
||||||
ALI_PAY = new PaymentMethod(ALI_PAY_ID, 0, DAY, Coin.parseCoin("1.5")),
|
ALI_PAY = new PaymentMethod(ALI_PAY_ID, 0, DAY, Coin.parseCoin("2")),
|
||||||
CASH_DEPOSIT = new PaymentMethod(CASH_DEPOSIT_ID, 0, 6 * DAY, Coin.parseCoin("0.5")),
|
CASH_DEPOSIT = new PaymentMethod(CASH_DEPOSIT_ID, 0, 6 * DAY, Coin.parseCoin("1")),
|
||||||
US_POSTAL_MONEY_ORDER = new PaymentMethod(US_POSTAL_MONEY_ORDER_ID, 0, 6 * DAY, Coin.parseCoin("0.5")),
|
US_POSTAL_MONEY_ORDER = new PaymentMethod(US_POSTAL_MONEY_ORDER_ID, 0, 6 * DAY, Coin.parseCoin("1")),
|
||||||
BLOCK_CHAINS = new PaymentMethod(BLOCK_CHAINS_ID, 0, DAY, Coin.parseCoin("2"))
|
BLOCK_CHAINS = new PaymentMethod(BLOCK_CHAINS_ID, 0, DAY, Coin.parseCoin("3"))
|
||||||
));
|
));
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
|
|
|
@ -39,7 +39,7 @@ public final class PerfectMoneyAccountContractData extends PaymentAccountContrac
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPaymentDetails() {
|
public String getPaymentDetails() {
|
||||||
return "PerfectMoney - Account nr.: " + accountNr;
|
return "PerfectMoney - Account no.: " + accountNr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -48,12 +48,12 @@ public final class SwishAccountContractData extends PaymentAccountContractData {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPaymentDetails() {
|
public String getPaymentDetails() {
|
||||||
return "Swish - Holder name: " + holderName + ", mobile nr.: " + mobileNr;
|
return "Swish - Holder name: " + holderName + ", mobile no.: " + mobileNr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPaymentDetailsForTradePopup() {
|
public String getPaymentDetailsForTradePopup() {
|
||||||
return "Holder name: " + holderName + "\n" +
|
return "Holder name: " + holderName + "\n" +
|
||||||
"Mobile nr.: " + mobileNr;
|
"Mobile no.: " + mobileNr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,7 @@ public abstract class Trade implements Tradable, Model {
|
||||||
@Nullable
|
@Nullable
|
||||||
transient private Storage<? extends TradableList> storage;
|
transient private Storage<? extends TradableList> storage;
|
||||||
transient protected TradeProtocol tradeProtocol;
|
transient protected TradeProtocol tradeProtocol;
|
||||||
private transient Date maxTradePeriodDate, halfTradePeriodDate;
|
transient private Date maxTradePeriodDate, halfTradePeriodDate;
|
||||||
|
|
||||||
// Immutable
|
// Immutable
|
||||||
private final Offer offer;
|
private final Offer offer;
|
||||||
|
|
|
@ -239,7 +239,7 @@ public class TradeManager {
|
||||||
trade.getDate(),
|
trade.getDate(),
|
||||||
(trade.getDepositTx() != null ? trade.getDepositTx().getHashAsString() : ""),
|
(trade.getDepositTx() != null ? trade.getDepositTx().getHashAsString() : ""),
|
||||||
keyRing.getPubKeyRing());
|
keyRing.getPubKeyRing());
|
||||||
tradeStatisticsManager.add(tradeStatistics);
|
tradeStatisticsManager.add(tradeStatistics, true);
|
||||||
|
|
||||||
// We only republish trades from last 10 days
|
// We only republish trades from last 10 days
|
||||||
// TODO check if needed at all. Don't want to remove it atm to not risk anything.
|
// TODO check if needed at all. Don't want to remove it atm to not risk anything.
|
||||||
|
|
|
@ -422,7 +422,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||||
|
|
||||||
double factor = (double) takersTradePrice / (double) offerPriceAsFiat.value;
|
double factor = (double) takersTradePrice / (double) offerPriceAsFiat.value;
|
||||||
// We allow max. 2 % difference between own offer price calculation and takers calculation.
|
// We allow max. 2 % difference between own offer price calculation and takers calculation.
|
||||||
// Market price might be different at offerers and takers side so we need a bit of tolerance.
|
// Market price might be different at offerer's and takers side so we need a bit of tolerance.
|
||||||
// The tolerance will get smaller once we have multiple price feeds avoiding fast price fluctuations
|
// The tolerance will get smaller once we have multiple price feeds avoiding fast price fluctuations
|
||||||
// from one provider.
|
// from one provider.
|
||||||
if (Math.abs(1 - factor) > 0.02) {
|
if (Math.abs(1 - factor) > 0.02) {
|
||||||
|
|
|
@ -458,7 +458,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
() -> {
|
() -> {
|
||||||
if (!stopped) {
|
if (!stopped) {
|
||||||
log.debug("Successful added offer to P2P network");
|
log.debug("Successful added offer to P2P network");
|
||||||
// Refresh means we send only the dat needed to refresh the TTL (hash, signature and sequence nr.)
|
// Refresh means we send only the dat needed to refresh the TTL (hash, signature and sequence no.)
|
||||||
if (periodicRefreshOffersTimer == null)
|
if (periodicRefreshOffersTimer == null)
|
||||||
startPeriodicRefreshOffersTimer();
|
startPeriodicRefreshOffersTimer();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class ProcessPayDepositRequest extends TradeTask {
|
||||||
PaymentAccountContractData paymentAccountContractData = checkNotNull(payDepositRequest.takerPaymentAccountContractData);
|
PaymentAccountContractData paymentAccountContractData = checkNotNull(payDepositRequest.takerPaymentAccountContractData);
|
||||||
final PaymentAccountFilter[] appliedPaymentAccountFilter = new PaymentAccountFilter[1];
|
final PaymentAccountFilter[] appliedPaymentAccountFilter = new PaymentAccountFilter[1];
|
||||||
if (processModel.isPeersPaymentAccountDataAreBanned(paymentAccountContractData, appliedPaymentAccountFilter)) {
|
if (processModel.isPeersPaymentAccountDataAreBanned(paymentAccountContractData, appliedPaymentAccountFilter)) {
|
||||||
failed("Other trader is banned by his payment account data.\n" +
|
failed("Other trader is banned by his trading account data.\n" +
|
||||||
"paymentAccountContractData=" + paymentAccountContractData.getPaymentDetails() + "\n" +
|
"paymentAccountContractData=" + paymentAccountContractData.getPaymentDetails() + "\n" +
|
||||||
"banFilter=" + appliedPaymentAccountFilter[0].toString());
|
"banFilter=" + appliedPaymentAccountFilter[0].toString());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class ProcessPublishDepositTxRequest extends TradeTask {
|
||||||
PaymentAccountContractData paymentAccountContractData = checkNotNull(publishDepositTxRequest.offererPaymentAccountContractData);
|
PaymentAccountContractData paymentAccountContractData = checkNotNull(publishDepositTxRequest.offererPaymentAccountContractData);
|
||||||
final PaymentAccountFilter[] appliedPaymentAccountFilter = new PaymentAccountFilter[1];
|
final PaymentAccountFilter[] appliedPaymentAccountFilter = new PaymentAccountFilter[1];
|
||||||
if (processModel.isPeersPaymentAccountDataAreBanned(paymentAccountContractData, appliedPaymentAccountFilter)) {
|
if (processModel.isPeersPaymentAccountDataAreBanned(paymentAccountContractData, appliedPaymentAccountFilter)) {
|
||||||
failed("Other trader is banned by his payment account data.\n" +
|
failed("Other trader is banned by his trading account data.\n" +
|
||||||
"paymentAccountContractData=" + paymentAccountContractData.getPaymentDetails() + "\n" +
|
"paymentAccountContractData=" + paymentAccountContractData.getPaymentDetails() + "\n" +
|
||||||
"banFilter=" + appliedPaymentAccountFilter[0].toString());
|
"banFilter=" + appliedPaymentAccountFilter[0].toString());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -72,14 +72,14 @@ public class TradeStatisticsManager {
|
||||||
|
|
||||||
HashSet<TradeStatistics> persisted = statisticsStorage.initAndGetPersistedWithFileName("TradeStatistics");
|
HashSet<TradeStatistics> persisted = statisticsStorage.initAndGetPersistedWithFileName("TradeStatistics");
|
||||||
if (persisted != null)
|
if (persisted != null)
|
||||||
persisted.stream().forEach(this::add);
|
persisted.stream().forEach(e -> add(e, false));
|
||||||
|
|
||||||
p2PService.addHashSetChangedListener(new HashMapChangedListener() {
|
p2PService.addHashSetChangedListener(new HashMapChangedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onAdded(ProtectedStorageEntry data) {
|
public void onAdded(ProtectedStorageEntry data) {
|
||||||
final StoragePayload storagePayload = data.getStoragePayload();
|
final StoragePayload storagePayload = data.getStoragePayload();
|
||||||
if (storagePayload instanceof TradeStatistics)
|
if (storagePayload instanceof TradeStatistics)
|
||||||
add((TradeStatistics) storagePayload);
|
add((TradeStatistics) storagePayload, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -92,17 +92,19 @@ public class TradeStatisticsManager {
|
||||||
p2PService.getP2PDataStorage().getMap().values().forEach(e -> {
|
p2PService.getP2PDataStorage().getMap().values().forEach(e -> {
|
||||||
final StoragePayload storagePayload = e.getStoragePayload();
|
final StoragePayload storagePayload = e.getStoragePayload();
|
||||||
if (storagePayload instanceof TradeStatistics)
|
if (storagePayload instanceof TradeStatistics)
|
||||||
add((TradeStatistics) storagePayload);
|
add((TradeStatistics) storagePayload, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(TradeStatistics tradeStatistics) {
|
public void add(TradeStatistics tradeStatistics, boolean storeLocally) {
|
||||||
if (!tradeStatisticsSet.contains(tradeStatistics)) {
|
if (!tradeStatisticsSet.contains(tradeStatistics)) {
|
||||||
boolean itemAlreadyAdded = tradeStatisticsSet.stream().filter(e -> (e.getOfferId().equals(tradeStatistics.getOfferId()))).findAny().isPresent();
|
boolean itemAlreadyAdded = tradeStatisticsSet.stream().filter(e -> (e.getOfferId().equals(tradeStatistics.getOfferId()))).findAny().isPresent();
|
||||||
if (!itemAlreadyAdded) {
|
if (!itemAlreadyAdded) {
|
||||||
tradeStatisticsSet.add(tradeStatistics);
|
tradeStatisticsSet.add(tradeStatistics);
|
||||||
observableTradeStatisticsSet.add(tradeStatistics);
|
observableTradeStatisticsSet.add(tradeStatistics);
|
||||||
statisticsStorage.queueUpForSave(new HashSet<>(tradeStatisticsSet), 2000);
|
|
||||||
|
if (storeLocally)
|
||||||
|
statisticsStorage.queueUpForSave(new HashSet<>(tradeStatisticsSet), 2000);
|
||||||
|
|
||||||
dump();
|
dump();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -129,10 +129,10 @@ public final class Preferences implements Persistable {
|
||||||
|
|
||||||
private String buyScreenCurrencyCode = CurrencyUtil.getDefaultTradeCurrency().getCode();
|
private String buyScreenCurrencyCode = CurrencyUtil.getDefaultTradeCurrency().getCode();
|
||||||
private String sellScreenCurrencyCode = CurrencyUtil.getDefaultTradeCurrency().getCode();
|
private String sellScreenCurrencyCode = CurrencyUtil.getDefaultTradeCurrency().getCode();
|
||||||
private int tradeStatisticsTickUnitIndex = 0;
|
private int tradeStatisticsTickUnitIndex = 3;
|
||||||
|
|
||||||
private boolean useStickyMarketPrice = false;
|
private boolean useStickyMarketPrice = false;
|
||||||
private boolean sortMarketCurrenciesNumerically = false;
|
private boolean sortMarketCurrenciesNumerically = true;
|
||||||
private boolean usePercentageBasedPrice = false;
|
private boolean usePercentageBasedPrice = false;
|
||||||
private Map<String, String> peerTagMap = new HashMap<>();
|
private Map<String, String> peerTagMap = new HashMap<>();
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
160
doc/build.md
160
doc/build.md
|
@ -21,43 +21,63 @@ If `java` is not found, or your version is anything less than `1.8.0_66`, then f
|
||||||
|
|
||||||
#### 1.1 Debian based systems (Ubuntu)
|
#### 1.1 Debian based systems (Ubuntu)
|
||||||
|
|
||||||
To install OpenJDK use:
|
You can use either OpenJDK or Oracle JDK.
|
||||||
|
|
||||||
|
**To install OpenJDK use:**
|
||||||
|
|
||||||
$ sudo apt-get install openjdk-8-jdk maven libopenjfx-java
|
$ sudo apt-get install openjdk-8-jdk maven libopenjfx-java
|
||||||
|
|
||||||
To install the Oracle JDK use:
|
Unfortunately, Ubuntu 14.04 & Linux Mint 17.3 are missing OpenJdk 8 and OpenJFX, so this might be useful:
|
||||||
|
|
||||||
|
If `openjdk-8-jdk` is not found you can add this ppa, update, then try again:
|
||||||
|
|
||||||
|
$ sudo apt-add-repository ppa:openjdk-r/ppa && sudo apt-get install openjdk-8-jdk
|
||||||
|
|
||||||
|
If `libopenjfx-java` is not found you can build & install it yourself:
|
||||||
|
|
||||||
|
* [How to install OpenJFX on Ubuntu 14.04 or Linux Mint 17.3](http://askubuntu.com/questions/833193/how-do-i-install-openjfx-on-ubuntu-14-04-linux-mint-17)
|
||||||
|
|
||||||
|
**To install the Oracle JDK use:**
|
||||||
|
|
||||||
$ sudo add-apt-repository ppa:webupd8team/java
|
$ sudo add-apt-repository ppa:webupd8team/java
|
||||||
$ sudo apt-get update
|
$ sudo apt-get update
|
||||||
$ sudo apt-get -y install oracle-java8-installer
|
$ sudo apt-get -y install oracle-java8-installer
|
||||||
|
|
||||||
Check if $JAVA_HOME is set
|
|
||||||
|
**Check if $JAVA_HOME is set:**
|
||||||
|
|
||||||
$ echo $JAVA_HOME
|
$ echo $JAVA_HOME
|
||||||
|
|
||||||
If $JAVA_HOME is not present, add it to the .bashrc file
|
|
||||||
|
|
||||||
$ touch .bashrc
|
If `$JAVA_HOME` is not present, open your `.bashrc` file:
|
||||||
$ gedit .bashrc
|
|
||||||
$ export JAVA_HOME=/usr/lib/jvm/java-8-oracle
|
$ touch ~/.bashrc
|
||||||
$ echo $JAVA_HOME
|
$ gedit ~/.bashrc
|
||||||
|
|
||||||
|
For OpenJDK add: `export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64`
|
||||||
|
For Oracle JDK add: `export JAVA_HOME=/usr/lib/jvm/java-8-oracle`
|
||||||
|
Save and close the file.
|
||||||
|
|
||||||
|
Reload the file in your shell:
|
||||||
|
|
||||||
|
$ . ~/.bashrc
|
||||||
|
$ echo $JAVA_HOME
|
||||||
|
|
||||||
#### 1.2 Other systems
|
#### 1.2 Other systems
|
||||||
|
|
||||||
[Download and install the latest JDK]( http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) for your platform.
|
[Download and install the latest Oracle JDK]( http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) for your platform.
|
||||||
|
|
||||||
Build bitcoinj
|
Build bitcoinj
|
||||||
-----------------
|
-----------------
|
||||||
### 2. Install bitcoinj fork
|
### 2. Install bitcoinj fork
|
||||||
> _**NOTE:**
|
> _**NOTE:**
|
||||||
Bitcoinj versions later than 0.13.1 has removed support for Java serialisation.
|
Bitcoinj versions later than 0.13.1 has removed support for Java serialisation.
|
||||||
In version 0.13.1 is also missing support for Java serialisation in MainNetParams (HttpDiscovery.Details).
|
Version 0.13.1 is also missing support for Java serialisation in MainNetParams (HttpDiscovery.Details).
|
||||||
We removed usage of Cartographer/HttpDiscovery and fixed privacy issues with Bloom Filters at our [fork version 0.13.1.5](https://github.com/bitsquare/bitcoinj/tree/FixBloomFilters).
|
We removed usage of Cartographer/HttpDiscovery and fixed privacy issues with Bloom Filters in our [fork of version 0.13.1.5](https://github.com/bitsquare/bitcoinj/tree/FixBloomFilters).
|
||||||
Beside the Java serialisation issues there are [privacy concerns](http://bitcoin-development.narkive.com/hczWIAby/bitcoin-development-cartographer#post3) regarding Cartographer.
|
Beside the Java serialisation issues there are [privacy concerns](http://bitcoin-development.narkive.com/hczWIAby/bitcoin-development-cartographer#post3) regarding Cartographer.
|
||||||
Here is a Github issue with background and open tasks regarding [Bloom Filters](https://github.com/bitsquare/bitsquare/issues/414)._
|
Here is a Github issue with background and open tasks regarding [Bloom Filters](https://github.com/bitsquare/bitsquare/issues/414)._
|
||||||
|
|
||||||
$ git clone -b FixBloomFilters https://github.com/bitsquare/bitcoinj.git
|
$ git clone -b FixBloomFilters https://github.com/bitsquare/bitcoinj.git
|
||||||
$ cd bitcoinj
|
$ cd bitcoinj
|
||||||
$ mvn clean install -DskipTests -Dmaven.javadoc.skip=true
|
$ mvn clean install -DskipTests -Dmaven.javadoc.skip=true
|
||||||
|
|
||||||
Prepare Bitsquare build
|
Prepare Bitsquare build
|
||||||
|
@ -65,44 +85,44 @@ Prepare Bitsquare build
|
||||||
|
|
||||||
### 3. Get Bitsquare source code and build a preliminary Bitsquare version
|
### 3. Get Bitsquare source code and build a preliminary Bitsquare version
|
||||||
|
|
||||||
You need to get the Bitsquare dependencies first as we need to copy the BountyCastle jar to the JRE directory as well as the jdkfix jar.
|
You need to get the Bitsquare dependencies first as we need to copy the BouncyCastle jar to the JRE directory as well as the jdkfix jar.
|
||||||
|
|
||||||
$ git clone https://github.com/bitsquare/bitsquare.git
|
$ git clone https://github.com/bitsquare/bitsquare.git
|
||||||
$ cd bitsquare
|
$ cd bitsquare
|
||||||
$ mvn clean package -DskipTests -Dmaven.javadoc.skip=true
|
$ mvn clean package -DskipTests -Dmaven.javadoc.skip=true
|
||||||
|
|
||||||
### 4. Copy the jdkfix jar file
|
### 4. Copy the jdkfix jar file
|
||||||
|
|
||||||
Copy the jdkfix-0.4.9.6.jar from the Bitsquare jdkfix/target directory to $JAVA_HOME/jre/lib/ext/.
|
Copy the jdkfix-0.4.9.6.jar from the Bitsquare jdkfix/target directory to $JAVA_HOME/jre/lib/ext/.
|
||||||
jdkfix-0.4.9.6.jar includes a bugfix of the SortedList class which will be released with the next JDK version.
|
jdkfix-0.4.9.6.jar includes a [bugfix of the SortedList class](https://github.com/jonathancross/bitsquare/blob/master/jdkfix/src/main/java/javafx/collections/transformation/SortedList.java#L2) which will be released with the next JDK version.
|
||||||
We need to load that class before the default java class. This step will be removed once the bugfix is in the official JDK.
|
We need to load that class before the default java class. This step will be removed once the bugfix is in the official JDK.
|
||||||
|
|
||||||
$ sudo cp bitsquare/jdkfix/target/jdkfix-0.4.9.6.jar $JAVA_HOME/jre/lib/ext/jdkfix-0.4.9.6.jar
|
|
||||||
|
|
||||||
### 5. Copy the BountyCastle provider jar file
|
$ sudo cp jdkfix/target/jdkfix-0.4.9.6.jar $JAVA_HOME/jre/lib/ext/
|
||||||
|
|
||||||
Copy the BountyCastle provider jar file from the local maven repository to the jre/lib/ext directory.
|
### 5. Copy the BouncyCastle provider jar file
|
||||||
|
|
||||||
|
Copy the BouncyCastle provider jar file from the local maven repository to the jre/lib/ext directory.
|
||||||
This prevents a "JCE cannot authenticate the provider BC" exception when starting the Bitsquare client.
|
This prevents a "JCE cannot authenticate the provider BC" exception when starting the Bitsquare client.
|
||||||
|
|
||||||
$ sudo cp ~/.m2/repository/org/bouncycastle/bcprov-jdk15on/1.53/bcprov-jdk15on-1.53.jar $JAVA_HOME/jre/lib/ext/bcprov-jdk15on-1.53.jar
|
$ sudo cp ~/.m2/repository/org/bouncycastle/bcprov-jdk15on/1.53/bcprov-jdk15on-1.53.jar $JAVA_HOME/jre/lib/ext/
|
||||||
|
|
||||||
### 6. Edit the java.security file and add BouncyCastleProvider
|
### 6. Edit the java.security file and add BouncyCastleProvider
|
||||||
|
|
||||||
Add org.bouncycastle.jce.provider.BouncyCastleProvider as last entry at: List of providers and their preference orders
|
Add org.bouncycastle.jce.provider.BouncyCastleProvider as last entry at: List of providers and their preference orders
|
||||||
E.g.:
|
E.g.:
|
||||||
security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
|
security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||||
|
|
||||||
$ sudo gedit $JAVA_HOME/jre/lib/security/java.security
|
$ sudo gedit $JAVA_HOME/jre/lib/security/java.security
|
||||||
... edit and save
|
... edit and save
|
||||||
|
|
||||||
### 7. Enable unlimited Strength for cryptographic keys (if Oracle JDK is used)
|
### 7. Enable unlimited Strength for cryptographic keys (if Oracle JDK is used)
|
||||||
|
|
||||||
If you are using Oracle JDK you need to follow the following step. If you use OpenJDK + OpenJFX you can skip that step.
|
If you are using Oracle JDK you need to follow the following step. If you use OpenJDK + OpenJFX you can skip that step.
|
||||||
Bitsquare uses 256 bit length keys which are still not permitted by default.
|
Bitsquare uses 256 bit length keys which are still not permitted by default.
|
||||||
Get around that ridiculous fact by adding the missing [jars from Oracle](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html).
|
Get around that ridiculous fact by adding the missing [jars from Oracle](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html).
|
||||||
Please follow the steps described in the Readme file at the downloaded package.
|
Please follow the steps described in the Readme file in the downloaded package.
|
||||||
You will get an error when building Bitsquare package if you don't have these.
|
You will get an error when building Bitsquare package if you don't have these.
|
||||||
|
|
||||||
$ wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip
|
$ wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip
|
||||||
$ unzip jce_policy-8.zip
|
$ unzip jce_policy-8.zip
|
||||||
$ sudo cp UnlimitedJCEPolicyJDK8/US_export_policy.jar $JAVA_HOME/jre/lib/security/US_export_policy.jar
|
$ sudo cp UnlimitedJCEPolicyJDK8/US_export_policy.jar $JAVA_HOME/jre/lib/security/US_export_policy.jar
|
||||||
|
@ -117,11 +137,11 @@ Build Bitsquare
|
||||||
|
|
||||||
### 8. Build final Bitsquare jar
|
### 8. Build final Bitsquare jar
|
||||||
|
|
||||||
Now we have all prepared to build the correct Bitsquare jar.
|
Now we have all prepared to build the correct Bitsquare jar.
|
||||||
|
|
||||||
$ mvn clean package -DskipTests -Dmaven.javadoc.skip=true
|
$ mvn clean package -DskipTests -Dmaven.javadoc.skip=true
|
||||||
|
|
||||||
When the build completes, you will find an executable jar: `gui/target/shaded.jar`.
|
When the build completes, you will find an executable jar: `gui/target/shaded.jar`.
|
||||||
To run it use:
|
To run it use:
|
||||||
|
|
||||||
$ java -jar gui/target/shaded.jar
|
$ java -jar gui/target/shaded.jar
|
||||||
|
@ -129,52 +149,52 @@ To run it use:
|
||||||
Build binaries
|
Build binaries
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
If you want to build the binaryies check out the build scripts under the package directory.
|
If you want to build the binaries check out the build scripts under the package directory.
|
||||||
|
|
||||||
Development mode
|
Development mode
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Please check out our wiki for more information about [testing](https://github.com/bitsquare/bitsquare/wiki/Testing-Bitsquare-with-Mainnet)
|
Please check out our wiki for more information about [testing](https://github.com/bitsquare/bitsquare/wiki/Testing-Bitsquare-with-Mainnet)
|
||||||
and how to use [regtest](https://github.com/bitsquare/bitsquare/wiki/How-to-use-Bitsquare-with-regtest-%28advanced%29)
|
and how to use [regtest](https://github.com/bitsquare/bitsquare/wiki/How-to-use-Bitsquare-with-regtest-%28advanced%29)
|
||||||
|
|
||||||
Here are example program arguments for using regtest with localhost environment (not using Tor):
|
Here are example program arguments for using regtest with localhost environment (not using Tor):
|
||||||
|
|
||||||
$ java -jar seednode/target/SeedNode.jar --bitcoinNetwork=REGTEST --useLocalhost=true --myAddress=localhost:2002 --nodePort=2002 --appName=Bitsquare_seed_node_localhost_2002
|
$ java -jar seednode/target/SeedNode.jar --bitcoinNetwork=REGTEST --useLocalhost=true --myAddress=localhost:2002 --nodePort=2002 --appName=Bitsquare_seed_node_localhost_2002
|
||||||
|
|
||||||
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --useLocalhost=true --myAddress=localhost:2222 --nodePort=2222 --appName=Bitsquare-Local-Regtest-Arbitrator
|
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --useLocalhost=true --myAddress=localhost:2222 --nodePort=2222 --appName=Bitsquare-Local-Regtest-Arbitrator
|
||||||
|
|
||||||
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --useLocalhost=true --myAddress=localhost:3333 --nodePort=3333 --appName=Bitsquare-Local-Regtest-Alice
|
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --useLocalhost=true --myAddress=localhost:3333 --nodePort=3333 --appName=Bitsquare-Local-Regtest-Alice
|
||||||
|
|
||||||
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --useLocalhost=true --myAddress=localhost:4444 --nodePort=4444 --appName=Bitsquare-Local-Regtest-Bob
|
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --useLocalhost=true --myAddress=localhost:4444 --nodePort=4444 --appName=Bitsquare-Local-Regtest-Bob
|
||||||
|
|
||||||
|
|
||||||
Running local seed node with Tor and RegTest
|
Running local seed node with Tor and RegTest
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
If you want to run locally a seed node via Tor you need to add your seed node's hidden service address to the SeedNodesRepository.java class.
|
If you want to run locally a seed node via Tor you need to add your seed node's hidden service address to the SeedNodesRepository.java class.
|
||||||
You can find the hidden service address after you started once a seed node. Start it with a placeholder address like:
|
You can find the hidden service address after you started once a seed node. Start it with a placeholder address like:
|
||||||
|
|
||||||
$ java -jar seednode/target/SeedNode.jar --bitcoinNetwork=REGTEST --nodePort=8002 --myAddress=xxxxxxxx.onion:8002 --appName=Bitsquare_seed_node_xxxxxxxx.onion_8000
|
$ java -jar seednode/target/SeedNode.jar --bitcoinNetwork=REGTEST --nodePort=8002 --myAddress=xxxxxxxx.onion:8002 --appName=Bitsquare_seed_node_xxxxxxxx.onion_8000
|
||||||
|
|
||||||
Once the hidden service is published (check console output) quit the seed node and copy the hidden service address from the console output.
|
Once the hidden service is published (check console output) quit the seed node and copy the hidden service address from the console output.
|
||||||
Alternatively you can navigate to the application directory and open Bitsquare_seed_node_xxxxxxx.onion_8002/tor/hiddenservice/hostname.
|
Alternatively you can navigate to the application directory and open Bitsquare_seed_node_xxxxxxx.onion_8002/tor/hiddenservice/hostname.
|
||||||
use that hidden service address also to rename the xxxxxxx placeholder of your Bitsquare_seed_node_xxxxxxx.onion_8002 directory.
|
use that hidden service address also to rename the xxxxxxx placeholder of your Bitsquare_seed_node_xxxxxxx.onion_8002 directory.
|
||||||
Start again the SeedNode.jar now with the correct hidden service address.
|
Start again the SeedNode.jar now with the correct hidden service address.
|
||||||
Instructions are also at the SeedNodesRepository class.
|
Instructions are also at the SeedNodesRepository class.
|
||||||
|
|
||||||
Here are example program arguments for using regtest and using the Tor network (example onion address is ewdkppp3vicnbgqt):
|
Here are example program arguments for using regtest and using the Tor network (example onion address is ewdkppp3vicnbgqt):
|
||||||
|
|
||||||
$ java -jar seednode/target/SeedNode.jar ewdkppp3vicnbgqt.onion:8002 2 50
|
$ java -jar seednode/target/SeedNode.jar ewdkppp3vicnbgqt.onion:8002 2 50
|
||||||
|
|
||||||
$ java -jar seednode/target/SeedNode.jar --bitcoinNetwork=REGTEST --nodePort=8002 --myAddress=ewdkppp3vicnbgqt.onion:8002 --appName=Bitsquare_seed_node_ewdkppp3vicnbgqt.oinion_8002
|
$ java -jar seednode/target/SeedNode.jar --bitcoinNetwork=REGTEST --nodePort=8002 --myAddress=ewdkppp3vicnbgqt.onion:8002 --appName=Bitsquare_seed_node_ewdkppp3vicnbgqt.oinion_8002
|
||||||
|
|
||||||
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --myAddress=localhost:2222 --nodePort=2222 --appName=Bitsquare-Local-Regtest-Arbitrator
|
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --myAddress=localhost:2222 --nodePort=2222 --appName=Bitsquare-Local-Regtest-Arbitrator
|
||||||
|
|
||||||
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --myAddress=localhost:3333 --nodePort=3333 --appName=Bitsquare-Local-Regtest-Alice
|
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --myAddress=localhost:3333 --nodePort=3333 --appName=Bitsquare-Local-Regtest-Alice
|
||||||
|
|
||||||
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --myAddress=localhost:4444 --nodePort=4444 --appName=Bitsquare-Local-Regtest-Bob
|
$ java -jar gui/target/shaded.jar --bitcoinNetwork=REGTEST --myAddress=localhost:4444 --nodePort=4444 --appName=Bitsquare-Local-Regtest-Bob
|
||||||
|
|
||||||
|
|
||||||
Problems?
|
Problems?
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,7 @@ public class BitsquareApp extends Application {
|
||||||
mainView.setPersistedFilesCorrupted(corruptedDatabaseFiles);
|
mainView.setPersistedFilesCorrupted(corruptedDatabaseFiles);
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
scene = new Scene(mainView.getRoot(), 1200, 740);
|
scene = new Scene(mainView.getRoot(), 1200, 700); //740
|
||||||
|
|
||||||
Font.loadFont(getClass().getResource("/fonts/Verdana.ttf").toExternalForm(), 13);
|
Font.loadFont(getClass().getResource("/fonts/Verdana.ttf").toExternalForm(), 13);
|
||||||
Font.loadFont(getClass().getResource("/fonts/VerdanaBold.ttf").toExternalForm(), 13);
|
Font.loadFont(getClass().getResource("/fonts/VerdanaBold.ttf").toExternalForm(), 13);
|
||||||
|
@ -212,11 +212,11 @@ public class BitsquareApp extends Application {
|
||||||
// configure the primary stage
|
// configure the primary stage
|
||||||
primaryStage.setTitle(env.getRequiredProperty(APP_NAME_KEY));
|
primaryStage.setTitle(env.getRequiredProperty(APP_NAME_KEY));
|
||||||
primaryStage.setScene(scene);
|
primaryStage.setScene(scene);
|
||||||
primaryStage.setMinWidth(1190);
|
primaryStage.setMinWidth(1000); // 1190
|
||||||
primaryStage.setMinHeight(620);
|
primaryStage.setMinHeight(620);
|
||||||
|
|
||||||
// on windows the title icon is also used as task bar icon in a larger size
|
// on windows the title icon is also used as task bar icon in a larger size
|
||||||
// on Linux no title icon is supported but also a large task bar icon is derived form that title icon
|
// on Linux no title icon is supported but also a large task bar icon is derived from that title icon
|
||||||
String iconPath;
|
String iconPath;
|
||||||
if (Utilities.isOSX())
|
if (Utilities.isOSX())
|
||||||
iconPath = ImageUtil.isRetina() ? "/images/window_icon@2x.png" : "/images/window_icon.png";
|
iconPath = ImageUtil.isRetina() ? "/images/window_icon@2x.png" : "/images/window_icon.png";
|
||||||
|
@ -235,8 +235,8 @@ public class BitsquareApp extends Application {
|
||||||
String osArchitecture = Utilities.getOSArchitecture();
|
String osArchitecture = Utilities.getOSArchitecture();
|
||||||
// We don't force a shutdown as the osArchitecture might in strange cases return a wrong value.
|
// We don't force a shutdown as the osArchitecture might in strange cases return a wrong value.
|
||||||
// Needs at least more testing on different machines...
|
// Needs at least more testing on different machines...
|
||||||
new Popup<>().warning("You have probably the wrong version installed for the architecture of your computer.\n" +
|
new Popup<>().warning("You probably have the wrong Bitsquare version for this computer.\n" +
|
||||||
"Your computers architecture is: " + osArchitecture + ".\n" +
|
"Your computer's architecture is: " + osArchitecture + ".\n" +
|
||||||
"The Bitsquare binary you installed is: " + Utilities.getJVMArchitecture() + ".\n" +
|
"The Bitsquare binary you installed is: " + Utilities.getJVMArchitecture() + ".\n" +
|
||||||
"Please shut down and re-install the correct version (" + osArchitecture + ").")
|
"Please shut down and re-install the correct version (" + osArchitecture + ").")
|
||||||
.show();
|
.show();
|
||||||
|
@ -358,7 +358,7 @@ public class BitsquareApp extends Application {
|
||||||
if (!shutDownRequested) {
|
if (!shutDownRequested) {
|
||||||
new Popup().headLine("Shut down in progress")
|
new Popup().headLine("Shut down in progress")
|
||||||
.backgroundInfo("Shutting down application can take a few seconds.\n" +
|
.backgroundInfo("Shutting down application can take a few seconds.\n" +
|
||||||
"Please don't interrupt that process.")
|
"Please don't interrupt this process.")
|
||||||
.hideCloseButton()
|
.hideCloseButton()
|
||||||
.useAnimation(false)
|
.useAnimation(false)
|
||||||
.show();
|
.show();
|
||||||
|
|
|
@ -59,7 +59,7 @@ bg color of non edit textFields: fafafa
|
||||||
-bs-buy: -bs-yellow;
|
-bs-buy: -bs-yellow;
|
||||||
-bs-buy-focus: derive(-bs-buy, -50%);
|
-bs-buy-focus: derive(-bs-buy, -50%);
|
||||||
-bs-buy-hover: derive(-bs-buy, -10%);
|
-bs-buy-hover: derive(-bs-buy, -10%);
|
||||||
-bs-buy-transparent: derive(-bs-buy, 95%);
|
-bs-buy-transparent: derive(-bs-buy, 75%);
|
||||||
|
|
||||||
-bs-sell: -bs-turquoise;
|
-bs-sell: -bs-turquoise;
|
||||||
-bs-sell-focus: derive(-bs-sell, -50%);
|
-bs-sell-focus: derive(-bs-sell, -50%);
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class AliPayForm extends PaymentMethodForm {
|
||||||
private InputTextField accountNrInputTextField;
|
private InputTextField accountNrInputTextField;
|
||||||
|
|
||||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account nr.:", ((AliPayAccountContractData) paymentAccountContractData).getAccountNr());
|
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account no.:", ((AliPayAccountContractData) paymentAccountContractData).getAccountNr());
|
||||||
return gridRow;
|
return gridRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ public class AliPayForm extends PaymentMethodForm {
|
||||||
public void addFormForAddAccount() {
|
public void addFormForAddAccount() {
|
||||||
gridRowFrom = gridRow + 1;
|
gridRowFrom = gridRow + 1;
|
||||||
|
|
||||||
accountNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Account nr.:").second;
|
accountNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Account no.:").second;
|
||||||
accountNrInputTextField.setValidator(aliPayValidator);
|
accountNrInputTextField.setValidator(aliPayValidator);
|
||||||
accountNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
accountNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||||
aliPayAccount.setAccountNr(newValue);
|
aliPayAccount.setAccountNr(newValue);
|
||||||
|
@ -84,7 +84,7 @@ public class AliPayForm extends PaymentMethodForm {
|
||||||
gridRowFrom = gridRow;
|
gridRowFrom = gridRow;
|
||||||
addLabelTextField(gridPane, gridRow, "Account name:", aliPayAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
addLabelTextField(gridPane, gridRow, "Account name:", aliPayAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(aliPayAccount.getPaymentMethod().getId()));
|
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(aliPayAccount.getPaymentMethod().getId()));
|
||||||
TextField field = addLabelTextField(gridPane, ++gridRow, "Account nr.:", aliPayAccount.getAccountNr()).second;
|
TextField field = addLabelTextField(gridPane, ++gridRow, "Account no.:", aliPayAccount.getAccountNr()).second;
|
||||||
field.setMouseTransparent(false);
|
field.setMouseTransparent(false);
|
||||||
addLabelTextField(gridPane, ++gridRow, "Currency:", aliPayAccount.getSingleTradeCurrency().getNameAndCode());
|
addLabelTextField(gridPane, ++gridRow, "Currency:", aliPayAccount.getSingleTradeCurrency().getNameAndCode());
|
||||||
addAllowedPeriod();
|
addAllowedPeriod();
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class ClearXchangeForm 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:", ((ClearXchangeAccountContractData) paymentAccountContractData).getHolderName());
|
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name:", ((ClearXchangeAccountContractData) paymentAccountContractData).getHolderName());
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Email or mobile nr.:", ((ClearXchangeAccountContractData) paymentAccountContractData).getEmailOrMobileNr());
|
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Email or mobile no.:", ((ClearXchangeAccountContractData) paymentAccountContractData).getEmailOrMobileNr());
|
||||||
return gridRow;
|
return gridRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +64,8 @@ public class ClearXchangeForm extends PaymentMethodForm {
|
||||||
clearXchangeAccount.setHolderName(newValue);
|
clearXchangeAccount.setHolderName(newValue);
|
||||||
updateFromInputs();
|
updateFromInputs();
|
||||||
});
|
});
|
||||||
|
|
||||||
mobileNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Email or mobile nr.:").second;
|
mobileNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Email or mobile no.:").second;
|
||||||
mobileNrInputTextField.setValidator(clearXchangeValidator);
|
mobileNrInputTextField.setValidator(clearXchangeValidator);
|
||||||
mobileNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
mobileNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||||
clearXchangeAccount.setEmailOrMobileNr(newValue);
|
clearXchangeAccount.setEmailOrMobileNr(newValue);
|
||||||
|
@ -93,7 +93,7 @@ public class ClearXchangeForm extends PaymentMethodForm {
|
||||||
addLabelTextField(gridPane, gridRow, "Account name:", clearXchangeAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
addLabelTextField(gridPane, gridRow, "Account name:", clearXchangeAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(clearXchangeAccount.getPaymentMethod().getId()));
|
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(clearXchangeAccount.getPaymentMethod().getId()));
|
||||||
addLabelTextField(gridPane, ++gridRow, "Account holder name:", clearXchangeAccount.getHolderName());
|
addLabelTextField(gridPane, ++gridRow, "Account holder name:", clearXchangeAccount.getHolderName());
|
||||||
TextField field = addLabelTextField(gridPane, ++gridRow, "Email or mobile nr.:", clearXchangeAccount.getEmailOrMobileNr()).second;
|
TextField field = addLabelTextField(gridPane, ++gridRow, "Email or mobile no.:", clearXchangeAccount.getEmailOrMobileNr()).second;
|
||||||
field.setMouseTransparent(false);
|
field.setMouseTransparent(false);
|
||||||
addLabelTextField(gridPane, ++gridRow, "Currency:", clearXchangeAccount.getSingleTradeCurrency().getNameAndCode());
|
addLabelTextField(gridPane, ++gridRow, "Currency:", clearXchangeAccount.getSingleTradeCurrency().getNameAndCode());
|
||||||
addAllowedPeriod();
|
addAllowedPeriod();
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class PerfectMoneyForm extends PaymentMethodForm {
|
||||||
private InputTextField accountNrInputTextField;
|
private InputTextField accountNrInputTextField;
|
||||||
|
|
||||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account nr.:", ((PerfectMoneyAccountContractData) paymentAccountContractData).getAccountNr());
|
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account no.:", ((PerfectMoneyAccountContractData) paymentAccountContractData).getAccountNr());
|
||||||
return gridRow;
|
return gridRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ public class PerfectMoneyForm extends PaymentMethodForm {
|
||||||
public void addFormForAddAccount() {
|
public void addFormForAddAccount() {
|
||||||
gridRowFrom = gridRow + 1;
|
gridRowFrom = gridRow + 1;
|
||||||
|
|
||||||
accountNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Account nr.:").second;
|
accountNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Account no.:").second;
|
||||||
accountNrInputTextField.setValidator(perfectMoneyValidator);
|
accountNrInputTextField.setValidator(perfectMoneyValidator);
|
||||||
accountNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
accountNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||||
perfectMoneyAccount.setAccountNr(newValue);
|
perfectMoneyAccount.setAccountNr(newValue);
|
||||||
|
@ -90,7 +90,7 @@ public class PerfectMoneyForm extends PaymentMethodForm {
|
||||||
gridRowFrom = gridRow;
|
gridRowFrom = gridRow;
|
||||||
addLabelTextField(gridPane, gridRow, "Account name:", perfectMoneyAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
addLabelTextField(gridPane, gridRow, "Account name:", perfectMoneyAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(perfectMoneyAccount.getPaymentMethod().getId()));
|
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(perfectMoneyAccount.getPaymentMethod().getId()));
|
||||||
TextField field = addLabelTextField(gridPane, ++gridRow, "Account nr.:", perfectMoneyAccount.getAccountNr()).second;
|
TextField field = addLabelTextField(gridPane, ++gridRow, "Account no.:", perfectMoneyAccount.getAccountNr()).second;
|
||||||
field.setMouseTransparent(false);
|
field.setMouseTransparent(false);
|
||||||
|
|
||||||
addLabelTextField(gridPane, ++gridRow, "Currency:", perfectMoneyAccount.getSingleTradeCurrency().getNameAndCode());
|
addLabelTextField(gridPane, ++gridRow, "Currency:", perfectMoneyAccount.getSingleTradeCurrency().getNameAndCode());
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class SwishForm extends PaymentMethodForm {
|
||||||
|
|
||||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||||
addLabelTextField(gridPane, ++gridRow, "Account holder name:", ((SwishAccountContractData) paymentAccountContractData).getHolderName());
|
addLabelTextField(gridPane, ++gridRow, "Account holder name:", ((SwishAccountContractData) paymentAccountContractData).getHolderName());
|
||||||
addLabelTextField(gridPane, ++gridRow, "Mobile nr.:", ((SwishAccountContractData) paymentAccountContractData).getMobileNr());
|
addLabelTextField(gridPane, ++gridRow, "Mobile no.:", ((SwishAccountContractData) paymentAccountContractData).getMobileNr());
|
||||||
return gridRow;
|
return gridRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ public class SwishForm extends PaymentMethodForm {
|
||||||
updateFromInputs();
|
updateFromInputs();
|
||||||
});
|
});
|
||||||
|
|
||||||
mobileNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Mobile nr.:").second;
|
mobileNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Mobile no.:").second;
|
||||||
mobileNrInputTextField.setValidator(swishValidator);
|
mobileNrInputTextField.setValidator(swishValidator);
|
||||||
mobileNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
mobileNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||||
swishAccount.setMobileNr(newValue);
|
swishAccount.setMobileNr(newValue);
|
||||||
|
@ -94,7 +94,7 @@ public class SwishForm extends PaymentMethodForm {
|
||||||
addLabelTextField(gridPane, gridRow, "Account name:", swishAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
addLabelTextField(gridPane, gridRow, "Account name:", swishAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(swishAccount.getPaymentMethod().getId()));
|
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(swishAccount.getPaymentMethod().getId()));
|
||||||
addLabelTextField(gridPane, ++gridRow, "Account holder name:", swishAccount.getHolderName());
|
addLabelTextField(gridPane, ++gridRow, "Account holder name:", swishAccount.getHolderName());
|
||||||
TextField field = addLabelTextField(gridPane, ++gridRow, "Mobile nr.:", swishAccount.getMobileNr()).second;
|
TextField field = addLabelTextField(gridPane, ++gridRow, "Mobile no.:", swishAccount.getMobileNr()).second;
|
||||||
field.setMouseTransparent(false);
|
field.setMouseTransparent(false);
|
||||||
addLabelTextField(gridPane, ++gridRow, "Currency:", swishAccount.getSingleTradeCurrency().getNameAndCode());
|
addLabelTextField(gridPane, ++gridRow, "Currency:", swishAccount.getSingleTradeCurrency().getNameAndCode());
|
||||||
addAllowedPeriod();
|
addAllowedPeriod();
|
||||||
|
|
|
@ -137,11 +137,11 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
Pane disputesButtonHolder = new Pane(disputesButton);
|
Pane disputesButtonHolder = new Pane(disputesButton);
|
||||||
|
|
||||||
HBox leftNavPane = new HBox(marketButton, buyButton, sellButton, portfolioButtonHolder, fundsButton, disputesButtonHolder) {{
|
HBox leftNavPane = new HBox(marketButton, buyButton, sellButton, portfolioButtonHolder, fundsButton, disputesButtonHolder) {{
|
||||||
setSpacing(10);
|
|
||||||
setLeftAnchor(this, 10d);
|
setLeftAnchor(this, 10d);
|
||||||
setTopAnchor(this, 0d);
|
setTopAnchor(this, 0d);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
Tuple3<ComboBox<PriceFeedComboBoxItem>, Label, VBox> marketPriceBox = getMarketPriceBox("Market price");
|
Tuple3<ComboBox<PriceFeedComboBoxItem>, Label, VBox> marketPriceBox = getMarketPriceBox("Market price");
|
||||||
ComboBox<PriceFeedComboBoxItem> priceComboBox = marketPriceBox.first;
|
ComboBox<PriceFeedComboBoxItem> priceComboBox = marketPriceBox.first;
|
||||||
|
|
||||||
|
@ -176,11 +176,18 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
|
|
||||||
HBox rightNavPane = new HBox(marketPriceBox.third, availableBalanceBox.second, reservedBalanceBox.second, lockedBalanceBox.second,
|
HBox rightNavPane = new HBox(marketPriceBox.third, availableBalanceBox.second, reservedBalanceBox.second, lockedBalanceBox.second,
|
||||||
settingsButton, accountButton) {{
|
settingsButton, accountButton) {{
|
||||||
setSpacing(10);
|
|
||||||
setRightAnchor(this, 10d);
|
setRightAnchor(this, 10d);
|
||||||
setTopAnchor(this, 0d);
|
setTopAnchor(this, 0d);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
root.widthProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
double w = (double) newValue;
|
||||||
|
if (w > 0) {
|
||||||
|
leftNavPane.setSpacing(w >= 1080 ? 10 : 5);
|
||||||
|
rightNavPane.setSpacing(w >= 1080 ? 10 : 5);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
AnchorPane contentContainer = new AnchorPane() {{
|
AnchorPane contentContainer = new AnchorPane() {{
|
||||||
setId("content-pane");
|
setId("content-pane");
|
||||||
setLeftAnchor(this, 0d);
|
setLeftAnchor(this, 0d);
|
||||||
|
@ -258,7 +265,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
private Tuple2<TextField, VBox> getBalanceBox(String text) {
|
private Tuple2<TextField, VBox> getBalanceBox(String text) {
|
||||||
TextField textField = new TextField();
|
TextField textField = new TextField();
|
||||||
textField.setEditable(false);
|
textField.setEditable(false);
|
||||||
textField.setPrefWidth(140);
|
textField.setPrefWidth(110); //140
|
||||||
textField.setMouseTransparent(true);
|
textField.setMouseTransparent(true);
|
||||||
textField.setFocusTraversable(false);
|
textField.setFocusTraversable(false);
|
||||||
textField.setStyle("-fx-alignment: center; -fx-background-color: white;");
|
textField.setStyle("-fx-alignment: center; -fx-background-color: white;");
|
||||||
|
|
|
@ -142,7 +142,7 @@ public class MainViewModel implements ViewModel {
|
||||||
final BooleanProperty bootstrapComplete = new SimpleBooleanProperty();
|
final BooleanProperty bootstrapComplete = new SimpleBooleanProperty();
|
||||||
|
|
||||||
// software update
|
// software update
|
||||||
final String version = "v." + Version.VERSION;
|
final String version = "v" + Version.VERSION;
|
||||||
|
|
||||||
final BooleanProperty showAppScreen = new SimpleBooleanProperty();
|
final BooleanProperty showAppScreen = new SimpleBooleanProperty();
|
||||||
final StringProperty numPendingTradesAsString = new SimpleStringProperty();
|
final StringProperty numPendingTradesAsString = new SimpleStringProperty();
|
||||||
|
@ -193,7 +193,7 @@ public class MainViewModel implements ViewModel {
|
||||||
this.preferences = preferences;
|
this.preferences = preferences;
|
||||||
this.alertManager = alertManager;
|
this.alertManager = alertManager;
|
||||||
this.privateNotificationManager = privateNotificationManager;
|
this.privateNotificationManager = privateNotificationManager;
|
||||||
this.filterManager = filterManager; // Needed to be referenced so we get it initialized and get the eventlistener registered
|
this.filterManager = filterManager; // Reference so it's initialized and eventlistener gets registered
|
||||||
this.walletPasswordWindow = walletPasswordWindow;
|
this.walletPasswordWindow = walletPasswordWindow;
|
||||||
this.notificationCenter = notificationCenter;
|
this.notificationCenter = notificationCenter;
|
||||||
this.tacWindow = tacWindow;
|
this.tacWindow = tacWindow;
|
||||||
|
@ -298,11 +298,11 @@ public class MainViewModel implements ViewModel {
|
||||||
result = warning;
|
result = warning;
|
||||||
} else {
|
} else {
|
||||||
if (dataReceived && hiddenService)
|
if (dataReceived && hiddenService)
|
||||||
result = "Nr. of P2P network peers: " + numPeers;
|
result = "P2P network peers: " + numPeers;
|
||||||
else if (peers == 0)
|
else if (peers == 0)
|
||||||
result = state;
|
result = state;
|
||||||
else
|
else
|
||||||
result = state + " / Nr. of P2P network peers: " + numPeers;
|
result = state + " / P2P network peers: " + numPeers;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
@ -444,7 +444,7 @@ public class MainViewModel implements ViewModel {
|
||||||
if (exception == null) {
|
if (exception == null) {
|
||||||
double percentage = (double) downloadPercentage;
|
double percentage = (double) downloadPercentage;
|
||||||
int peers = (int) numPeers;
|
int peers = (int) numPeers;
|
||||||
String numPeersString = "Nr. of Bitcoin network peers: " + peers;
|
String numPeersString = "Bitcoin network peers: " + peers;
|
||||||
|
|
||||||
btcSyncProgress.set(percentage);
|
btcSyncProgress.set(percentage);
|
||||||
if (percentage == 1) {
|
if (percentage == 1) {
|
||||||
|
@ -456,14 +456,14 @@ public class MainViewModel implements ViewModel {
|
||||||
result = numPeersString + " / connecting to " + btcNetworkAsString;
|
result = numPeersString + " / connecting to " + btcNetworkAsString;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = "Nr. of Bitcoin network peers: " + numBtcPeers + " / connecting to " + btcNetworkAsString + " failed";
|
result = "Bitcoin network peers: " + numBtcPeers + " / connecting to " + btcNetworkAsString + " failed";
|
||||||
if (exception instanceof TimeoutException) {
|
if (exception instanceof TimeoutException) {
|
||||||
walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout.");
|
walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout.");
|
||||||
} else if (exception.getCause() instanceof BlockStoreException) {
|
} else if (exception.getCause() instanceof BlockStoreException) {
|
||||||
log.error(exception.getMessage());
|
log.error(exception.getMessage());
|
||||||
// Ugly, but no other way to cover that specific case
|
// Ugly, but no other way to cover that specific case
|
||||||
if (exception.getMessage().equals("Store file is already locked by another process"))
|
if (exception.getMessage().equals("Store file is already locked by another process"))
|
||||||
new Popup().warning("Bitsquare is already running. You cannot run 2 instances of Bitsquare.")
|
new Popup().warning("Bitsquare is already running. You cannot run two instances of Bitsquare.")
|
||||||
.closeButtonText("Shut down")
|
.closeButtonText("Shut down")
|
||||||
.onClose(BitsquareApp.shutDownHandler::run)
|
.onClose(BitsquareApp.shutDownHandler::run)
|
||||||
.show();
|
.show();
|
||||||
|
@ -616,7 +616,7 @@ public class MainViewModel implements ViewModel {
|
||||||
|
|
||||||
String remindPasswordAndBackupKey = "remindPasswordAndBackup";
|
String remindPasswordAndBackupKey = "remindPasswordAndBackup";
|
||||||
user.getPaymentAccountsAsObservable().addListener((SetChangeListener<PaymentAccount>) change -> {
|
user.getPaymentAccountsAsObservable().addListener((SetChangeListener<PaymentAccount>) change -> {
|
||||||
if (preferences.showAgain(remindPasswordAndBackupKey) && change.wasAdded()) {
|
if (!walletService.getWallet().isEncrypted() && preferences.showAgain(remindPasswordAndBackupKey) && change.wasAdded()) {
|
||||||
new Popup<>().headLine("Important security recommendation")
|
new Popup<>().headLine("Important security recommendation")
|
||||||
.information("We would like to remind you to consider using password protection for your wallet if you have not already enabled that.\n\n" +
|
.information("We would like to remind you to consider using password protection for your wallet if you have not already enabled that.\n\n" +
|
||||||
"It is also highly recommended to write down the wallet seed words. Those seed words are like a master password for recovering your Bitcoin wallet.\n" +
|
"It is also highly recommended to write down the wallet seed words. Those seed words are like a master password for recovering your Bitcoin wallet.\n" +
|
||||||
|
|
|
@ -121,7 +121,7 @@ public class AccountView extends ActivatableView<TabPane, AccountViewModel> {
|
||||||
|
|
||||||
String key = "accountPrivacyInfo";
|
String key = "accountPrivacyInfo";
|
||||||
if (!DevFlags.DEV_MODE)
|
if (!DevFlags.DEV_MODE)
|
||||||
new Popup().backgroundInfo("In the account screen you can setup your payment accounts for national currencies " +
|
new Popup().backgroundInfo("In the account screen you can setup your trading accounts for national currencies " +
|
||||||
"as well as for altcoins.\n\n" +
|
"as well as for altcoins.\n\n" +
|
||||||
"For Bitcoin you don't need to set up an account.\n" +
|
"For Bitcoin you don't need to set up an account.\n" +
|
||||||
"You can manage your Bitsquare wallet at the \"Funds\" section.\n\n" +
|
"You can manage your Bitsquare wallet at the \"Funds\" section.\n\n" +
|
||||||
|
|
|
@ -102,9 +102,10 @@ public class SeedWordsView extends ActivatableView<GridPane, Void> {
|
||||||
restoreButton = addButtonAfterGroup(root, ++gridRow, "Restore wallet");
|
restoreButton = addButtonAfterGroup(root, ++gridRow, "Restore wallet");
|
||||||
|
|
||||||
addTitledGroupBg(root, ++gridRow, 1, "Information", Layout.GROUP_DISTANCE);
|
addTitledGroupBg(root, ++gridRow, 1, "Information", Layout.GROUP_DISTANCE);
|
||||||
addMultilineLabel(root, gridRow, "Please write down you wallet seed words.\n" +
|
addMultilineLabel(root, gridRow, "Please write down you wallet seed words. " +
|
||||||
"You can recover your wallet with those seed words.\n\n" +
|
"You can recover your wallet with those seed words.\n\n" +
|
||||||
"If you are restoring your wallet you need to use the wallet date of the wallet into which you want to restore.\n" +
|
"If you are restoring your wallet you need to use the wallet date " +
|
||||||
|
"of the wallet into which you want to restore. " +
|
||||||
"So in case you restore to a new wallet it is the today's date.",
|
"So in case you restore to a new wallet it is the today's date.",
|
||||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
|
|
||||||
|
|
|
@ -97,10 +97,10 @@ public class DisputesView extends ActivatableViewAndModel<TabPane, Activatable>
|
||||||
.findAny().isPresent();
|
.findAny().isPresent();
|
||||||
|
|
||||||
if (arbitratorsDisputesTab == null && isArbitrator) {
|
if (arbitratorsDisputesTab == null && isArbitrator) {
|
||||||
arbitratorsDisputesTab = new Tab("Arbitrators support tickets");
|
arbitratorsDisputesTab = new Tab("Arbitrator's support tickets");
|
||||||
arbitratorsDisputesTab.setClosable(false);
|
arbitratorsDisputesTab.setClosable(false);
|
||||||
root.getTabs().add(arbitratorsDisputesTab);
|
root.getTabs().add(arbitratorsDisputesTab);
|
||||||
tradersDisputesTab.setText("Traders support tickets");
|
tradersDisputesTab.setText("Trader's support tickets");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,7 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||||
});
|
});
|
||||||
disputeGroups.sort((o1, o2) -> !o1.isEmpty() && !o2.isEmpty() ? o1.get(0).getOpeningDate().compareTo(o2.get(0).getOpeningDate()) : 0);
|
disputeGroups.sort((o1, o2) -> !o1.isEmpty() && !o2.isEmpty() ? o1.get(0).getOpeningDate().compareTo(o2.get(0).getOpeningDate()) : 0);
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
stringBuilder.append("Summary of all disputes (Nr. of disputes: " + disputeGroups.size() + ")\n\n");
|
stringBuilder.append("Summary of all disputes (No. of disputes: " + disputeGroups.size() + ")\n\n");
|
||||||
disputeGroups.stream().forEach(disputeGroup -> {
|
disputeGroups.stream().forEach(disputeGroup -> {
|
||||||
Dispute dispute0 = disputeGroup.get(0);
|
Dispute dispute0 = disputeGroup.get(0);
|
||||||
stringBuilder.append("##########################################################################################/\n")
|
stringBuilder.append("##########################################################################################/\n")
|
||||||
|
@ -243,12 +243,12 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||||
disputeGroup.stream().forEach(dispute -> {
|
disputeGroup.stream().forEach(dispute -> {
|
||||||
stringBuilder
|
stringBuilder
|
||||||
.append("*******************************************************************************************\n")
|
.append("*******************************************************************************************\n")
|
||||||
.append("** Traders ID: ")
|
.append("** Trader's ID: ")
|
||||||
.append(dispute.getTraderId())
|
.append(dispute.getTraderId())
|
||||||
.append("\n*******************************************************************************************\n")
|
.append("\n*******************************************************************************************\n")
|
||||||
.append("\n");
|
.append("\n");
|
||||||
dispute.getDisputeCommunicationMessagesAsObservableList().stream().forEach(m -> {
|
dispute.getDisputeCommunicationMessagesAsObservableList().stream().forEach(m -> {
|
||||||
String role = m.isSenderIsTrader() ? ">> Traders msg: " : "<< Arbitrators msg: ";
|
String role = m.isSenderIsTrader() ? ">> Trader's msg: " : "<< Arbitrator's msg: ";
|
||||||
stringBuilder.append(role)
|
stringBuilder.append(role)
|
||||||
.append(m.getMessage())
|
.append(m.getMessage())
|
||||||
.append("\n");
|
.append("\n");
|
||||||
|
@ -264,6 +264,13 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||||
.actionButtonText("Copy")
|
.actionButtonText("Copy")
|
||||||
.onAction(() -> Utilities.copyToClipboard(message))
|
.onAction(() -> Utilities.copyToClipboard(message))
|
||||||
.show();
|
.show();
|
||||||
|
} else if (new KeyCodeCombination(KeyCode.U, KeyCombination.SHORTCUT_DOWN).match(event)) {
|
||||||
|
// Hidden shortcut to re-open a dispute. Allow it also for traders not only arbitrator.
|
||||||
|
if (selectedDispute != null) {
|
||||||
|
if (selectedDisputeClosedPropertyListener != null)
|
||||||
|
selectedDispute.isClosedProperty().removeListener(selectedDisputeClosedPropertyListener);
|
||||||
|
selectedDispute.setIsClosed(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -766,7 +773,7 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||||
private void showMailboxIcon() {
|
private void showMailboxIcon() {
|
||||||
statusIcon.setVisible(true);
|
statusIcon.setVisible(true);
|
||||||
AwesomeDude.setIcon(statusIcon, AwesomeIcon.ENVELOPE_ALT, "14");
|
AwesomeDude.setIcon(statusIcon, AwesomeIcon.ENVELOPE_ALT, "14");
|
||||||
Tooltip.install(statusIcon, new Tooltip("Message saved in receivers mailbox"));
|
Tooltip.install(statusIcon, new Tooltip("Message saved in receiver's mailbox"));
|
||||||
statusIcon.setTextFill(Paint.valueOf("#0f87c3"));
|
statusIcon.setTextFill(Paint.valueOf("#0f87c3"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1110,9 +1117,10 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||||
setText(isClosed ? "Closed" : "Open");
|
setText(isClosed ? "Closed" : "Open");
|
||||||
getTableRow().setOpacity(isClosed ? 0.4 : 1);
|
getTableRow().setOpacity(isClosed ? 0.4 : 1);
|
||||||
} else {
|
} else {
|
||||||
if (closedProperty != null)
|
if (closedProperty != null) {
|
||||||
closedProperty.removeListener(listener);
|
closedProperty.removeListener(listener);
|
||||||
|
closedProperty = null;
|
||||||
|
}
|
||||||
setText("");
|
setText("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
||||||
walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE);
|
walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE);
|
||||||
|
|
||||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||||
tableView.setPlaceholder(new Label("No deposit addresses are generated yet"));
|
tableView.setPlaceholder(new Label("No deposit addresses have been generated yet"));
|
||||||
tableViewSelectionListener = (observableValue, oldValue, newValue) -> {
|
tableViewSelectionListener = (observableValue, oldValue, newValue) -> {
|
||||||
if (newValue != null)
|
if (newValue != null)
|
||||||
fillForm(newValue.getAddressString());
|
fillForm(newValue.getAddressString());
|
||||||
|
@ -137,7 +137,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
||||||
|
|
||||||
titledGroupBg = addTitledGroupBg(gridPane, gridRow, 3, "Fund your wallet");
|
titledGroupBg = addTitledGroupBg(gridPane, gridRow, 3, "Fund your wallet");
|
||||||
|
|
||||||
qrCodeLabel = addLabel(gridPane, gridRow, "QR-Code:", 0);
|
qrCodeLabel = addLabel(gridPane, gridRow, "", 0);
|
||||||
//GridPane.setMargin(qrCodeLabel, new Insets(Layout.FIRST_ROW_DISTANCE - 9, 0, 0, 5));
|
//GridPane.setMargin(qrCodeLabel, new Insets(Layout.FIRST_ROW_DISTANCE - 9, 0, 0, 5));
|
||||||
|
|
||||||
qrCodeImageView = new ImageView();
|
qrCodeImageView = new ImageView();
|
||||||
|
|
|
@ -246,7 +246,7 @@ public class LockedView extends ActivatableView<VBox, Void> {
|
||||||
field.setTooltip(new Tooltip("Open popup for details"));
|
field.setTooltip(new Tooltip("Open popup for details"));
|
||||||
setGraphic(field);
|
setGraphic(field);
|
||||||
} else if (item.getAddressEntry().getContext() == AddressEntry.Context.ARBITRATOR) {
|
} else if (item.getAddressEntry().getContext() == AddressEntry.Context.ARBITRATOR) {
|
||||||
setGraphic(new Label("Arbitrators fee"));
|
setGraphic(new Label("Arbitrator's fee"));
|
||||||
} else {
|
} else {
|
||||||
setGraphic(new Label("No details available"));
|
setGraphic(new Label("No details available"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,7 @@ public class ReservedView extends ActivatableView<VBox, Void> {
|
||||||
field.setTooltip(new Tooltip("Open popup for details"));
|
field.setTooltip(new Tooltip("Open popup for details"));
|
||||||
setGraphic(field);
|
setGraphic(field);
|
||||||
} else if (item.getAddressEntry().getContext() == AddressEntry.Context.ARBITRATOR) {
|
} else if (item.getAddressEntry().getContext() == AddressEntry.Context.ARBITRATOR) {
|
||||||
setGraphic(new Label("Arbitrators fee"));
|
setGraphic(new Label("Arbitrator's fee"));
|
||||||
} else {
|
} else {
|
||||||
setGraphic(new Label("No details available"));
|
setGraphic(new Label("No details available"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -616,7 +616,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
|
||||||
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
map.entrySet().stream().forEach(e -> {
|
map.entrySet().stream().forEach(e -> {
|
||||||
stringBuilder.append("Nr. of transactions for amount ").
|
stringBuilder.append("No. of transactions for amount ").
|
||||||
append(formatter.formatCoinWithCode(Coin.valueOf(e.getKey()))).
|
append(formatter.formatCoinWithCode(Coin.valueOf(e.getKey()))).
|
||||||
append(": ").
|
append(": ").
|
||||||
append(e.getValue().size()).
|
append(e.getValue().size()).
|
||||||
|
@ -649,7 +649,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
|
||||||
append(tuple4.forth.second).
|
append(tuple4.forth.second).
|
||||||
append(")");
|
append(")");
|
||||||
});
|
});
|
||||||
String message = stringBuilder.toString() + "\nNr. of transactions by day:" + transactionsByDayStringBuilder.toString();
|
String message = stringBuilder.toString() + "\nNo. of transactions by day:" + transactionsByDayStringBuilder.toString();
|
||||||
new Popup().headLine("Statistical info")
|
new Popup().headLine("Statistical info")
|
||||||
.information(message)
|
.information(message)
|
||||||
.actionButtonText("Copy")
|
.actionButtonText("Copy")
|
||||||
|
|
|
@ -47,6 +47,7 @@ import javafx.scene.chart.XYChart;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.util.Callback;
|
import javafx.util.Callback;
|
||||||
import javafx.util.StringConverter;
|
import javafx.util.StringConverter;
|
||||||
|
@ -111,7 +112,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
||||||
Label currencyLabel = new Label("Currency:");
|
Label currencyLabel = new Label("Currency:");
|
||||||
HBox currencyHBox = new HBox();
|
HBox currencyHBox = new HBox();
|
||||||
currencyHBox.setSpacing(5);
|
currencyHBox.setSpacing(5);
|
||||||
currencyHBox.setPadding(new Insets(10, -20, -10, 20));
|
currencyHBox.setPadding(new Insets(5, -20, -5, 20));
|
||||||
currencyHBox.setAlignment(Pos.CENTER_LEFT);
|
currencyHBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
currencyHBox.getChildren().addAll(currencyLabel, currencyComboBox);
|
currencyHBox.getChildren().addAll(currencyLabel, currencyComboBox);
|
||||||
|
|
||||||
|
@ -129,8 +130,10 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
||||||
sellOfferHeaderLabel = tupleSell.forth;
|
sellOfferHeaderLabel = tupleSell.forth;
|
||||||
|
|
||||||
bottomHBox = new HBox();
|
bottomHBox = new HBox();
|
||||||
bottomHBox.setSpacing(30);
|
bottomHBox.setSpacing(20); //30
|
||||||
bottomHBox.setAlignment(Pos.CENTER);
|
bottomHBox.setAlignment(Pos.CENTER);
|
||||||
|
HBox.setHgrow(tupleBuy.second, Priority.ALWAYS);
|
||||||
|
HBox.setHgrow(tupleSell.second, Priority.ALWAYS);
|
||||||
tupleBuy.second.setUserData("BUY");
|
tupleBuy.second.setUserData("BUY");
|
||||||
tupleSell.second.setUserData("SELL");
|
tupleSell.second.setUserData("SELL");
|
||||||
bottomHBox.getChildren().addAll(tupleBuy.second, tupleSell.second);
|
bottomHBox.getChildren().addAll(tupleBuy.second, tupleSell.second);
|
||||||
|
@ -283,13 +286,13 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
||||||
private Tuple4<TableView<OfferListItem>, VBox, Button, Label> getOfferTable(Offer.Direction direction) {
|
private Tuple4<TableView<OfferListItem>, VBox, Button, Label> getOfferTable(Offer.Direction direction) {
|
||||||
TableView<OfferListItem> tableView = new TableView<>();
|
TableView<OfferListItem> tableView = new TableView<>();
|
||||||
tableView.setMinHeight(109);
|
tableView.setMinHeight(109);
|
||||||
tableView.setMinWidth(530);
|
tableView.setMinWidth(480); //530
|
||||||
|
|
||||||
// price
|
// price
|
||||||
TableColumn<OfferListItem, OfferListItem> priceColumn = new TableColumn<>();
|
TableColumn<OfferListItem, OfferListItem> priceColumn = new TableColumn<>();
|
||||||
priceColumn.textProperty().bind(priceColumnLabel);
|
priceColumn.textProperty().bind(priceColumnLabel);
|
||||||
priceColumn.setMinWidth(130);
|
priceColumn.setMinWidth(115); //130
|
||||||
priceColumn.setMaxWidth(130);
|
priceColumn.setMaxWidth(115); //130
|
||||||
priceColumn.setSortable(false);
|
priceColumn.setSortable(false);
|
||||||
priceColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
priceColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||||
priceColumn.setCellFactory(
|
priceColumn.setCellFactory(
|
||||||
|
@ -332,8 +335,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
||||||
|
|
||||||
// volume
|
// volume
|
||||||
TableColumn<OfferListItem, OfferListItem> volumeColumn = new TableColumn<>();
|
TableColumn<OfferListItem, OfferListItem> volumeColumn = new TableColumn<>();
|
||||||
volumeColumn.setMinWidth(125);
|
volumeColumn.setMinWidth(115); //125
|
||||||
volumeColumn.setMaxWidth(125);
|
|
||||||
volumeColumn.setSortable(false);
|
volumeColumn.setSortable(false);
|
||||||
volumeColumn.textProperty().bind(volumeColumnLabel);
|
volumeColumn.textProperty().bind(volumeColumnLabel);
|
||||||
volumeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
volumeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||||
|
@ -378,8 +380,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
||||||
|
|
||||||
// amount
|
// amount
|
||||||
TableColumn<OfferListItem, OfferListItem> amountColumn = new TableColumn<>("Amount in BTC");
|
TableColumn<OfferListItem, OfferListItem> amountColumn = new TableColumn<>("Amount in BTC");
|
||||||
amountColumn.setMinWidth(125);
|
amountColumn.setMinWidth(115); //125
|
||||||
amountColumn.setMaxWidth(125);
|
|
||||||
amountColumn.setSortable(false);
|
amountColumn.setSortable(false);
|
||||||
amountColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
amountColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||||
amountColumn.setCellFactory(
|
amountColumn.setCellFactory(
|
||||||
|
@ -401,7 +402,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
||||||
|
|
||||||
// accumulated
|
// accumulated
|
||||||
TableColumn<OfferListItem, OfferListItem> accumulatedColumn = new TableColumn<>("Sum in BTC");
|
TableColumn<OfferListItem, OfferListItem> accumulatedColumn = new TableColumn<>("Sum in BTC");
|
||||||
accumulatedColumn.setMinWidth(130);
|
accumulatedColumn.setMinWidth(100);//130
|
||||||
accumulatedColumn.setSortable(false);
|
accumulatedColumn.setSortable(false);
|
||||||
accumulatedColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
accumulatedColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||||
accumulatedColumn.setCellFactory(
|
accumulatedColumn.setCellFactory(
|
||||||
|
|
|
@ -269,7 +269,7 @@ class OfferBookChartViewModel extends ActivatableViewModel {
|
||||||
buildChartAndTableEntries(allSellOffers, Offer.Direction.SELL, sellData, topSellOfferList);
|
buildChartAndTableEntries(allSellOffers, Offer.Direction.SELL, sellData, topSellOfferList);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are more then 3 offers we ignore the offers which are further thn 30% from the best price
|
// If there are more then 3 offers we ignore the offers which are further than 30% from the best price
|
||||||
private List<Offer> filterOffersWithRelevantPrices(List<Offer> offers) {
|
private List<Offer> filterOffersWithRelevantPrices(List<Offer> offers) {
|
||||||
if (offers.size() > 3) {
|
if (offers.size() > 3) {
|
||||||
Fiat bestPrice = offers.get(0).getPrice();
|
Fiat bestPrice = offers.get(0).getPrice();
|
||||||
|
|
|
@ -117,9 +117,9 @@ public class SpreadView extends ActivatableViewAndModel<GridPane, SpreadViewMode
|
||||||
|
|
||||||
private void updateHeaders() {
|
private void updateHeaders() {
|
||||||
numberOfOffersColumn.setText("All offers (" + sortedList.stream().mapToInt(item -> item.numberOfOffers).sum() + ")");
|
numberOfOffersColumn.setText("All offers (" + sortedList.stream().mapToInt(item -> item.numberOfOffers).sum() + ")");
|
||||||
numberOfBuyOffersColumn.setText("Buy BTC offers (" + sortedList.stream().mapToInt(item -> item.numberOfBuyOffers).sum() + ")");
|
numberOfBuyOffersColumn.setText("Buy BTC (" + sortedList.stream().mapToInt(item -> item.numberOfBuyOffers).sum() + ")");
|
||||||
numberOfSellOffersColumn.setText("Sell BTC offers (" + sortedList.stream().mapToInt(item -> item.numberOfSellOffers).sum() + ")");
|
numberOfSellOffersColumn.setText("Sell BTC (" + sortedList.stream().mapToInt(item -> item.numberOfSellOffers).sum() + ")");
|
||||||
totalAmountColumn.setText("Total amount in BTC (" + formatter.formatCoin(Coin.valueOf(sortedList.stream().mapToLong(item -> item.totalAmount.value).sum())) + ")");
|
totalAmountColumn.setText("Total BTC (" + formatter.formatCoin(Coin.valueOf(sortedList.stream().mapToLong(item -> item.totalAmount.value).sum())) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ public class SpreadView extends ActivatableViewAndModel<GridPane, SpreadViewMode
|
||||||
private TableColumn<SpreadItem, SpreadItem> getCurrencyColumn() {
|
private TableColumn<SpreadItem, SpreadItem> getCurrencyColumn() {
|
||||||
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Currency") {
|
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Currency") {
|
||||||
{
|
{
|
||||||
setMinWidth(110);
|
setMinWidth(160); //110
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||||
|
@ -242,7 +242,7 @@ public class SpreadView extends ActivatableViewAndModel<GridPane, SpreadViewMode
|
||||||
private TableColumn<SpreadItem, SpreadItem> getTotalAmountColumn() {
|
private TableColumn<SpreadItem, SpreadItem> getTotalAmountColumn() {
|
||||||
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Total amount") {
|
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Total amount") {
|
||||||
{
|
{
|
||||||
setMinWidth(170);
|
setMinWidth(140); //170
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||||
|
@ -270,7 +270,7 @@ public class SpreadView extends ActivatableViewAndModel<GridPane, SpreadViewMode
|
||||||
private TableColumn<SpreadItem, SpreadItem> getSpreadColumn() {
|
private TableColumn<SpreadItem, SpreadItem> getSpreadColumn() {
|
||||||
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Spread") {
|
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Spread") {
|
||||||
{
|
{
|
||||||
setMinWidth(130);
|
setMinWidth(110); //130
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||||
|
|
|
@ -130,7 +130,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||||
volumeAxisYWidth = (double) newValue;
|
volumeAxisYWidth = (double) newValue;
|
||||||
layoutChart();
|
layoutChart();
|
||||||
};
|
};
|
||||||
tradeStatisticsByCurrencyListener = c -> nrOfTradeStatisticsLabel.setText("Nr. of trades: " + model.tradeStatisticsByCurrency.size());
|
tradeStatisticsByCurrencyListener = c -> nrOfTradeStatisticsLabel.setText("Trades: " + model.tradeStatisticsByCurrency.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -204,7 +204,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||||
priceAxisX.setTickLabelFormatter(getTimeAxisStringConverter());
|
priceAxisX.setTickLabelFormatter(getTimeAxisStringConverter());
|
||||||
volumeAxisX.setTickLabelFormatter(getTimeAxisStringConverter());
|
volumeAxisX.setTickLabelFormatter(getTimeAxisStringConverter());
|
||||||
|
|
||||||
nrOfTradeStatisticsLabel.setText("Nr. of trades: " + model.tradeStatisticsByCurrency.size());
|
nrOfTradeStatisticsLabel.setText("Trades: " + model.tradeStatisticsByCurrency.size());
|
||||||
|
|
||||||
UserThread.runAfter(this::updateChartData, 100, TimeUnit.MILLISECONDS);
|
UserThread.runAfter(this::updateChartData, 100, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
@ -280,7 +280,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
priceChart.setMinHeight(250);
|
priceChart.setMinHeight(200);
|
||||||
priceChart.setMaxHeight(300);
|
priceChart.setMaxHeight(300);
|
||||||
priceChart.setLegendVisible(false);
|
priceChart.setLegendVisible(false);
|
||||||
priceChart.setData(FXCollections.observableArrayList(priceSeries));
|
priceChart.setData(FXCollections.observableArrayList(priceSeries));
|
||||||
|
@ -391,18 +391,18 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
||||||
label.setPadding(new Insets(0, 4, 0, 0));
|
label.setPadding(new Insets(0, 4, 0, 0));
|
||||||
|
|
||||||
toggleGroup = new ToggleGroup();
|
toggleGroup = new ToggleGroup();
|
||||||
|
ToggleButton year = getToggleButton("Year", TradesChartsViewModel.TickUnit.YEAR, toggleGroup, "toggle-left");
|
||||||
ToggleButton month = getToggleButton("Month", TradesChartsViewModel.TickUnit.MONTH, toggleGroup, "toggle-left");
|
ToggleButton month = getToggleButton("Month", TradesChartsViewModel.TickUnit.MONTH, toggleGroup, "toggle-left");
|
||||||
ToggleButton week = getToggleButton("Week", TradesChartsViewModel.TickUnit.WEEK, toggleGroup, "toggle-center");
|
ToggleButton week = getToggleButton("Week", TradesChartsViewModel.TickUnit.WEEK, toggleGroup, "toggle-center");
|
||||||
ToggleButton day = getToggleButton("Day", TradesChartsViewModel.TickUnit.DAY, toggleGroup, "toggle-center");
|
ToggleButton day = getToggleButton("Day", TradesChartsViewModel.TickUnit.DAY, toggleGroup, "toggle-center");
|
||||||
ToggleButton hour = getToggleButton("Hour", TradesChartsViewModel.TickUnit.HOUR, toggleGroup, "toggle-center");
|
ToggleButton hour = getToggleButton("Hour", TradesChartsViewModel.TickUnit.HOUR, toggleGroup, "toggle-center");
|
||||||
ToggleButton minute10 = getToggleButton("10 Minutes", TradesChartsViewModel.TickUnit.MINUTE_10, toggleGroup, "toggle-center");
|
ToggleButton minute10 = getToggleButton("10 Minutes", TradesChartsViewModel.TickUnit.MINUTE_10, toggleGroup, "toggle-center");
|
||||||
ToggleButton minute = getToggleButton("Minute", TradesChartsViewModel.TickUnit.MINUTE, toggleGroup, "toggle-right");
|
|
||||||
|
|
||||||
HBox hBox = new HBox();
|
HBox hBox = new HBox();
|
||||||
hBox.setSpacing(0);
|
hBox.setSpacing(0);
|
||||||
hBox.setPadding(new Insets(5, 9, -10, 10));
|
hBox.setPadding(new Insets(5, 9, -10, 10));
|
||||||
hBox.setAlignment(Pos.CENTER_LEFT);
|
hBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
hBox.getChildren().addAll(currencyLabel, currencyComboBox, spacer, label, month, week, day, hour, minute10, minute);
|
hBox.getChildren().addAll(currencyLabel, currencyComboBox, spacer, label, year, month, week, day, hour, minute10);
|
||||||
return hBox;
|
return hBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,12 +61,15 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public enum TickUnit {
|
public enum TickUnit {
|
||||||
|
YEAR,
|
||||||
MONTH,
|
MONTH,
|
||||||
WEEK,
|
WEEK,
|
||||||
DAY,
|
DAY,
|
||||||
HOUR,
|
HOUR,
|
||||||
MINUTE_10,
|
MINUTE_10,
|
||||||
MINUTE
|
// TODO Can be removed after version 4.9.7
|
||||||
|
// Not used anymore but leave it as it might be used in preferences and could cause an exception if not there.
|
||||||
|
MINUTE
|
||||||
}
|
}
|
||||||
|
|
||||||
private final TradeStatisticsManager tradeStatisticsManager;
|
private final TradeStatisticsManager tradeStatisticsManager;
|
||||||
|
@ -325,6 +328,8 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
||||||
|
|
||||||
long getTickFromTime(long tradeDateAsTime, TickUnit tickUnit) {
|
long getTickFromTime(long tradeDateAsTime, TickUnit tickUnit) {
|
||||||
switch (tickUnit) {
|
switch (tickUnit) {
|
||||||
|
case YEAR:
|
||||||
|
return TimeUnit.MILLISECONDS.toDays(tradeDateAsTime) / 365;
|
||||||
case MONTH:
|
case MONTH:
|
||||||
return TimeUnit.MILLISECONDS.toDays(tradeDateAsTime) / 31;
|
return TimeUnit.MILLISECONDS.toDays(tradeDateAsTime) / 31;
|
||||||
case WEEK:
|
case WEEK:
|
||||||
|
@ -344,6 +349,8 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
||||||
|
|
||||||
long getTimeFromTick(long tick, TickUnit tickUnit) {
|
long getTimeFromTick(long tick, TickUnit tickUnit) {
|
||||||
switch (tickUnit) {
|
switch (tickUnit) {
|
||||||
|
case YEAR:
|
||||||
|
return TimeUnit.DAYS.toMillis(tick) * 365;
|
||||||
case MONTH:
|
case MONTH:
|
||||||
return TimeUnit.DAYS.toMillis(tick) * 31;
|
return TimeUnit.DAYS.toMillis(tick) * 31;
|
||||||
case WEEK:
|
case WEEK:
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class VolumeBar extends Group {
|
||||||
public void update(double height, double candleWidth, CandleData candleData) {
|
public void update(double height, double candleWidth, CandleData candleData) {
|
||||||
bar.resizeRelocate(-candleWidth / 2, 0, candleWidth, height);
|
bar.resizeRelocate(-candleWidth / 2, 0, candleWidth, height);
|
||||||
tooltip.setText("Volume: " + volumeStringConverter.toString(candleData.accumulatedAmount) + "\n" +
|
tooltip.setText("Volume: " + volumeStringConverter.toString(candleData.accumulatedAmount) + "\n" +
|
||||||
"Nr. of trades: " + candleData.numTrades + "\n" +
|
"No. of trades: " + candleData.numTrades + "\n" +
|
||||||
"Date: " + candleData.date);
|
"Date: " + candleData.date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,14 +241,14 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
public void initWithData(Offer.Direction direction, TradeCurrency tradeCurrency) {
|
public void initWithData(Offer.Direction direction, TradeCurrency tradeCurrency) {
|
||||||
boolean result = model.initWithData(direction, tradeCurrency);
|
boolean result = model.initWithData(direction, tradeCurrency);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
new Popup().warning("You don't have a payment account set up.").onClose(this::close).show();
|
new Popup().warning("You don't have a trading account set up.").onClose(this::close).show();
|
||||||
|
|
||||||
if (direction == Offer.Direction.BUY) {
|
if (direction == Offer.Direction.BUY) {
|
||||||
imageView.setId("image-buy-large");
|
imageView.setId("image-buy-large");
|
||||||
|
|
||||||
placeOfferButton.setId("buy-button-big");
|
placeOfferButton.setId("buy-button-big");
|
||||||
placeOfferButton.setText("Review offer for buying bitcoin");
|
placeOfferButton.setText("Review offer to buy bitcoin");
|
||||||
nextButton.setId("buy-button");
|
nextButton.setId("buy-button");
|
||||||
} else {
|
} else {
|
||||||
imageView.setId("image-sell-large");
|
imageView.setId("image-sell-large");
|
||||||
|
@ -256,7 +256,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
totalToPayTextField.setPromptText(BSResources.get("createOffer.fundsBox.totalsNeeded.prompt"));
|
totalToPayTextField.setPromptText(BSResources.get("createOffer.fundsBox.totalsNeeded.prompt"));
|
||||||
|
|
||||||
placeOfferButton.setId("sell-button-big");
|
placeOfferButton.setId("sell-button-big");
|
||||||
placeOfferButton.setText("Review offer for selling bitcoin");
|
placeOfferButton.setText("Review offer to sell bitcoin");
|
||||||
nextButton.setId("sell-button");
|
nextButton.setId("sell-button");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,14 +348,11 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
"- Trading fee: " + model.getOfferFee() + "\n" +
|
"- Trading fee: " + model.getOfferFee() + "\n" +
|
||||||
"- Bitcoin mining fee: " + model.getNetworkFee() + "\n\n" +
|
"- Bitcoin mining fee: " + model.getNetworkFee() + "\n\n" +
|
||||||
|
|
||||||
"For funding you can choose between 2 options:\n" +
|
"You can choose between two options when funding your trade:\n" +
|
||||||
"- Transfer fund from your Bitsquare wallet OR\n" +
|
"- Use your Bitsquare wallet (convenient, but transactions may be linkable) OR\n" +
|
||||||
"- Transfer fund from any external wallet\n\n" +
|
"- Transfer from an external wallet (potentially more private)\n\n" +
|
||||||
|
|
||||||
"If you prefer a higher level of privacy you should use for each trade a distinct funding transaction using the external wallet option.\n" +
|
"You will see all funding options and details after closing this popup.")
|
||||||
"If you prefer convenience using the Bitsquare wallet for several trades might be your preferred option.\n\n" +
|
|
||||||
|
|
||||||
"You can see all the details for funding when you close that popup.")
|
|
||||||
.dontShowAgainId(key, preferences)
|
.dontShowAgainId(key, preferences)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
@ -483,7 +480,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
placeOfferButton.disableProperty().bind(model.isPlaceOfferButtonDisabled);
|
placeOfferButton.disableProperty().bind(model.isPlaceOfferButtonDisabled);
|
||||||
cancelButton2.disableProperty().bind(model.cancelButtonDisabled);
|
cancelButton2.disableProperty().bind(model.cancelButtonDisabled);
|
||||||
|
|
||||||
// payment account
|
// trading account
|
||||||
currencyComboBox.prefWidthProperty().bind(paymentAccountsComboBox.widthProperty());
|
currencyComboBox.prefWidthProperty().bind(paymentAccountsComboBox.widthProperty());
|
||||||
currencyComboBox.managedProperty().bind(currencyComboBox.visibleProperty());
|
currencyComboBox.managedProperty().bind(currencyComboBox.visibleProperty());
|
||||||
currencyComboBoxLabel.visibleProperty().bind(currencyComboBox.visibleProperty());
|
currencyComboBoxLabel.visibleProperty().bind(currencyComboBox.visibleProperty());
|
||||||
|
@ -531,7 +528,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
placeOfferButton.disableProperty().unbind();
|
placeOfferButton.disableProperty().unbind();
|
||||||
cancelButton2.disableProperty().unbind();
|
cancelButton2.disableProperty().unbind();
|
||||||
|
|
||||||
// payment account
|
// trading account
|
||||||
currencyComboBox.managedProperty().unbind();
|
currencyComboBox.managedProperty().unbind();
|
||||||
currencyComboBox.prefWidthProperty().unbind();
|
currencyComboBox.prefWidthProperty().unbind();
|
||||||
currencyComboBoxLabel.visibleProperty().unbind();
|
currencyComboBoxLabel.visibleProperty().unbind();
|
||||||
|
@ -627,7 +624,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
if (DevFlags.DEV_MODE) {
|
if (DevFlags.DEV_MODE) {
|
||||||
close();
|
close();
|
||||||
} else if (newValue) {
|
} else if (newValue) {
|
||||||
// We need a bit of delay to avoid issues with fade out/fade in of 2 popups
|
// We need a bit of delay to avoid issues with fade out/fade in of 2 popups
|
||||||
String key = "createOfferSuccessInfo";
|
String key = "createOfferSuccessInfo";
|
||||||
if (preferences.showAgain(key)) {
|
if (preferences.showAgain(key)) {
|
||||||
UserThread.runAfter(() -> new Popup().headLine(BSResources.get("createOffer.success.headline"))
|
UserThread.runAfter(() -> new Popup().headLine(BSResources.get("createOffer.success.headline"))
|
||||||
|
@ -729,11 +726,11 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPaymentGroup() {
|
private void addPaymentGroup() {
|
||||||
TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, gridRow, 2, "Select payment account");
|
TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, gridRow, 2, "Select trading account");
|
||||||
GridPane.setColumnSpan(titledGroupBg, 3);
|
GridPane.setColumnSpan(titledGroupBg, 3);
|
||||||
|
|
||||||
paymentAccountsComboBox = addLabelComboBox(gridPane, gridRow, "Payment account:", Layout.FIRST_ROW_DISTANCE).second;
|
paymentAccountsComboBox = addLabelComboBox(gridPane, gridRow, "Trading account:", Layout.FIRST_ROW_DISTANCE).second;
|
||||||
paymentAccountsComboBox.setPromptText("Select payment account");
|
paymentAccountsComboBox.setPromptText("Select trading account");
|
||||||
paymentAccountsComboBox.setMinWidth(300);
|
paymentAccountsComboBox.setMinWidth(300);
|
||||||
editOfferElements.add(paymentAccountsComboBox);
|
editOfferElements.add(paymentAccountsComboBox);
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
// If we would change the price representation in the domain we would not be backward compatible
|
// If we would change the price representation in the domain we would not be backward compatible
|
||||||
final StringProperty price = new SimpleStringProperty();
|
final StringProperty price = new SimpleStringProperty();
|
||||||
|
|
||||||
// Positive % value means always a better price form the offerers perspective:
|
// Positive % value means always a better price form the offerer's perspective:
|
||||||
// Buyer (with fiat): lower price as market
|
// Buyer (with fiat): lower price as market
|
||||||
// Buyer (with altcoin): higher (display) price as market (display price is inverted)
|
// Buyer (with altcoin): higher (display) price as market (display price is inverted)
|
||||||
final StringProperty marketPriceMargin = new SimpleStringProperty();
|
final StringProperty marketPriceMargin = new SimpleStringProperty();
|
||||||
|
@ -160,7 +160,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
UserThread.runAfter(() -> {
|
UserThread.runAfter(() -> {
|
||||||
amount.set("1");
|
amount.set("1");
|
||||||
minAmount.set(amount.get());
|
minAmount.set(amount.get());
|
||||||
price.set("500");
|
price.set("600");
|
||||||
|
|
||||||
setAmountToModel();
|
setAmountToModel();
|
||||||
setMinAmountToModel();
|
setMinAmountToModel();
|
||||||
|
@ -510,7 +510,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
formatter.formatCoinWithCode(dataModel.totalAvailableBalance) + " in your Bitsquare wallet.\n\n" +
|
formatter.formatCoinWithCode(dataModel.totalAvailableBalance) + " in your Bitsquare wallet.\n\n" +
|
||||||
"Please fund that trade from an external Bitcoin wallet or fund your Bitsquare " +
|
"Please fund that trade from an external Bitcoin wallet or fund your Bitsquare " +
|
||||||
"wallet at \"Funds/Depost funds\".")
|
"wallet at \"Funds/Depost funds\".")
|
||||||
.actionButtonText("Go to \"Funds/Depost funds\"")
|
.actionButtonText("Go to \"Funds/Deposit funds\"")
|
||||||
.onAction(() -> navigation.navigateTo(MainView.class, FundsView.class, DepositView.class))
|
.onAction(() -> navigation.navigateTo(MainView.class, FundsView.class, DepositView.class))
|
||||||
.show();
|
.show();
|
||||||
return false;
|
return false;
|
||||||
|
@ -623,7 +623,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
|
|
||||||
public boolean isPriceInRange() {
|
public boolean isPriceInRange() {
|
||||||
if (marketPriceMargin.get() != null && !marketPriceMargin.get().isEmpty()) {
|
if (marketPriceMargin.get() != null && !marketPriceMargin.get().isEmpty()) {
|
||||||
if (formatter.parsePercentStringToDouble(marketPriceMargin.get()) > preferences.getMaxPriceDistanceInPercent()) {
|
if (Math.abs(formatter.parsePercentStringToDouble(marketPriceMargin.get())) > preferences.getMaxPriceDistanceInPercent()) {
|
||||||
displayPriceOutOfRangePopup();
|
displayPriceOutOfRangePopup();
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -59,7 +59,7 @@ public class OfferBook {
|
||||||
if (!offerBookListItems.contains(offerBookListItem)) {
|
if (!offerBookListItems.contains(offerBookListItem)) {
|
||||||
offerBookListItems.add(offerBookListItem);
|
offerBookListItems.add(offerBookListItem);
|
||||||
|
|
||||||
Log.logIfStressTests("Offer added: Nr. of offers = " + offerBookListItems.size());
|
Log.logIfStressTests("Offer added: No. of offers = " + offerBookListItems.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ public class OfferBook {
|
||||||
OfferBookListItem item = candidate.get();
|
OfferBookListItem item = candidate.get();
|
||||||
if (offerBookListItems.contains(item)) {
|
if (offerBookListItems.contains(item)) {
|
||||||
offerBookListItems.remove(item);
|
offerBookListItems.remove(item);
|
||||||
Log.logIfStressTests("Offer removed: Nr. of offers = " + offerBookListItems.size());
|
Log.logIfStressTests("Offer removed: No. of offers = " + offerBookListItems.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ public class OfferBook {
|
||||||
.map(OfferBookListItem::new)
|
.map(OfferBookListItem::new)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
Log.logIfStressTests("Offer filled: Nr. of offers = " + offerBookListItems.size());
|
Log.logIfStressTests("Offer filled: No. of offers = " + offerBookListItems.size());
|
||||||
|
|
||||||
log.debug("offerBookListItems " + offerBookListItems.size());
|
log.debug("offerBookListItems " + offerBookListItems.size());
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
package io.bitsquare.gui.main.offer.offerbook;
|
package io.bitsquare.gui.main.offer.offerbook;
|
||||||
|
|
||||||
import io.bitsquare.alert.PrivateNotificationManager;
|
import io.bitsquare.alert.PrivateNotificationManager;
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.btc.FeePolicy;
|
||||||
import io.bitsquare.gui.Navigation;
|
import io.bitsquare.gui.Navigation;
|
||||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||||
import io.bitsquare.gui.common.view.FxmlView;
|
import io.bitsquare.gui.common.view.FxmlView;
|
||||||
|
@ -36,7 +36,6 @@ import io.bitsquare.gui.main.offer.OfferView;
|
||||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||||
import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow;
|
import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow;
|
||||||
import io.bitsquare.gui.util.BSFormatter;
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
import io.bitsquare.gui.util.CurrencyListItem;
|
|
||||||
import io.bitsquare.gui.util.GUIUtil;
|
import io.bitsquare.gui.util.GUIUtil;
|
||||||
import io.bitsquare.gui.util.Layout;
|
import io.bitsquare.gui.util.Layout;
|
||||||
import io.bitsquare.locale.BSResources;
|
import io.bitsquare.locale.BSResources;
|
||||||
|
@ -65,7 +64,6 @@ import org.fxmisc.easybind.Subscription;
|
||||||
import org.fxmisc.easybind.monadic.MonadicBinding;
|
import org.fxmisc.easybind.monadic.MonadicBinding;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||||
|
|
||||||
|
@ -77,7 +75,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
private BSFormatter formatter;
|
private BSFormatter formatter;
|
||||||
private PrivateNotificationManager privateNotificationManager;
|
private PrivateNotificationManager privateNotificationManager;
|
||||||
|
|
||||||
private ComboBox<CurrencyListItem> currencyComboBox;
|
private ComboBox<TradeCurrency> currencyComboBox;
|
||||||
private ComboBox<PaymentMethod> paymentMethodComboBox;
|
private ComboBox<PaymentMethod> paymentMethodComboBox;
|
||||||
private Button createOfferButton;
|
private Button createOfferButton;
|
||||||
private TableColumn<OfferBookListItem, OfferBookListItem> amountColumn, volumeColumn, marketColumn, priceColumn, paymentMethodColumn, avatarColumn;
|
private TableColumn<OfferBookListItem, OfferBookListItem> amountColumn, volumeColumn, marketColumn, priceColumn, paymentMethodColumn, avatarColumn;
|
||||||
|
@ -90,7 +88,6 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
private ListChangeListener<OfferBookListItem> offerListListener;
|
private ListChangeListener<OfferBookListItem> offerListListener;
|
||||||
private MonadicBinding<Void> currencySelectionBinding;
|
private MonadicBinding<Void> currencySelectionBinding;
|
||||||
private Subscription currencySelectionSubscriber;
|
private Subscription currencySelectionSubscriber;
|
||||||
private ListChangeListener<CurrencyListItem> currencyListItemsListener;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -115,7 +112,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
|
|
||||||
currencyComboBox = addLabelComboBox(root, gridRow, "Filter by currency:", Layout.FIRST_ROW_DISTANCE).second;
|
currencyComboBox = addLabelComboBox(root, gridRow, "Filter by currency:", Layout.FIRST_ROW_DISTANCE).second;
|
||||||
currencyComboBox.setPromptText("Select currency");
|
currencyComboBox.setPromptText("Select currency");
|
||||||
currencyComboBox.setConverter(GUIUtil.getCurrencyListItemConverter("offers", model.preferences));
|
currencyComboBox.setConverter(GUIUtil.getTradeCurrencyConverter());
|
||||||
|
|
||||||
paymentMethodComboBox = addLabelComboBox(root, ++gridRow, "Filter by payment method:").second;
|
paymentMethodComboBox = addLabelComboBox(root, ++gridRow, "Filter by payment method:").second;
|
||||||
paymentMethodComboBox.setPromptText("Select payment method");
|
paymentMethodComboBox.setPromptText("Select payment method");
|
||||||
|
@ -199,25 +196,19 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
GridPane.setHalignment(createOfferButton, HPos.RIGHT);
|
GridPane.setHalignment(createOfferButton, HPos.RIGHT);
|
||||||
GridPane.setVgrow(createOfferButton, Priority.NEVER);
|
GridPane.setVgrow(createOfferButton, Priority.NEVER);
|
||||||
GridPane.setValignment(createOfferButton, VPos.TOP);
|
GridPane.setValignment(createOfferButton, VPos.TOP);
|
||||||
offerListListener = c -> nrOfOffersLabel.setText("Nr. of offers: " + model.getOfferList().size());
|
offerListListener = c -> nrOfOffersLabel.setText("No. of offers: " + model.getOfferList().size());
|
||||||
currencyListItemsListener = c -> applyCurrencyComboBoxSelection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void activate() {
|
protected void activate() {
|
||||||
currencyComboBox.setItems(model.getCurrencyListItems());
|
currencyComboBox.setItems(model.getTradeCurrencies());
|
||||||
currencyComboBox.setVisibleRowCount(25);
|
currencyComboBox.setVisibleRowCount(Math.min(currencyComboBox.getItems().size(), 25));
|
||||||
|
currencyComboBox.setOnAction(e -> model.onSetTradeCurrency(currencyComboBox.getSelectionModel().getSelectedItem()));
|
||||||
|
|
||||||
model.currencyListItems.addListener(currencyListItemsListener);
|
if (model.showAllTradeCurrenciesProperty.get())
|
||||||
|
currencyComboBox.getSelectionModel().select(0);
|
||||||
applyCurrencyComboBoxSelection();
|
else
|
||||||
|
currencyComboBox.getSelectionModel().select(model.getSelectedTradeCurrency());
|
||||||
currencyComboBox.setOnAction(e -> {
|
|
||||||
CurrencyListItem selectedItem = currencyComboBox.getSelectionModel().getSelectedItem();
|
|
||||||
|
|
||||||
if (selectedItem != null)
|
|
||||||
model.onSetTradeCurrency(selectedItem.tradeCurrency);
|
|
||||||
});
|
|
||||||
|
|
||||||
priceColumn.sortableProperty().bind(model.showAllTradeCurrenciesProperty.not());
|
priceColumn.sortableProperty().bind(model.showAllTradeCurrenciesProperty.not());
|
||||||
volumeColumn.sortableProperty().bind(model.showAllTradeCurrenciesProperty.not());
|
volumeColumn.sortableProperty().bind(model.showAllTradeCurrenciesProperty.not());
|
||||||
|
@ -242,7 +233,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
if (!tableView.getColumns().contains(marketColumn))
|
if (!tableView.getColumns().contains(marketColumn))
|
||||||
tableView.getColumns().add(0, marketColumn);
|
tableView.getColumns().add(0, marketColumn);
|
||||||
} else {
|
} else {
|
||||||
volumeColumn.setText("Amount in " + code + " (min - max)");
|
volumeColumn.setText(code + " (min - max)");
|
||||||
priceColumn.setText(formatter.getPriceWithCurrencyCode(code));
|
priceColumn.setText(formatter.getPriceWithCurrencyCode(code));
|
||||||
|
|
||||||
if (tableView.getColumns().contains(marketColumn))
|
if (tableView.getColumns().contains(marketColumn))
|
||||||
|
@ -261,7 +252,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
priceColumn.setSortType((model.getDirection() == Offer.Direction.BUY) ? TableColumn.SortType.ASCENDING : TableColumn.SortType.DESCENDING);
|
priceColumn.setSortType((model.getDirection() == Offer.Direction.BUY) ? TableColumn.SortType.ASCENDING : TableColumn.SortType.DESCENDING);
|
||||||
|
|
||||||
model.getOfferList().addListener(offerListListener);
|
model.getOfferList().addListener(offerListListener);
|
||||||
nrOfOffersLabel.setText("Nr. of offers: " + model.getOfferList().size());
|
nrOfOffersLabel.setText("No. of offers: " + model.getOfferList().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -274,18 +265,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
priceColumn.sortableProperty().unbind();
|
priceColumn.sortableProperty().unbind();
|
||||||
amountColumn.sortableProperty().unbind();
|
amountColumn.sortableProperty().unbind();
|
||||||
model.getOfferList().removeListener(offerListListener);
|
model.getOfferList().removeListener(offerListListener);
|
||||||
model.currencyListItems.removeListener(currencyListItemsListener);
|
|
||||||
currencySelectionSubscriber.unsubscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyCurrencyComboBoxSelection() {
|
currencySelectionSubscriber.unsubscribe();
|
||||||
Optional<CurrencyListItem> selectedCurrencyListItem = model.getSelectedCurrencyListItem();
|
|
||||||
UserThread.execute(() -> {
|
|
||||||
if (model.showAllTradeCurrenciesProperty.get() || !selectedCurrencyListItem.isPresent())
|
|
||||||
currencyComboBox.getSelectionModel().select(model.getShowAllCurrencyListItem());
|
|
||||||
else
|
|
||||||
currencyComboBox.getSelectionModel().select(selectedCurrencyListItem.get());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -312,9 +293,9 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
TradeCurrency selectedTradeCurrency = model.getSelectedTradeCurrency();
|
TradeCurrency selectedTradeCurrency = model.getSelectedTradeCurrency();
|
||||||
if (selectedTradeCurrency != null) {
|
if (selectedTradeCurrency != null) {
|
||||||
Offer.Direction direction = model.getDirection();
|
Offer.Direction direction = model.getDirection();
|
||||||
String preFix = "Create new offer for ";
|
String preFix = "Create new offer to ";
|
||||||
String directionText = direction == Offer.Direction.BUY ? "buying" : "selling";
|
String directionText = direction == Offer.Direction.BUY ? "buy" : "sell";
|
||||||
String mirroredDirectionText = direction == Offer.Direction.SELL ? "buying" : "selling";
|
String mirroredDirectionText = direction == Offer.Direction.SELL ? "buy" : "sell";
|
||||||
String code = selectedTradeCurrency.getCode();
|
String code = selectedTradeCurrency.getCode();
|
||||||
if (model.showAllTradeCurrenciesProperty.get())
|
if (model.showAllTradeCurrenciesProperty.get())
|
||||||
createOfferButton.setText(preFix + directionText + " BTC");
|
createOfferButton.setText(preFix + directionText + " BTC");
|
||||||
|
@ -340,19 +321,19 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
|
|
||||||
private void onCreateOffer() {
|
private void onCreateOffer() {
|
||||||
if (!model.hasPaymentAccount()) {
|
if (!model.hasPaymentAccount()) {
|
||||||
openPopupForMissingAccountSetup("You have not setup a payment account",
|
openPopupForMissingAccountSetup("You have not setup a trading account",
|
||||||
"You need to setup a national currency or altcoin account before you can create an offer.\n" +
|
"You need to setup a national currency or altcoin account before you can create an offer.\n" +
|
||||||
"Do you want to setup an account?", FiatAccountsView.class, "\"Account\"");
|
"Do you want to setup an account?", FiatAccountsView.class, "\"Account\"");
|
||||||
} else if (!model.hasPaymentAccountForCurrency()) {
|
} else if (!model.hasPaymentAccountForCurrency()) {
|
||||||
new Popup().headLine("No payment account for selected currency")
|
new Popup().headLine("No trading account for selected currency")
|
||||||
.instruction("You don't have a payment account for the selected currency.\n" +
|
.instruction("You don't have a trading account for the selected currency.\n" +
|
||||||
"Do you want to create an offer with one of your existing payment accounts?")
|
"Do you want to create an offer with one of your existing trading accounts?")
|
||||||
.actionButtonText("Yes, create offer")
|
.actionButtonText("Yes, create offer")
|
||||||
.onAction(() -> {
|
.onAction(() -> {
|
||||||
createOfferButton.setDisable(true);
|
createOfferButton.setDisable(true);
|
||||||
offerActionHandler.onCreateOffer(model.getSelectedTradeCurrency());
|
offerActionHandler.onCreateOffer(model.getSelectedTradeCurrency());
|
||||||
})
|
})
|
||||||
.closeButtonText("Set up a new payment account")
|
.closeButtonText("Set up a new trading account")
|
||||||
.onClose(() -> {
|
.onClose(() -> {
|
||||||
navigation.setReturnPath(navigation.getCurrentPath());
|
navigation.setReturnPath(navigation.getCurrentPath());
|
||||||
navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, FiatAccountsView.class);
|
navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, FiatAccountsView.class);
|
||||||
|
@ -376,9 +357,9 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
"You need to setup at least one arbitrator to be able to trade.\n" +
|
"You need to setup at least one arbitrator to be able to trade.\n" +
|
||||||
"Do you want to do this now?", ArbitratorSelectionView.class, "\"Arbitrator selection\"");
|
"Do you want to do this now?", ArbitratorSelectionView.class, "\"Arbitrator selection\"");
|
||||||
} else if (!isPaymentAccountValidForOffer) {
|
} else if (!isPaymentAccountValidForOffer) {
|
||||||
openPopupForMissingAccountSetup("No matching payment account",
|
openPopupForMissingAccountSetup("No matching trading account.",
|
||||||
"You don't have a payment account with the payment method required for that offer.\n" +
|
"You don't have a trading account with the payment method required for that offer.\n" +
|
||||||
"You need to setup a payment account with that payment method if you want to take this offer.\n" +
|
"You need to setup a trading account with that payment method if you want to take this offer.\n" +
|
||||||
"Do you want to do this now?", FiatAccountsView.class, "\"Account\"");
|
"Do you want to do this now?", FiatAccountsView.class, "\"Account\"");
|
||||||
} else if (!hasSameProtocolVersion) {
|
} else if (!hasSameProtocolVersion) {
|
||||||
new Popup().warning("That offer requires a different protocol version as the one used in your " +
|
new Popup().warning("That offer requires a different protocol version as the one used in your " +
|
||||||
|
@ -414,7 +395,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
String key = "RemoveOfferWarning";
|
String key = "RemoveOfferWarning";
|
||||||
if (model.preferences.showAgain(key))
|
if (model.preferences.showAgain(key))
|
||||||
new Popup().warning("Are you sure you want to remove that offer?\n" +
|
new Popup().warning("Are you sure you want to remove that offer?\n" +
|
||||||
"The offer fee you have paid will be lost if you remove that offer.")
|
"The offer fee you " + model.formatter.formatCoinWithCode(FeePolicy.getCreateOfferFee()) + " will be lost if you remove that offer.")
|
||||||
.actionButtonText("Remove offer")
|
.actionButtonText("Remove offer")
|
||||||
.onAction(() -> doRemoveOffer(offer))
|
.onAction(() -> doRemoveOffer(offer))
|
||||||
.closeButtonText("Don't remove the offer")
|
.closeButtonText("Don't remove the offer")
|
||||||
|
@ -432,7 +413,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
String key = "WithdrawFundsAfterRemoveOfferInfo";
|
String key = "WithdrawFundsAfterRemoveOfferInfo";
|
||||||
model.onRemoveOpenOffer(offer,
|
model.onRemoveOpenOffer(offer,
|
||||||
() -> {
|
() -> {
|
||||||
log.debug("Remove offer was successful");
|
log.debug("Remove offer was successful.");
|
||||||
if (model.preferences.showAgain(key))
|
if (model.preferences.showAgain(key))
|
||||||
new Popup().instruction("You can withdraw the funds you paid in from the \"Fund/Available for withdrawal\" screen.")
|
new Popup().instruction("You can withdraw the funds you paid in from the \"Fund/Available for withdrawal\" screen.")
|
||||||
.actionButtonText("Go to \"Funds/Available for withdrawal\"")
|
.actionButtonText("Go to \"Funds/Available for withdrawal\"")
|
||||||
|
@ -461,7 +442,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private TableColumn<OfferBookListItem, OfferBookListItem> getAmountColumn() {
|
private TableColumn<OfferBookListItem, OfferBookListItem> getAmountColumn() {
|
||||||
TableColumn<OfferBookListItem, OfferBookListItem> column = new TableColumn<OfferBookListItem, OfferBookListItem>("Amount in BTC (min - max)") {
|
TableColumn<OfferBookListItem, OfferBookListItem> column = new TableColumn<OfferBookListItem, OfferBookListItem>("BTC (min - max)") {
|
||||||
{
|
{
|
||||||
setMinWidth(150);
|
setMinWidth(150);
|
||||||
}
|
}
|
||||||
|
@ -491,8 +472,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
private TableColumn<OfferBookListItem, OfferBookListItem> getMarketColumn() {
|
private TableColumn<OfferBookListItem, OfferBookListItem> getMarketColumn() {
|
||||||
TableColumn<OfferBookListItem, OfferBookListItem> column = new TableColumn<OfferBookListItem, OfferBookListItem>("Market") {
|
TableColumn<OfferBookListItem, OfferBookListItem> column = new TableColumn<OfferBookListItem, OfferBookListItem>("Market") {
|
||||||
{
|
{
|
||||||
setMinWidth(130);
|
setMinWidth(120); //130
|
||||||
setMaxWidth(130);
|
// setMaxWidth(130);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||||
|
@ -522,7 +503,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
private TableColumn<OfferBookListItem, OfferBookListItem> getPriceColumn() {
|
private TableColumn<OfferBookListItem, OfferBookListItem> getPriceColumn() {
|
||||||
TableColumn<OfferBookListItem, OfferBookListItem> column = new TableColumn<OfferBookListItem, OfferBookListItem>() {
|
TableColumn<OfferBookListItem, OfferBookListItem> column = new TableColumn<OfferBookListItem, OfferBookListItem>() {
|
||||||
{
|
{
|
||||||
setMinWidth(130);
|
setMinWidth(120); //130
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||||
|
@ -572,7 +553,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
private TableColumn<OfferBookListItem, OfferBookListItem> getVolumeColumn() {
|
private TableColumn<OfferBookListItem, OfferBookListItem> getVolumeColumn() {
|
||||||
TableColumn<OfferBookListItem, OfferBookListItem> column = new TableColumn<OfferBookListItem, OfferBookListItem>() {
|
TableColumn<OfferBookListItem, OfferBookListItem> column = new TableColumn<OfferBookListItem, OfferBookListItem>() {
|
||||||
{
|
{
|
||||||
setMinWidth(130);
|
setMinWidth(125); //130
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||||
|
@ -621,7 +602,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
private TableColumn<OfferBookListItem, OfferBookListItem> getPaymentMethodColumn() {
|
private TableColumn<OfferBookListItem, OfferBookListItem> getPaymentMethodColumn() {
|
||||||
TableColumn<OfferBookListItem, OfferBookListItem> column = new TableColumn<OfferBookListItem, OfferBookListItem>("Payment method") {
|
TableColumn<OfferBookListItem, OfferBookListItem> column = new TableColumn<OfferBookListItem, OfferBookListItem>("Payment method") {
|
||||||
{
|
{
|
||||||
setMinWidth(120);
|
setMinWidth(125); //120
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||||
|
@ -675,8 +656,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
|
|
||||||
{
|
{
|
||||||
button.setGraphic(iconView);
|
button.setGraphic(iconView);
|
||||||
button.setMinWidth(150);
|
button.setMinWidth(130);
|
||||||
button.setMaxWidth(150);
|
button.setMaxWidth(130);
|
||||||
button.setGraphicTextGap(10);
|
button.setGraphicTextGap(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,10 +665,10 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
public void updateItem(final OfferBookListItem newItem, boolean empty) {
|
public void updateItem(final OfferBookListItem newItem, boolean empty) {
|
||||||
super.updateItem(newItem, empty);
|
super.updateItem(newItem, empty);
|
||||||
|
|
||||||
|
TableRow tableRow = getTableRow();
|
||||||
if (newItem != null && !empty) {
|
if (newItem != null && !empty) {
|
||||||
final Offer offer = newItem.getOffer();
|
final Offer offer = newItem.getOffer();
|
||||||
boolean myOffer = model.isMyOffer(offer);
|
boolean myOffer = model.isMyOffer(offer);
|
||||||
TableRow tableRow = getTableRow();
|
|
||||||
if (tableRow != null) {
|
if (tableRow != null) {
|
||||||
isPaymentAccountValidForOffer = model.isAnyPaymentAccountValidForOffer(offer);
|
isPaymentAccountValidForOffer = model.isAnyPaymentAccountValidForOffer(offer);
|
||||||
hasMatchingArbitrator = model.hasMatchingArbitrator(offer);
|
hasMatchingArbitrator = model.hasMatchingArbitrator(offer);
|
||||||
|
@ -706,7 +687,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
if (isTradable) {
|
if (isTradable) {
|
||||||
// set first row button as default
|
// set first row button as default
|
||||||
button.setDefaultButton(getIndex() == 0);
|
button.setDefaultButton(getIndex() == 0);
|
||||||
tableRow.setOnMouseClicked(null);
|
tableRow.setOnMousePressed(null);
|
||||||
} else {
|
} else {
|
||||||
button.setDefaultButton(false);
|
button.setDefaultButton(false);
|
||||||
tableRow.setOnMousePressed(e -> {
|
tableRow.setOnMousePressed(e -> {
|
||||||
|
@ -749,10 +730,9 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
setGraphic(null);
|
setGraphic(null);
|
||||||
if (button != null)
|
if (button != null)
|
||||||
button.setOnAction(null);
|
button.setOnAction(null);
|
||||||
TableRow tableRow = getTableRow();
|
|
||||||
if (tableRow != null) {
|
if (tableRow != null) {
|
||||||
tableRow.setOpacity(1);
|
tableRow.setOpacity(1);
|
||||||
tableRow.setOnMouseClicked(null);
|
tableRow.setOnMousePressed(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -786,8 +766,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||||
String hostName = newItem.getOffer().getOwnerNodeAddress().hostName;
|
String hostName = newItem.getOffer().getOwnerNodeAddress().hostName;
|
||||||
int numPastTrades = model.getNumPastTrades(newItem.getOffer());
|
int numPastTrades = model.getNumPastTrades(newItem.getOffer());
|
||||||
boolean hasTraded = numPastTrades > 0;
|
boolean hasTraded = numPastTrades > 0;
|
||||||
String tooltipText = hasTraded ? "Offerers onion address: " + hostName + "\n" +
|
String tooltipText = hasTraded ? "Offerer's onion address: " + hostName + "\n" +
|
||||||
"You have already traded " + numPastTrades + " times with that offerer." : "Offerers onion address: " + hostName;
|
"You have already traded " + numPastTrades + " times with that offerer." : "Offerer's onion address: " + hostName;
|
||||||
Node identIcon = new PeerInfoIcon(hostName, tooltipText, numPastTrades, privateNotificationManager, newItem.getOffer());
|
Node identIcon = new PeerInfoIcon(hostName, tooltipText, numPastTrades, privateNotificationManager, newItem.getOffer());
|
||||||
setPadding(new Insets(-2, 0, -2, 0));
|
setPadding(new Insets(-2, 0, -2, 0));
|
||||||
if (identIcon != null)
|
if (identIcon != null)
|
||||||
|
|
|
@ -30,7 +30,6 @@ import io.bitsquare.gui.main.MainView;
|
||||||
import io.bitsquare.gui.main.settings.SettingsView;
|
import io.bitsquare.gui.main.settings.SettingsView;
|
||||||
import io.bitsquare.gui.main.settings.preferences.PreferencesView;
|
import io.bitsquare.gui.main.settings.preferences.PreferencesView;
|
||||||
import io.bitsquare.gui.util.BSFormatter;
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
import io.bitsquare.gui.util.CurrencyListItem;
|
|
||||||
import io.bitsquare.gui.util.GUIUtil;
|
import io.bitsquare.gui.util.GUIUtil;
|
||||||
import io.bitsquare.locale.*;
|
import io.bitsquare.locale.*;
|
||||||
import io.bitsquare.p2p.NodeAddress;
|
import io.bitsquare.p2p.NodeAddress;
|
||||||
|
@ -59,7 +58,6 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -80,10 +78,10 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
|
|
||||||
private final FilteredList<OfferBookListItem> filteredItems;
|
private final FilteredList<OfferBookListItem> filteredItems;
|
||||||
private final SortedList<OfferBookListItem> sortedItems;
|
private final SortedList<OfferBookListItem> sortedItems;
|
||||||
|
private final ListChangeListener<TradeCurrency> tradeCurrencyListChangeListener;
|
||||||
private TradeCurrency selectedTradeCurrency;
|
private TradeCurrency selectedTradeCurrency;
|
||||||
private final ListChangeListener<OfferBookListItem> offerBookListItemsListener;
|
private final ObservableList<TradeCurrency> allTradeCurrencies = FXCollections.observableArrayList();
|
||||||
final ObservableList<CurrencyListItem> currencyListItems = FXCollections.observableArrayList();
|
|
||||||
private CurrencyListItem showAllCurrencyListItem = new CurrencyListItem(new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, GUIUtil.SHOW_ALL_FLAG), -1);
|
|
||||||
private Offer.Direction direction;
|
private Offer.Direction direction;
|
||||||
|
|
||||||
private final StringProperty btcCode = new SimpleStringProperty();
|
private final StringProperty btcCode = new SimpleStringProperty();
|
||||||
|
@ -122,16 +120,19 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
|
|
||||||
offerBookListItems = offerBook.getOfferBookListItems();
|
offerBookListItems = offerBook.getOfferBookListItems();
|
||||||
offerBookListItemsListener = c -> fillTradeCurrencies();
|
|
||||||
|
|
||||||
this.filteredItems = new FilteredList<>(offerBookListItems);
|
this.filteredItems = new FilteredList<>(offerBookListItems);
|
||||||
this.sortedItems = new SortedList<>(filteredItems);
|
this.sortedItems = new SortedList<>(filteredItems);
|
||||||
|
|
||||||
|
tradeCurrencyListChangeListener = c -> {
|
||||||
|
tradeCurrencyCodes = preferences.getTradeCurrenciesAsObservable().stream().map(e -> e.getCode()).collect(Collectors.toSet());
|
||||||
|
fillAllTradeCurrencies();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void activate() {
|
protected void activate() {
|
||||||
fillTradeCurrencies();
|
tradeCurrencyCodes = preferences.getTradeCurrenciesAsObservable().stream().map(e -> e.getCode()).collect(Collectors.toSet());
|
||||||
offerBookListItems.addListener(offerBookListItemsListener);
|
|
||||||
|
|
||||||
String code = direction == Offer.Direction.BUY ? preferences.getBuyScreenCurrencyCode() : preferences.getSellScreenCurrencyCode();
|
String code = direction == Offer.Direction.BUY ? preferences.getBuyScreenCurrencyCode() : preferences.getSellScreenCurrencyCode();
|
||||||
if (code != null && !code.equals("SHOW_ALL_FLAG") && !code.isEmpty() && CurrencyUtil.getTradeCurrency(code).isPresent()) {
|
if (code != null && !code.equals("SHOW_ALL_FLAG") && !code.isEmpty() && CurrencyUtil.getTradeCurrency(code).isPresent()) {
|
||||||
|
@ -145,7 +146,9 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
|
|
||||||
setPriceFeedType();
|
setPriceFeedType();
|
||||||
|
|
||||||
|
fillAllTradeCurrencies();
|
||||||
btcCode.bind(preferences.btcDenominationProperty());
|
btcCode.bind(preferences.btcDenominationProperty());
|
||||||
|
preferences.getTradeCurrenciesAsObservable().addListener(tradeCurrencyListChangeListener);
|
||||||
offerBook.fillOfferBookListItems();
|
offerBook.fillOfferBookListItems();
|
||||||
applyFilterPredicate();
|
applyFilterPredicate();
|
||||||
setMarketPriceFeedCurrency();
|
setMarketPriceFeedCurrency();
|
||||||
|
@ -154,9 +157,10 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
@Override
|
@Override
|
||||||
protected void deactivate() {
|
protected void deactivate() {
|
||||||
btcCode.unbind();
|
btcCode.unbind();
|
||||||
offerBookListItems.removeListener(offerBookListItemsListener);
|
preferences.getTradeCurrenciesAsObservable().removeListener(tradeCurrencyListChangeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// API
|
// API
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -227,6 +231,10 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ObservableList<TradeCurrency> getTradeCurrencies() {
|
||||||
|
return allTradeCurrencies;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isBootstrapped() {
|
boolean isBootstrapped() {
|
||||||
return p2PService.isBootstrapped();
|
return p2PService.isBootstrapped();
|
||||||
}
|
}
|
||||||
|
@ -241,19 +249,6 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObservableList<CurrencyListItem> getCurrencyListItems() {
|
|
||||||
return currencyListItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<CurrencyListItem> getSelectedCurrencyListItem() {
|
|
||||||
return currencyListItems.stream().filter(e -> tradeCurrencyCode.get() != null && e.tradeCurrency.getCode().equals(tradeCurrencyCode.get())).findAny();
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrencyListItem getShowAllCurrencyListItem() {
|
|
||||||
return showAllCurrencyListItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String getAmount(OfferBookListItem item) {
|
String getAmount(OfferBookListItem item) {
|
||||||
Offer offer = item.getOffer();
|
Offer offer = item.getOffer();
|
||||||
Coin amount = offer.getAmount();
|
Coin amount = offer.getAmount();
|
||||||
|
@ -326,14 +321,14 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
String bankId = offer.getBankId();
|
String bankId = offer.getBankId();
|
||||||
if (bankId != null && !bankId.equals("null")) {
|
if (bankId != null && !bankId.equals("null")) {
|
||||||
if (BankUtil.isBankIdRequired(methodCountryCode))
|
if (BankUtil.isBankIdRequired(methodCountryCode))
|
||||||
result += "\nOfferers bank ID: " + bankId;
|
result += "\nOfferer's bank ID: " + bankId;
|
||||||
else if (BankUtil.isBankNameRequired(methodCountryCode))
|
else if (BankUtil.isBankNameRequired(methodCountryCode))
|
||||||
result += "\nOfferers bank name: " + bankId;
|
result += "\nOfferer's bank name: " + bankId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (methodCountryCode != null)
|
if (methodCountryCode != null)
|
||||||
result += "\nOfferers seat of bank country: " + CountryUtil.getNameByCode(methodCountryCode);
|
result += "\nOfferer's seat of bank country: " + CountryUtil.getNameByCode(methodCountryCode);
|
||||||
|
|
||||||
List<String> acceptedCountryCodes = offer.getAcceptedCountryCodes();
|
List<String> acceptedCountryCodes = offer.getAcceptedCountryCodes();
|
||||||
List<String> acceptedBanks = offer.getAcceptedBankIds();
|
List<String> acceptedBanks = offer.getAcceptedBankIds();
|
||||||
|
@ -381,24 +376,12 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
priceFeedService.setType(direction == Offer.Direction.BUY ? PriceFeedService.Type.ASK : PriceFeedService.Type.BID);
|
priceFeedService.setType(direction == Offer.Direction.BUY ? PriceFeedService.Type.ASK : PriceFeedService.Type.BID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillTradeCurrencies() {
|
private void fillAllTradeCurrencies() {
|
||||||
// Don't use a set as we need all entries
|
allTradeCurrencies.clear();
|
||||||
Offer.Direction mirroredDirection = direction == Offer.Direction.BUY ? Offer.Direction.SELL : Offer.Direction.BUY;
|
// Used for ignoring filter (show all)
|
||||||
List<TradeCurrency> tradeCurrencyList = offerBookListItems.stream()
|
allTradeCurrencies.add(new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, GUIUtil.SHOW_ALL_FLAG));
|
||||||
.filter(e -> e.getOffer().getDirection() == mirroredDirection)
|
allTradeCurrencies.addAll(preferences.getTradeCurrenciesAsObservable());
|
||||||
.map(e -> {
|
allTradeCurrencies.add(new CryptoCurrency(GUIUtil.EDIT_FLAG, GUIUtil.EDIT_FLAG));
|
||||||
Optional<TradeCurrency> tradeCurrencyOptional = CurrencyUtil.getTradeCurrency(e.getOffer().getCurrencyCode());
|
|
||||||
if (tradeCurrencyOptional.isPresent())
|
|
||||||
return tradeCurrencyOptional.get();
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
|
|
||||||
})
|
|
||||||
.filter(e -> e != null)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
GUIUtil.fillCurrencyListItems(tradeCurrencyList, currencyListItems, showAllCurrencyListItem, preferences);
|
|
||||||
tradeCurrencyCodes = currencyListItems.stream().map(e -> e.tradeCurrency.getCode()).collect(Collectors.toSet());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -433,7 +416,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
boolean currencyResult;
|
boolean currencyResult;
|
||||||
final String currencyCode = offer.getCurrencyCode();
|
final String currencyCode = offer.getCurrencyCode();
|
||||||
if (showAllTradeCurrenciesProperty.get()) {
|
if (showAllTradeCurrenciesProperty.get()) {
|
||||||
currencyResult = true;
|
currencyResult = tradeCurrencyCodes.contains(currencyCode);
|
||||||
} else
|
} else
|
||||||
currencyResult = currencyCode.equals(selectedTradeCurrency.getCode());
|
currencyResult = currencyCode.equals(selectedTradeCurrency.getCode());
|
||||||
|
|
||||||
|
|
|
@ -223,7 +223,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
directionLabel.setId("direction-icon-label-buy");
|
directionLabel.setId("direction-icon-label-buy");
|
||||||
|
|
||||||
takeOfferButton.setId("buy-button-big");
|
takeOfferButton.setId("buy-button-big");
|
||||||
takeOfferButton.setText("Review offer for buying bitcoin");
|
takeOfferButton.setText("Review offer to buy bitcoin");
|
||||||
nextButton.setId("buy-button");
|
nextButton.setId("buy-button");
|
||||||
} else {
|
} else {
|
||||||
imageView.setId("image-sell-large");
|
imageView.setId("image-sell-large");
|
||||||
|
@ -231,7 +231,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
|
|
||||||
takeOfferButton.setId("sell-button-big");
|
takeOfferButton.setId("sell-button-big");
|
||||||
nextButton.setId("sell-button");
|
nextButton.setId("sell-button");
|
||||||
takeOfferButton.setText("Review offer for selling bitcoin");
|
takeOfferButton.setText("Review offer to sell bitcoin");
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean showComboBox = model.getPossiblePaymentAccounts().size() > 1;
|
boolean showComboBox = model.getPossiblePaymentAccounts().size() > 1;
|
||||||
|
@ -350,14 +350,11 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
"- Trading fee: " + model.getTakerFee() + "\n" +
|
"- Trading fee: " + model.getTakerFee() + "\n" +
|
||||||
"- Bitcoin mining fee: " + model.getNetworkFee() + "\n\n" +
|
"- Bitcoin mining fee: " + model.getNetworkFee() + "\n\n" +
|
||||||
|
|
||||||
"For funding you can choose between 2 options:\n" +
|
"You can choose between two options when funding your trade:\n" +
|
||||||
"- Transfer fund from your Bitsquare wallet OR\n" +
|
"- Use your Bitsquare wallet (convenient, but transactions may be linkable) OR\n" +
|
||||||
"- Transfer fund from any external wallet\n\n" +
|
"- Transfer from an external wallet (potentially more private)\n\n" +
|
||||||
|
|
||||||
"If you prefer a higher level of privacy you should use for each trade a distinct funding transaction using the external wallet option.\n" +
|
"You will see all funding options and details after closing this popup.")
|
||||||
"If you prefer convenience using the Bitsquare wallet for several trades might be your preferred option.\n\n" +
|
|
||||||
|
|
||||||
"You can see all the details for funding when you close that popup.")
|
|
||||||
.dontShowAgainId(key, preferences)
|
.dontShowAgainId(key, preferences)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
@ -623,12 +620,12 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, gridRow, 2, "Payment info");
|
TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, gridRow, 2, "Payment info");
|
||||||
GridPane.setColumnSpan(titledGroupBg, 3);
|
GridPane.setColumnSpan(titledGroupBg, 3);
|
||||||
|
|
||||||
Tuple2<Label, ComboBox> tuple = addLabelComboBox(gridPane, gridRow, "Payment account:", Layout.FIRST_ROW_DISTANCE);
|
Tuple2<Label, ComboBox> tuple = addLabelComboBox(gridPane, gridRow, "Trading account:", Layout.FIRST_ROW_DISTANCE);
|
||||||
paymentAccountsLabel = tuple.first;
|
paymentAccountsLabel = tuple.first;
|
||||||
paymentAccountsLabel.setVisible(false);
|
paymentAccountsLabel.setVisible(false);
|
||||||
paymentAccountsLabel.setManaged(false);
|
paymentAccountsLabel.setManaged(false);
|
||||||
paymentAccountsComboBox = tuple.second;
|
paymentAccountsComboBox = tuple.second;
|
||||||
paymentAccountsComboBox.setPromptText("Select payment account");
|
paymentAccountsComboBox.setPromptText("Select trading account");
|
||||||
paymentAccountsComboBox.setConverter(new StringConverter<PaymentAccount>() {
|
paymentAccountsComboBox.setConverter(new StringConverter<PaymentAccount>() {
|
||||||
@Override
|
@Override
|
||||||
public String toString(PaymentAccount paymentAccount) {
|
public String toString(PaymentAccount paymentAccount) {
|
||||||
|
|
|
@ -128,7 +128,7 @@ public class ContractWindow extends Overlay<ContractWindow> {
|
||||||
contract.getBuyerPayoutAddressString() + " / " + contract.getSellerPayoutAddressString()).second.setMouseTransparent(false);
|
contract.getBuyerPayoutAddressString() + " / " + contract.getSellerPayoutAddressString()).second.setMouseTransparent(false);
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Network address BTC buyer / BTC seller:", contract.getBuyerNodeAddress().getFullAddress() + " / " + contract.getSellerNodeAddress().getFullAddress());
|
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Network address BTC buyer / BTC seller:", contract.getBuyerNodeAddress().getFullAddress() + " / " + contract.getSellerNodeAddress().getFullAddress());
|
||||||
|
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Nr. of disputes BTC buyer / BTC seller:", disputeManager.getNrOfDisputes(true, contract) + " / " + disputeManager.getNrOfDisputes(false, contract));
|
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "No. of disputes BTC buyer / BTC seller:", disputeManager.getNrOfDisputes(true, contract) + " / " + disputeManager.getNrOfDisputes(false, contract));
|
||||||
|
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "BTC buyer payment details:",
|
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "BTC buyer payment details:",
|
||||||
BSResources.get(contract.getBuyerPaymentAccountContractData().getPaymentDetails())).second.setMouseTransparent(false);
|
BSResources.get(contract.getBuyerPaymentAccountContractData().getPaymentDetails())).second.setMouseTransparent(false);
|
||||||
|
|
|
@ -27,6 +27,7 @@ import io.bitsquare.btc.WalletService;
|
||||||
import io.bitsquare.btc.exceptions.TransactionVerificationException;
|
import io.bitsquare.btc.exceptions.TransactionVerificationException;
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.common.UserThread;
|
||||||
import io.bitsquare.common.util.Tuple2;
|
import io.bitsquare.common.util.Tuple2;
|
||||||
|
import io.bitsquare.gui.components.InputTextField;
|
||||||
import io.bitsquare.gui.main.overlays.Overlay;
|
import io.bitsquare.gui.main.overlays.Overlay;
|
||||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||||
import io.bitsquare.gui.util.BSFormatter;
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
|
@ -69,18 +70,23 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
private Optional<Runnable> finalizeDisputeHandlerOptional = Optional.empty();
|
private Optional<Runnable> finalizeDisputeHandlerOptional = Optional.empty();
|
||||||
private ToggleGroup tradeAmountToggleGroup;
|
private ToggleGroup tradeAmountToggleGroup;
|
||||||
private DisputeResult disputeResult;
|
private DisputeResult disputeResult;
|
||||||
private RadioButton buyerIsWinnerRadioButton, sellerIsWinnerRadioButton, shareRadioButton, loserPaysFeeRadioButton, splitFeeRadioButton,
|
private RadioButton buyerIsWinnerRadioButton, sellerIsWinnerRadioButton, shareRadioButton, customRadioButton, loserPaysFeeRadioButton, splitFeeRadioButton,
|
||||||
waiveFeeRadioButton, reasonWasBugRadioButton, reasonWasUsabilityIssueRadioButton, reasonProtocolViolationRadioButton, reasonNoReplyRadioButton, reasonWasScamRadioButton, reasonWasOtherRadioButton;
|
waiveFeeRadioButton, reasonWasBugRadioButton, reasonWasUsabilityIssueRadioButton, reasonProtocolViolationRadioButton, reasonNoReplyRadioButton, reasonWasScamRadioButton, reasonWasOtherRadioButton;
|
||||||
private Optional<Dispute> peersDisputeOptional;
|
private Optional<Dispute> peersDisputeOptional;
|
||||||
private Coin arbitratorPayoutAmount, winnerPayoutAmount, loserPayoutAmount, stalematePayoutAmount;
|
private Coin arbitratorPayoutAmount, winnerPayoutAmount, loserPayoutAmount, stalematePayoutAmount;
|
||||||
private ToggleGroup feeToggleGroup, reasonToggleGroup;
|
private ToggleGroup feeToggleGroup, reasonToggleGroup;
|
||||||
private String role;
|
private String role;
|
||||||
private TextArea summaryNotesTextArea;
|
private TextArea summaryNotesTextArea;
|
||||||
private ObjectBinding<Tuple2<DisputeResult.DisputeFeePolicy, Toggle>> feePaymentPolicyChanged;
|
|
||||||
private ChangeListener<Tuple2<DisputeResult.DisputeFeePolicy, Toggle>> feePaymentPolicyListener;
|
|
||||||
private ChangeListener<Boolean> shareRadioButtonSelectedListener;
|
|
||||||
private ChangeListener<Toggle> feeToggleSelectionListener, reasonToggleSelectionListener;
|
|
||||||
// keep a reference to not get GCed
|
// keep a reference to not get GCed
|
||||||
|
private ObjectBinding<Tuple2<DisputeResult.DisputeFeePolicy, Toggle>> feePaymentPolicyChanged;
|
||||||
|
|
||||||
|
private ChangeListener<Tuple2<DisputeResult.DisputeFeePolicy, Toggle>> feePaymentPolicyListener;
|
||||||
|
private ChangeListener<Boolean> shareRadioButtonSelectedListener, customRadioButtonSelectedListener;
|
||||||
|
private ChangeListener<Toggle> feeToggleSelectionListener, reasonToggleSelectionListener;
|
||||||
|
private InputTextField buyerPayoutAmountInputTextField, sellerPayoutAmountInputTextField, arbitratorPayoutAmountInputTextField;
|
||||||
|
private ChangeListener<String> buyerPayoutAmountListener, sellerPayoutAmountListener, arbitratorPayoutAmountListener;
|
||||||
|
private CheckBox isLoserPublisherCheckBox;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -130,6 +136,11 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
|
|
||||||
if (reasonToggleGroup != null)
|
if (reasonToggleGroup != null)
|
||||||
reasonToggleGroup.selectedToggleProperty().removeListener(reasonToggleSelectionListener);
|
reasonToggleGroup.selectedToggleProperty().removeListener(reasonToggleSelectionListener);
|
||||||
|
|
||||||
|
if (customRadioButton != null)
|
||||||
|
customRadioButton.selectedProperty().removeListener(customRadioButtonSelectedListener);
|
||||||
|
|
||||||
|
removePayoutAmountListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -172,6 +183,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
|
|
||||||
addTradeAmountPayoutControls();
|
addTradeAmountPayoutControls();
|
||||||
addFeeControls();
|
addFeeControls();
|
||||||
|
addPayoutAmountTextFields();
|
||||||
addReasonControls();
|
addReasonControls();
|
||||||
|
|
||||||
boolean applyPeersDisputeResult = peersDisputeOptional.isPresent() && peersDisputeOptional.get().isClosed();
|
boolean applyPeersDisputeResult = peersDisputeOptional.isPresent() && peersDisputeOptional.get().isClosed();
|
||||||
|
@ -183,6 +195,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
disputeResult.setArbitratorPayoutAmount(peersDisputeResult.getArbitratorPayoutAmount());
|
disputeResult.setArbitratorPayoutAmount(peersDisputeResult.getArbitratorPayoutAmount());
|
||||||
disputeResult.setDisputeFeePolicy(peersDisputeResult.getDisputeFeePolicy());
|
disputeResult.setDisputeFeePolicy(peersDisputeResult.getDisputeFeePolicy());
|
||||||
disputeResult.setWinner(peersDisputeResult.getWinner());
|
disputeResult.setWinner(peersDisputeResult.getWinner());
|
||||||
|
disputeResult.setLoserIsPublisher(peersDisputeResult.isLoserPublisher());
|
||||||
disputeResult.setReason(peersDisputeResult.getReason());
|
disputeResult.setReason(peersDisputeResult.getReason());
|
||||||
disputeResult.setSummaryNotes(peersDisputeResult.summaryNotesProperty().get());
|
disputeResult.setSummaryNotes(peersDisputeResult.summaryNotesProperty().get());
|
||||||
|
|
||||||
|
@ -195,10 +208,18 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
buyerIsWinnerRadioButton.setDisable(true);
|
buyerIsWinnerRadioButton.setDisable(true);
|
||||||
sellerIsWinnerRadioButton.setDisable(true);
|
sellerIsWinnerRadioButton.setDisable(true);
|
||||||
shareRadioButton.setDisable(true);
|
shareRadioButton.setDisable(true);
|
||||||
|
customRadioButton.setDisable(true);
|
||||||
loserPaysFeeRadioButton.setDisable(true);
|
loserPaysFeeRadioButton.setDisable(true);
|
||||||
splitFeeRadioButton.setDisable(true);
|
splitFeeRadioButton.setDisable(true);
|
||||||
waiveFeeRadioButton.setDisable(true);
|
waiveFeeRadioButton.setDisable(true);
|
||||||
|
|
||||||
|
buyerPayoutAmountInputTextField.setDisable(true);
|
||||||
|
sellerPayoutAmountInputTextField.setDisable(true);
|
||||||
|
arbitratorPayoutAmountInputTextField.setDisable(true);
|
||||||
|
buyerPayoutAmountInputTextField.setEditable(false);
|
||||||
|
sellerPayoutAmountInputTextField.setEditable(false);
|
||||||
|
arbitratorPayoutAmountInputTextField.setEditable(false);
|
||||||
|
|
||||||
reasonWasBugRadioButton.setDisable(true);
|
reasonWasBugRadioButton.setDisable(true);
|
||||||
reasonWasUsabilityIssueRadioButton.setDisable(true);
|
reasonWasUsabilityIssueRadioButton.setDisable(true);
|
||||||
reasonProtocolViolationRadioButton.setDisable(true);
|
reasonProtocolViolationRadioButton.setDisable(true);
|
||||||
|
@ -206,6 +227,9 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
reasonWasScamRadioButton.setDisable(true);
|
reasonWasScamRadioButton.setDisable(true);
|
||||||
reasonWasOtherRadioButton.setDisable(true);
|
reasonWasOtherRadioButton.setDisable(true);
|
||||||
|
|
||||||
|
isLoserPublisherCheckBox.setDisable(true);
|
||||||
|
isLoserPublisherCheckBox.setSelected(peersDisputeResult.isLoserPublisher());
|
||||||
|
|
||||||
calculatePayoutAmounts(disputeResult.getDisputeFeePolicy());
|
calculatePayoutAmounts(disputeResult.getDisputeFeePolicy());
|
||||||
applyTradeAmountRadioButtonStates();
|
applyTradeAmountRadioButtonStates();
|
||||||
} else {
|
} else {
|
||||||
|
@ -214,10 +238,10 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
() -> new Tuple2<>(disputeResult.disputeFeePolicyProperty().get(), tradeAmountToggleGroup.selectedToggleProperty().get()),
|
() -> new Tuple2<>(disputeResult.disputeFeePolicyProperty().get(), tradeAmountToggleGroup.selectedToggleProperty().get()),
|
||||||
disputeResult.disputeFeePolicyProperty(),
|
disputeResult.disputeFeePolicyProperty(),
|
||||||
tradeAmountToggleGroup.selectedToggleProperty());
|
tradeAmountToggleGroup.selectedToggleProperty());
|
||||||
feePaymentPolicyListener = (observable, oldValue, newValue) -> {
|
feePaymentPolicyListener = (observable, oldValue, newValue) -> applyPayoutAmounts(newValue.first, newValue.second);
|
||||||
applyPayoutAmounts(newValue.first, newValue.second);
|
|
||||||
};
|
|
||||||
feePaymentPolicyChanged.addListener(feePaymentPolicyListener);
|
feePaymentPolicyChanged.addListener(feePaymentPolicyListener);
|
||||||
|
|
||||||
|
isLoserPublisherCheckBox.setSelected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
setFeeRadioButtonState();
|
setFeeRadioButtonState();
|
||||||
|
@ -229,7 +253,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
|
|
||||||
private void addInfoPane() {
|
private void addInfoPane() {
|
||||||
Contract contract = dispute.getContract();
|
Contract contract = dispute.getContract();
|
||||||
addTitledGroupBg(gridPane, ++rowIndex, 12, "Summary");
|
addTitledGroupBg(gridPane, ++rowIndex, 16, "Summary");
|
||||||
addLabelTextField(gridPane, rowIndex, "Trade ID:", dispute.getShortTradeId(), Layout.FIRST_ROW_DISTANCE);
|
addLabelTextField(gridPane, rowIndex, "Trade ID:", dispute.getShortTradeId(), Layout.FIRST_ROW_DISTANCE);
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Ticket opening date:", formatter.formatDateTime(dispute.getOpeningDate()));
|
addLabelTextField(gridPane, ++rowIndex, "Ticket opening date:", formatter.formatDateTime(dispute.getOpeningDate()));
|
||||||
if (dispute.isDisputeOpenerIsOfferer()) {
|
if (dispute.isDisputeOpenerIsOfferer()) {
|
||||||
|
@ -243,7 +267,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
else
|
else
|
||||||
role = "BTC Seller/taker";
|
role = "BTC Seller/taker";
|
||||||
}
|
}
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Traders role:", role);
|
addLabelTextField(gridPane, ++rowIndex, "Trader's role:", role);
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(contract.getTradeAmount()));
|
addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(contract.getTradeAmount()));
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Trade price:", formatter.formatPrice(contract.getTradePrice()));
|
addLabelTextField(gridPane, ++rowIndex, "Trade price:", formatter.formatPrice(contract.getTradePrice()));
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Trade volume:", formatter.formatVolumeWithCode(new ExchangeRate(contract.getTradePrice()).coinToFiat(contract.getTradeAmount())));
|
addLabelTextField(gridPane, ++rowIndex, "Trade volume:", formatter.formatVolumeWithCode(new ExchangeRate(contract.getTradePrice()).coinToFiat(contract.getTradeAmount())));
|
||||||
|
@ -277,18 +301,20 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
buyerIsWinnerRadioButton = new RadioButton("BTC buyer gets trade amount payout");
|
buyerIsWinnerRadioButton = new RadioButton("BTC buyer gets trade amount payout");
|
||||||
sellerIsWinnerRadioButton = new RadioButton("BTC seller gets trade amount payout");
|
sellerIsWinnerRadioButton = new RadioButton("BTC seller gets trade amount payout");
|
||||||
shareRadioButton = new RadioButton("Both gets half trade amount payout");
|
shareRadioButton = new RadioButton("Both gets half trade amount payout");
|
||||||
|
customRadioButton = new RadioButton("Custom payout");
|
||||||
VBox radioButtonPane = new VBox();
|
VBox radioButtonPane = new VBox();
|
||||||
radioButtonPane.setSpacing(20);
|
radioButtonPane.setSpacing(10);
|
||||||
radioButtonPane.getChildren().addAll(buyerIsWinnerRadioButton, sellerIsWinnerRadioButton, shareRadioButton);
|
radioButtonPane.getChildren().addAll(buyerIsWinnerRadioButton, sellerIsWinnerRadioButton, shareRadioButton, customRadioButton);
|
||||||
GridPane.setRowIndex(radioButtonPane, rowIndex);
|
GridPane.setRowIndex(radioButtonPane, rowIndex);
|
||||||
GridPane.setColumnIndex(radioButtonPane, 1);
|
GridPane.setColumnIndex(radioButtonPane, 1);
|
||||||
GridPane.setMargin(radioButtonPane, new Insets(10, 0, 10, 0));
|
GridPane.setMargin(radioButtonPane, new Insets(10, 0, 0, 0));
|
||||||
gridPane.getChildren().add(radioButtonPane);
|
gridPane.getChildren().add(radioButtonPane);
|
||||||
|
|
||||||
tradeAmountToggleGroup = new ToggleGroup();
|
tradeAmountToggleGroup = new ToggleGroup();
|
||||||
buyerIsWinnerRadioButton.setToggleGroup(tradeAmountToggleGroup);
|
buyerIsWinnerRadioButton.setToggleGroup(tradeAmountToggleGroup);
|
||||||
sellerIsWinnerRadioButton.setToggleGroup(tradeAmountToggleGroup);
|
sellerIsWinnerRadioButton.setToggleGroup(tradeAmountToggleGroup);
|
||||||
shareRadioButton.setToggleGroup(tradeAmountToggleGroup);
|
shareRadioButton.setToggleGroup(tradeAmountToggleGroup);
|
||||||
|
customRadioButton.setToggleGroup(tradeAmountToggleGroup);
|
||||||
|
|
||||||
shareRadioButtonSelectedListener = (observable, oldValue, newValue) -> {
|
shareRadioButtonSelectedListener = (observable, oldValue, newValue) -> {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
|
@ -304,6 +330,91 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
loserPaysFeeRadioButton.setDisable(newValue);
|
loserPaysFeeRadioButton.setDisable(newValue);
|
||||||
};
|
};
|
||||||
shareRadioButton.selectedProperty().addListener(shareRadioButtonSelectedListener);
|
shareRadioButton.selectedProperty().addListener(shareRadioButtonSelectedListener);
|
||||||
|
|
||||||
|
buyerPayoutAmountListener = (observable1, oldValue1, newValue1) -> applyCustomAmounts(buyerPayoutAmountInputTextField);
|
||||||
|
sellerPayoutAmountListener = (observable1, oldValue1, newValue1) -> applyCustomAmounts(sellerPayoutAmountInputTextField);
|
||||||
|
arbitratorPayoutAmountListener = (observable1, oldValue1, newValue1) -> applyCustomAmounts(arbitratorPayoutAmountInputTextField);
|
||||||
|
|
||||||
|
customRadioButtonSelectedListener = (observable, oldValue, newValue) -> {
|
||||||
|
buyerPayoutAmountInputTextField.setEditable(newValue);
|
||||||
|
sellerPayoutAmountInputTextField.setEditable(newValue);
|
||||||
|
arbitratorPayoutAmountInputTextField.setEditable(newValue);
|
||||||
|
|
||||||
|
loserPaysFeeRadioButton.setDisable(newValue);
|
||||||
|
splitFeeRadioButton.setDisable(newValue);
|
||||||
|
waiveFeeRadioButton.setDisable(newValue);
|
||||||
|
|
||||||
|
if (newValue) {
|
||||||
|
buyerPayoutAmountInputTextField.textProperty().addListener(buyerPayoutAmountListener);
|
||||||
|
sellerPayoutAmountInputTextField.textProperty().addListener(sellerPayoutAmountListener);
|
||||||
|
arbitratorPayoutAmountInputTextField.textProperty().addListener(arbitratorPayoutAmountListener);
|
||||||
|
} else {
|
||||||
|
removePayoutAmountListeners();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
customRadioButton.selectedProperty().addListener(customRadioButtonSelectedListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removePayoutAmountListeners() {
|
||||||
|
if (buyerPayoutAmountInputTextField != null && buyerPayoutAmountListener != null)
|
||||||
|
buyerPayoutAmountInputTextField.textProperty().removeListener(buyerPayoutAmountListener);
|
||||||
|
|
||||||
|
if (sellerPayoutAmountInputTextField != null && sellerPayoutAmountListener != null)
|
||||||
|
sellerPayoutAmountInputTextField.textProperty().removeListener(sellerPayoutAmountListener);
|
||||||
|
|
||||||
|
if (arbitratorPayoutAmountInputTextField != null && arbitratorPayoutAmountListener != null)
|
||||||
|
arbitratorPayoutAmountInputTextField.textProperty().removeListener(arbitratorPayoutAmountListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPayoutAmountValid() {
|
||||||
|
Coin buyerAmount = formatter.parseToCoin(buyerPayoutAmountInputTextField.getText());
|
||||||
|
Coin sellerAmount = formatter.parseToCoin(sellerPayoutAmountInputTextField.getText());
|
||||||
|
Coin arbitratorAmount = formatter.parseToCoin(arbitratorPayoutAmountInputTextField.getText());
|
||||||
|
Coin securityDeposit = FeePolicy.getSecurityDeposit();
|
||||||
|
Coin tradeAmount = dispute.getContract().getTradeAmount();
|
||||||
|
Coin available = tradeAmount.add(securityDeposit).add(securityDeposit);
|
||||||
|
Coin totalAmount = buyerAmount.add(sellerAmount).add(arbitratorAmount);
|
||||||
|
return (totalAmount.compareTo(available) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyCustomAmounts(InputTextField inputTextField) {
|
||||||
|
Coin securityDeposit = FeePolicy.getSecurityDeposit();
|
||||||
|
Coin tradeAmount = dispute.getContract().getTradeAmount();
|
||||||
|
|
||||||
|
Coin buyerAmount = formatter.parseToCoin(buyerPayoutAmountInputTextField.getText());
|
||||||
|
Coin sellerAmount = formatter.parseToCoin(sellerPayoutAmountInputTextField.getText());
|
||||||
|
Coin arbitratorAmount = formatter.parseToCoin(arbitratorPayoutAmountInputTextField.getText());
|
||||||
|
|
||||||
|
Coin available = tradeAmount.add(securityDeposit).add(securityDeposit);
|
||||||
|
Coin totalAmount = buyerAmount.add(sellerAmount).add(arbitratorAmount);
|
||||||
|
|
||||||
|
if (totalAmount.compareTo(available) > 0) {
|
||||||
|
new Popup<>().warning("Amount entered exceeds available amount of " + available.toFriendlyString() + ".\n" +
|
||||||
|
"We adjust this input field to the max possible value.")
|
||||||
|
.show();
|
||||||
|
|
||||||
|
if (inputTextField == buyerPayoutAmountInputTextField) {
|
||||||
|
buyerAmount = available.subtract(sellerAmount).subtract(arbitratorAmount);
|
||||||
|
inputTextField.setText(formatter.formatCoin(buyerAmount));
|
||||||
|
} else if (inputTextField == sellerPayoutAmountInputTextField) {
|
||||||
|
sellerAmount = available.subtract(buyerAmount).subtract(arbitratorAmount);
|
||||||
|
inputTextField.setText(formatter.formatCoin(sellerAmount));
|
||||||
|
} else if (inputTextField == arbitratorPayoutAmountInputTextField) {
|
||||||
|
arbitratorAmount = available.subtract(sellerAmount).subtract(buyerAmount);
|
||||||
|
inputTextField.setText(formatter.formatCoin(arbitratorAmount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disputeResult.setBuyerPayoutAmount(buyerAmount);
|
||||||
|
disputeResult.setSellerPayoutAmount(sellerAmount);
|
||||||
|
disputeResult.setArbitratorPayoutAmount(arbitratorAmount);
|
||||||
|
|
||||||
|
if (buyerAmount.compareTo(sellerAmount) == 0)
|
||||||
|
disputeResult.setWinner(DisputeResult.Winner.STALE_MATE);
|
||||||
|
else if (buyerAmount.compareTo(sellerAmount) > 0)
|
||||||
|
disputeResult.setWinner(DisputeResult.Winner.BUYER);
|
||||||
|
else
|
||||||
|
disputeResult.setWinner(DisputeResult.Winner.SELLER);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFeeControls() {
|
private void addFeeControls() {
|
||||||
|
@ -340,6 +451,19 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
feeToggleGroup.selectToggle(waiveFeeRadioButton);
|
feeToggleGroup.selectToggle(waiveFeeRadioButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addPayoutAmountTextFields() {
|
||||||
|
buyerPayoutAmountInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Buyer's payout amount:").second;
|
||||||
|
buyerPayoutAmountInputTextField.setEditable(false);
|
||||||
|
|
||||||
|
sellerPayoutAmountInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Seller's payout amount:").second;
|
||||||
|
sellerPayoutAmountInputTextField.setEditable(false);
|
||||||
|
|
||||||
|
arbitratorPayoutAmountInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Arbitrator's payout amount:").second;
|
||||||
|
arbitratorPayoutAmountInputTextField.setEditable(false);
|
||||||
|
|
||||||
|
isLoserPublisherCheckBox = addLabelCheckBox(gridPane, ++rowIndex, "Use loser as publisher:").second;
|
||||||
|
}
|
||||||
|
|
||||||
private void setFeeRadioButtonState() {
|
private void setFeeRadioButtonState() {
|
||||||
switch (disputeResult.getDisputeFeePolicy()) {
|
switch (disputeResult.getDisputeFeePolicy()) {
|
||||||
case LOSER:
|
case LOSER:
|
||||||
|
@ -432,6 +556,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
summaryNotesTextArea = new TextArea();
|
summaryNotesTextArea = new TextArea();
|
||||||
summaryNotesTextArea.setPromptText("Add summary notes");
|
summaryNotesTextArea.setPromptText("Add summary notes");
|
||||||
summaryNotesTextArea.setWrapText(true);
|
summaryNotesTextArea.setWrapText(true);
|
||||||
|
summaryNotesTextArea.setPrefHeight(50);
|
||||||
summaryNotesTextArea.textProperty().bindBidirectional(disputeResult.summaryNotesProperty());
|
summaryNotesTextArea.textProperty().bindBidirectional(disputeResult.summaryNotesProperty());
|
||||||
GridPane.setRowIndex(summaryNotesTextArea, rowIndex);
|
GridPane.setRowIndex(summaryNotesTextArea, rowIndex);
|
||||||
GridPane.setColumnIndex(summaryNotesTextArea, 1);
|
GridPane.setColumnIndex(summaryNotesTextArea, 1);
|
||||||
|
@ -444,9 +569,13 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
closeTicketButton.disableProperty().bind(Bindings.createBooleanBinding(
|
closeTicketButton.disableProperty().bind(Bindings.createBooleanBinding(
|
||||||
() -> tradeAmountToggleGroup.getSelectedToggle() == null
|
() -> tradeAmountToggleGroup.getSelectedToggle() == null
|
||||||
|| summaryNotesTextArea.getText() == null
|
|| summaryNotesTextArea.getText() == null
|
||||||
|| summaryNotesTextArea.getText().length() == 0,
|
|| summaryNotesTextArea.getText().length() == 0
|
||||||
|
|| !isPayoutAmountValid(),
|
||||||
tradeAmountToggleGroup.selectedToggleProperty(),
|
tradeAmountToggleGroup.selectedToggleProperty(),
|
||||||
summaryNotesTextArea.textProperty()));
|
summaryNotesTextArea.textProperty(),
|
||||||
|
buyerPayoutAmountInputTextField.textProperty(),
|
||||||
|
sellerPayoutAmountInputTextField.textProperty(),
|
||||||
|
arbitratorPayoutAmountInputTextField.textProperty()));
|
||||||
|
|
||||||
Button cancelButton = tuple.second;
|
Button cancelButton = tuple.second;
|
||||||
|
|
||||||
|
@ -457,7 +586,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
AddressEntry arbitratorAddressEntry = walletService.getOrCreateAddressEntry(AddressEntry.Context.ARBITRATOR);
|
AddressEntry arbitratorAddressEntry = walletService.getOrCreateAddressEntry(AddressEntry.Context.ARBITRATOR);
|
||||||
disputeResult.setArbitratorAddressAsString(arbitratorAddressEntry.getAddressString());
|
disputeResult.setArbitratorAddressAsString(arbitratorAddressEntry.getAddressString());
|
||||||
disputeResult.setArbitratorPubKey(arbitratorAddressEntry.getPubKey());
|
disputeResult.setArbitratorPubKey(arbitratorAddressEntry.getPubKey());
|
||||||
|
|
||||||
/* byte[] depositTxSerialized,
|
/* byte[] depositTxSerialized,
|
||||||
Coin buyerPayoutAmount,
|
Coin buyerPayoutAmount,
|
||||||
Coin sellerPayoutAmount,
|
Coin sellerPayoutAmount,
|
||||||
|
@ -486,6 +615,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
closeTicketButton.disableProperty().unbind();
|
closeTicketButton.disableProperty().unbind();
|
||||||
dispute.setDisputeResult(disputeResult);
|
dispute.setDisputeResult(disputeResult);
|
||||||
|
|
||||||
|
disputeResult.setLoserIsPublisher(isLoserPublisherCheckBox.isSelected());
|
||||||
disputeResult.setCloseDate(new Date());
|
disputeResult.setCloseDate(new Date());
|
||||||
String text = "Ticket closed on " + formatter.formatDateTime(disputeResult.getCloseDate()) +
|
String text = "Ticket closed on " + formatter.formatDateTime(disputeResult.getCloseDate()) +
|
||||||
"\n\nSummary:" +
|
"\n\nSummary:" +
|
||||||
|
@ -494,7 +624,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
"\n" + role + " did screencast or video: " + formatter.booleanToYesNo(disputeResult.screenCastProperty().get()) +
|
"\n" + role + " did screencast or video: " + formatter.booleanToYesNo(disputeResult.screenCastProperty().get()) +
|
||||||
"\nPayout amount for BTC buyer: " + formatter.formatCoinWithCode(disputeResult.getBuyerPayoutAmount()) +
|
"\nPayout amount for BTC buyer: " + formatter.formatCoinWithCode(disputeResult.getBuyerPayoutAmount()) +
|
||||||
"\nPayout amount for BTC seller: " + formatter.formatCoinWithCode(disputeResult.getSellerPayoutAmount()) +
|
"\nPayout amount for BTC seller: " + formatter.formatCoinWithCode(disputeResult.getSellerPayoutAmount()) +
|
||||||
"\nArbitrators dispute fee: " + formatter.formatCoinWithCode(disputeResult.getArbitratorPayoutAmount()) +
|
"\nArbitrator's dispute fee: " + formatter.formatCoinWithCode(disputeResult.getArbitratorPayoutAmount()) +
|
||||||
"\n\nSummary notes:\n" + disputeResult.summaryNotesProperty().get();
|
"\n\nSummary notes:\n" + disputeResult.summaryNotesProperty().get();
|
||||||
|
|
||||||
dispute.setIsClosed(true);
|
dispute.setIsClosed(true);
|
||||||
|
@ -528,10 +658,12 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void applyPayoutAmounts(DisputeResult.DisputeFeePolicy feePayment, Toggle selectedTradeAmountToggle) {
|
private void applyPayoutAmounts(DisputeResult.DisputeFeePolicy feePayment, Toggle selectedTradeAmountToggle) {
|
||||||
calculatePayoutAmounts(feePayment);
|
if (selectedTradeAmountToggle != customRadioButton) {
|
||||||
if (selectedTradeAmountToggle != null) {
|
calculatePayoutAmounts(feePayment);
|
||||||
applyPayoutAmountsToDisputeResult(selectedTradeAmountToggle);
|
if (selectedTradeAmountToggle != null) {
|
||||||
applyTradeAmountRadioButtonStates();
|
applyPayoutAmountsToDisputeResult(selectedTradeAmountToggle);
|
||||||
|
applyTradeAmountRadioButtonStates();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,6 +690,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
arbitratorPayoutAmount = refund;
|
arbitratorPayoutAmount = refund;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
winnerPayoutAmount = contract.getTradeAmount().add(winnerRefund);
|
winnerPayoutAmount = contract.getTradeAmount().add(winnerRefund);
|
||||||
loserPayoutAmount = loserRefund;
|
loserPayoutAmount = loserRefund;
|
||||||
stalematePayoutAmount = contract.getTradeAmount().divide(2L).add(winnerRefund);
|
stalematePayoutAmount = contract.getTradeAmount().divide(2L).add(winnerRefund);
|
||||||
|
@ -568,31 +701,44 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
disputeResult.setBuyerPayoutAmount(winnerPayoutAmount);
|
disputeResult.setBuyerPayoutAmount(winnerPayoutAmount);
|
||||||
disputeResult.setSellerPayoutAmount(loserPayoutAmount);
|
disputeResult.setSellerPayoutAmount(loserPayoutAmount);
|
||||||
disputeResult.setWinner(DisputeResult.Winner.BUYER);
|
disputeResult.setWinner(DisputeResult.Winner.BUYER);
|
||||||
|
|
||||||
|
buyerPayoutAmountInputTextField.setText(formatter.formatCoin(winnerPayoutAmount));
|
||||||
|
sellerPayoutAmountInputTextField.setText(formatter.formatCoin(loserPayoutAmount));
|
||||||
} else if (selectedTradeAmountToggle == sellerIsWinnerRadioButton) {
|
} else if (selectedTradeAmountToggle == sellerIsWinnerRadioButton) {
|
||||||
disputeResult.setBuyerPayoutAmount(loserPayoutAmount);
|
disputeResult.setBuyerPayoutAmount(loserPayoutAmount);
|
||||||
disputeResult.setSellerPayoutAmount(winnerPayoutAmount);
|
disputeResult.setSellerPayoutAmount(winnerPayoutAmount);
|
||||||
disputeResult.setWinner(DisputeResult.Winner.SELLER);
|
disputeResult.setWinner(DisputeResult.Winner.SELLER);
|
||||||
|
|
||||||
|
buyerPayoutAmountInputTextField.setText(formatter.formatCoin(loserPayoutAmount));
|
||||||
|
sellerPayoutAmountInputTextField.setText(formatter.formatCoin(winnerPayoutAmount));
|
||||||
} else if (selectedTradeAmountToggle == shareRadioButton) {
|
} else if (selectedTradeAmountToggle == shareRadioButton) {
|
||||||
disputeResult.setBuyerPayoutAmount(stalematePayoutAmount);
|
disputeResult.setBuyerPayoutAmount(stalematePayoutAmount);
|
||||||
disputeResult.setSellerPayoutAmount(stalematePayoutAmount);
|
disputeResult.setSellerPayoutAmount(stalematePayoutAmount);
|
||||||
disputeResult.setWinner(DisputeResult.Winner.STALE_MATE);
|
disputeResult.setWinner(DisputeResult.Winner.STALE_MATE);
|
||||||
|
|
||||||
|
buyerPayoutAmountInputTextField.setText(formatter.formatCoin(stalematePayoutAmount));
|
||||||
|
sellerPayoutAmountInputTextField.setText(formatter.formatCoin(stalematePayoutAmount));
|
||||||
}
|
}
|
||||||
disputeResult.setArbitratorPayoutAmount(arbitratorPayoutAmount);
|
disputeResult.setArbitratorPayoutAmount(arbitratorPayoutAmount);
|
||||||
if (disputeResult.getBuyerPayoutAmount() != null) {
|
arbitratorPayoutAmountInputTextField.setText(formatter.formatCoin(arbitratorPayoutAmount));
|
||||||
log.debug("buyerPayoutAmount " + disputeResult.getBuyerPayoutAmount().toFriendlyString());
|
|
||||||
log.debug("sellerPayoutAmount " + disputeResult.getSellerPayoutAmount().toFriendlyString());
|
|
||||||
log.debug("arbitratorPayoutAmount " + disputeResult.getArbitratorPayoutAmount().toFriendlyString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyTradeAmountRadioButtonStates() {
|
private void applyTradeAmountRadioButtonStates() {
|
||||||
if (disputeResult.getBuyerPayoutAmount() != null) {
|
Coin buyerPayoutAmount = disputeResult.getBuyerPayoutAmount();
|
||||||
if (disputeResult.getBuyerPayoutAmount().equals(winnerPayoutAmount) && disputeResult.getSellerPayoutAmount().equals(loserPayoutAmount))
|
Coin sellerPayoutAmount = disputeResult.getSellerPayoutAmount();
|
||||||
buyerIsWinnerRadioButton.setSelected(true);
|
|
||||||
else if (disputeResult.getSellerPayoutAmount().equals(winnerPayoutAmount) && disputeResult.getBuyerPayoutAmount().equals(loserPayoutAmount))
|
buyerPayoutAmountInputTextField.setText(formatter.formatCoin(buyerPayoutAmount));
|
||||||
sellerIsWinnerRadioButton.setSelected(true);
|
sellerPayoutAmountInputTextField.setText(formatter.formatCoin(sellerPayoutAmount));
|
||||||
else
|
arbitratorPayoutAmountInputTextField.setText(formatter.formatCoin(disputeResult.getArbitratorPayoutAmount()));
|
||||||
shareRadioButton.setSelected(true); // there might be a not perfect split if only the trade amount is split but fees are not split
|
|
||||||
|
if (buyerPayoutAmount.equals(winnerPayoutAmount) && sellerPayoutAmount.equals(loserPayoutAmount)) {
|
||||||
|
buyerIsWinnerRadioButton.setSelected(true);
|
||||||
|
} else if (sellerPayoutAmount.equals(winnerPayoutAmount) && buyerPayoutAmount.equals(loserPayoutAmount)) {
|
||||||
|
sellerIsWinnerRadioButton.setSelected(true);
|
||||||
|
} else if (sellerPayoutAmount.equals(buyerPayoutAmount)) {
|
||||||
|
shareRadioButton.setSelected(true);
|
||||||
|
} else {
|
||||||
|
customRadioButton.setSelected(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static io.bitsquare.gui.util.FormBuilder.addLabelInputTextField;
|
import static io.bitsquare.gui.util.FormBuilder.addLabelInputTextField;
|
||||||
|
@ -113,7 +112,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
|
||||||
InputTextField keyInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Private key to unlock:", 10).second;
|
InputTextField keyInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Private key to unlock:", 10).second;
|
||||||
InputTextField offerIdsInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Filtered offers (comma sep.):").second;
|
InputTextField offerIdsInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Filtered offers (comma sep.):").second;
|
||||||
InputTextField nodesInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Filtered onion addresses (comma sep.):").second;
|
InputTextField nodesInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Filtered onion addresses (comma sep.):").second;
|
||||||
InputTextField paymentAccountFilterInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Filtered payment account data:\nFormat: comma sep. list of [payment method id | data field | value]").second;
|
InputTextField paymentAccountFilterInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Filtered trading account data:\nFormat: comma sep. list of [payment method id | data field | value]").second;
|
||||||
GridPane.setHalignment(paymentAccountFilterInputTextField, HPos.RIGHT);
|
GridPane.setHalignment(paymentAccountFilterInputTextField, HPos.RIGHT);
|
||||||
|
|
||||||
final Filter filter = filterManager.getDevelopersFilter();
|
final Filter filter = filterManager.getDevelopersFilter();
|
||||||
|
@ -137,16 +136,16 @@ public class FilterWindow extends Overlay<FilterWindow> {
|
||||||
}
|
}
|
||||||
sendButton = new Button("Add filter");
|
sendButton = new Button("Add filter");
|
||||||
sendButton.setOnAction(e -> {
|
sendButton.setOnAction(e -> {
|
||||||
List<String> offerIds = new ArrayList<>();
|
ArrayList<String> offerIds = new ArrayList<>();
|
||||||
List<String> nodes = new ArrayList<>();
|
ArrayList<String> nodes = new ArrayList<>();
|
||||||
List<PaymentAccountFilter> paymentAccountFilters = new ArrayList<>();
|
ArrayList<PaymentAccountFilter> paymentAccountFilters = new ArrayList<>();
|
||||||
|
|
||||||
if (!offerIdsInputTextField.getText().isEmpty())
|
if (!offerIdsInputTextField.getText().isEmpty())
|
||||||
offerIds = Arrays.asList(offerIdsInputTextField.getText().replace(" ", "").replace(", ", ",").split(","));
|
offerIds = new ArrayList<>(Arrays.asList(offerIdsInputTextField.getText().replace(" ", "").replace(", ", ",").split(",")));
|
||||||
if (!nodesInputTextField.getText().isEmpty())
|
if (!nodesInputTextField.getText().isEmpty())
|
||||||
nodes = Arrays.asList(nodesInputTextField.getText().replace(":9999", "").replace(".onion", "").replace(" ", "").replace(", ", ",").split(","));
|
nodes = new ArrayList<>(Arrays.asList(nodesInputTextField.getText().replace(":9999", "").replace(".onion", "").replace(" ", "").replace(", ", ",").split(",")));
|
||||||
if (!paymentAccountFilterInputTextField.getText().isEmpty())
|
if (!paymentAccountFilterInputTextField.getText().isEmpty())
|
||||||
paymentAccountFilters = Arrays.asList(paymentAccountFilterInputTextField.getText().replace(", ", ",").split(","))
|
paymentAccountFilters = new ArrayList<>(Arrays.asList(paymentAccountFilterInputTextField.getText().replace(", ", ",").split(","))
|
||||||
.stream().map(item -> {
|
.stream().map(item -> {
|
||||||
String[] list = item.split("\\|");
|
String[] list = item.split("\\|");
|
||||||
if (list.length == 3)
|
if (list.length == 3)
|
||||||
|
@ -154,7 +153,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
|
||||||
else
|
else
|
||||||
return new PaymentAccountFilter("", "", "");
|
return new PaymentAccountFilter("", "", "");
|
||||||
})
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
if (sendFilterMessageHandler.handle(new Filter(offerIds, nodes, paymentAccountFilters), keyInputTextField.getText()))
|
if (sendFilterMessageHandler.handle(new Filter(offerIds, nodes, paymentAccountFilters), keyInputTextField.getText()))
|
||||||
hide();
|
hide();
|
||||||
|
|
|
@ -208,14 +208,14 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
||||||
final boolean isNationalBanks = paymentMethod.equals(PaymentMethod.NATIONAL_BANK);
|
final boolean isNationalBanks = paymentMethod.equals(PaymentMethod.NATIONAL_BANK);
|
||||||
final boolean isSepa = paymentMethod.equals(PaymentMethod.SEPA);
|
final boolean isSepa = paymentMethod.equals(PaymentMethod.SEPA);
|
||||||
if (offer.isMyOffer(keyRing) && offererPaymentAccountId != null && paymentAccount != null) {
|
if (offer.isMyOffer(keyRing) && offererPaymentAccountId != null && paymentAccount != null) {
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Payment account:", paymentAccount.getAccountName());
|
addLabelTextField(gridPane, ++rowIndex, "My trading account:", paymentAccount.getAccountName());
|
||||||
} else {
|
} else {
|
||||||
final String method = BSResources.get(paymentMethod.getId());
|
final String method = BSResources.get(paymentMethod.getId());
|
||||||
if (isNationalBanks || isSpecificBanks || isSepa) {
|
if (isNationalBanks || isSpecificBanks || isSepa) {
|
||||||
if (BankUtil.isBankIdRequired(offer.getCountryCode()))
|
if (BankUtil.isBankIdRequired(offer.getCountryCode()))
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Payment method (offerers bank ID):", method + bankId);
|
addLabelTextField(gridPane, ++rowIndex, "Payment method (offerer's bank ID):", method + bankId);
|
||||||
else if (BankUtil.isBankNameRequired(offer.getCountryCode()))
|
else if (BankUtil.isBankNameRequired(offer.getCountryCode()))
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Payment method (offerers bank name):", method + bankId);
|
addLabelTextField(gridPane, ++rowIndex, "Payment method (offerer's bank name):", method + bankId);
|
||||||
} else {
|
} else {
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Payment method:", method);
|
addLabelTextField(gridPane, ++rowIndex, "Payment method:", method);
|
||||||
}
|
}
|
||||||
|
@ -262,12 +262,12 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
||||||
|
|
||||||
addTitledGroupBg(gridPane, ++rowIndex, rows, "Details", Layout.GROUP_DISTANCE);
|
addTitledGroupBg(gridPane, ++rowIndex, rows, "Details", Layout.GROUP_DISTANCE);
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, rowIndex, "Offer ID:", offer.getId(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
addLabelTextFieldWithCopyIcon(gridPane, rowIndex, "Offer ID:", offer.getId(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Offerers onion address:", offer.getOffererNodeAddress().getFullAddress());
|
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Offerer's onion address:", offer.getOffererNodeAddress().getFullAddress());
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Creation date:", formatter.formatDateTime(offer.getDate()));
|
addLabelTextField(gridPane, ++rowIndex, "Creation date:", formatter.formatDateTime(offer.getDate()));
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Security deposit:", formatter.formatCoinWithCode(FeePolicy.getSecurityDeposit()));
|
addLabelTextField(gridPane, ++rowIndex, "Security deposit:", formatter.formatCoinWithCode(FeePolicy.getSecurityDeposit()));
|
||||||
|
|
||||||
if (paymentMethodCountryCode != null)
|
if (paymentMethodCountryCode != null)
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Offerers country of bank:",
|
addLabelTextField(gridPane, ++rowIndex, "Offerer's country of bank:",
|
||||||
CountryUtil.getNameAndCode(paymentMethodCountryCode));
|
CountryUtil.getNameAndCode(paymentMethodCountryCode));
|
||||||
|
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Accepted arbitrators:", formatter.arbitratorAddressesToString(offer.getArbitratorNodeAddresses()));
|
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Accepted arbitrators:", formatter.arbitratorAddressesToString(offer.getArbitratorNodeAddresses()));
|
||||||
|
@ -297,8 +297,8 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
||||||
boolean isBuyOffer = offer.getDirection() == Offer.Direction.BUY;
|
boolean isBuyOffer = offer.getDirection() == Offer.Direction.BUY;
|
||||||
boolean isBuyerRole = isPlaceOffer ? isBuyOffer : !isBuyOffer;
|
boolean isBuyerRole = isPlaceOffer ? isBuyOffer : !isBuyOffer;
|
||||||
|
|
||||||
String placeOfferButtonText = isBuyerRole ? "Confirm offer for buying bitcoin" : "Confirm offer for selling bitcoin";
|
String placeOfferButtonText = isBuyerRole ? "Confirm offer to buy bitcoin" : "Confirm offer to sell bitcoin";
|
||||||
String takeOfferButtonText = isBuyerRole ? "Confirm offer for buying bitcoin" : "Confirm offer for selling bitcoin";
|
String takeOfferButtonText = isBuyerRole ? "Confirm offer to buy bitcoin" : "Confirm offer to sell bitcoin";
|
||||||
|
|
||||||
ImageView iconView = new ImageView();
|
ImageView iconView = new ImageView();
|
||||||
iconView.setId(isBuyerRole ? "image-buy-white" : "image-sell-white");
|
iconView.setId(isBuyerRole ? "image-buy-white" : "image-sell-white");
|
||||||
|
|
|
@ -112,7 +112,7 @@ public class SendAlertMessageWindow extends Overlay<SendAlertMessageWindow> {
|
||||||
CheckBox isUpdateCheckBox = addLabelCheckBox(gridPane, ++rowIndex, "Is update notification:", "").second;
|
CheckBox isUpdateCheckBox = addLabelCheckBox(gridPane, ++rowIndex, "Is update notification:", "").second;
|
||||||
isUpdateCheckBox.setSelected(true);
|
isUpdateCheckBox.setSelected(true);
|
||||||
|
|
||||||
InputTextField versionInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "New version nr.:").second;
|
InputTextField versionInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "New version no.:").second;
|
||||||
versionInputTextField.disableProperty().bind(isUpdateCheckBox.selectedProperty().not());
|
versionInputTextField.disableProperty().bind(isUpdateCheckBox.selectedProperty().not());
|
||||||
|
|
||||||
sendButton = new Button("Send notification");
|
sendButton = new Button("Send notification");
|
||||||
|
|
|
@ -215,7 +215,7 @@ public class WalletPasswordWindow extends Overlay<WalletPasswordWindow> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
log.error("wallet.getKeyCrypter() is null, than must not happen.");
|
log.error("wallet.getKeyCrypter() is null, that must not happen.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<TableColumn text="Amount in BTC" fx:id="amountColumn" minWidth="130"/>
|
<TableColumn text="Amount in BTC" fx:id="amountColumn" minWidth="130"/>
|
||||||
<TableColumn text="Amount" fx:id="volumeColumn" minWidth="130"/>
|
<TableColumn text="Amount" fx:id="volumeColumn" minWidth="130"/>
|
||||||
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="80"/>
|
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="80"/>
|
||||||
<TableColumn text="State" fx:id="stateColumn" minWidth="80"/>
|
<TableColumn text="Status" fx:id="stateColumn" minWidth="80"/>
|
||||||
<TableColumn text="" fx:id="avatarColumn" minWidth="40" maxWidth="40"/>
|
<TableColumn text="" fx:id="avatarColumn" minWidth="40" maxWidth="40"/>
|
||||||
</columns>
|
</columns>
|
||||||
</TableView>
|
</TableView>
|
||||||
|
|
|
@ -29,10 +29,10 @@
|
||||||
<TableView fx:id="tableView" VBox.vgrow="ALWAYS">
|
<TableView fx:id="tableView" VBox.vgrow="ALWAYS">
|
||||||
<columns>
|
<columns>
|
||||||
<TableColumn text="Offer ID" fx:id="offerIdColumn" minWidth="120" maxWidth="130"/>
|
<TableColumn text="Offer ID" fx:id="offerIdColumn" minWidth="120" maxWidth="130"/>
|
||||||
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="170" maxWidth="190"/>
|
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="180" maxWidth="190"/>
|
||||||
<TableColumn text="Market" fx:id="marketColumn" minWidth="100"/>
|
<TableColumn text="Market" fx:id="marketColumn" minWidth="100"/>
|
||||||
<TableColumn text="Price" fx:id="priceColumn" minWidth="160"/>
|
<TableColumn text="Price" fx:id="priceColumn" minWidth="160"/>
|
||||||
<TableColumn text="Amount in BTC (min - max)" fx:id="amountColumn" minWidth="220"/>
|
<TableColumn text="BTC (min - max)" fx:id="amountColumn" minWidth="160"/>
|
||||||
<TableColumn text="Amount (min - max)" fx:id="volumeColumn" minWidth="180"/>
|
<TableColumn text="Amount (min - max)" fx:id="volumeColumn" minWidth="180"/>
|
||||||
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="100"/>
|
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="100"/>
|
||||||
<TableColumn text="" fx:id="removeItemColumn" minWidth="120" maxWidth="120" sortable="false"/>
|
<TableColumn text="" fx:id="removeItemColumn" minWidth="120" maxWidth="120" sortable="false"/>
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package io.bitsquare.gui.main.portfolio.openoffer;
|
package io.bitsquare.gui.main.portfolio.openoffer;
|
||||||
|
|
||||||
|
import io.bitsquare.btc.FeePolicy;
|
||||||
import io.bitsquare.gui.Navigation;
|
import io.bitsquare.gui.Navigation;
|
||||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||||
import io.bitsquare.gui.common.view.FxmlView;
|
import io.bitsquare.gui.common.view.FxmlView;
|
||||||
|
@ -111,7 +112,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
|
||||||
String key = "RemoveOfferWarning";
|
String key = "RemoveOfferWarning";
|
||||||
if (preferences.showAgain(key))
|
if (preferences.showAgain(key))
|
||||||
new Popup().warning("Are you sure you want to remove that offer?\n" +
|
new Popup().warning("Are you sure you want to remove that offer?\n" +
|
||||||
"The offer fee you have paid will be lost if you remove that offer.")
|
"The offer fee of " + model.formatter.formatCoinWithCode(FeePolicy.getCreateOfferFee()) + " will be lost if you remove that offer.")
|
||||||
.actionButtonText("Remove offer")
|
.actionButtonText("Remove offer")
|
||||||
.onAction(() -> doRemoveOpenOffer(openOffer))
|
.onAction(() -> doRemoveOpenOffer(openOffer))
|
||||||
.closeButtonText("Don't remove the offer")
|
.closeButtonText("Don't remove the offer")
|
||||||
|
|
|
@ -31,18 +31,17 @@ import org.bitcoinj.utils.Fiat;
|
||||||
|
|
||||||
class OpenOffersViewModel extends ActivatableWithDataModel<OpenOffersDataModel> implements ViewModel {
|
class OpenOffersViewModel extends ActivatableWithDataModel<OpenOffersDataModel> implements ViewModel {
|
||||||
private final P2PService p2PService;
|
private final P2PService p2PService;
|
||||||
private final BSFormatter formatter;
|
final BSFormatter formatter;
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public OpenOffersViewModel(OpenOffersDataModel dataModel, P2PService p2PService, BSFormatter formatter) {
|
public OpenOffersViewModel(OpenOffersDataModel dataModel, P2PService p2PService, BSFormatter formatter) {
|
||||||
super(dataModel);
|
super(dataModel);
|
||||||
this.p2PService = p2PService;
|
|
||||||
|
|
||||||
|
this.p2PService = p2PService;
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void onCancelOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
void onCancelOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||||
dataModel.onCancelOpenOffer(openOffer, resultHandler, errorMessageHandler);
|
dataModel.onCancelOpenOffer(openOffer, resultHandler, errorMessageHandler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
"Please transfer from your external " +
|
"Please transfer from your external " +
|
||||||
CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode()) + " wallet\n" +
|
CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode()) + " wallet\n" +
|
||||||
model.formatter.formatVolumeWithCode(trade.getTradeVolume()) + " to the BTC seller.\n\n" +
|
model.formatter.formatVolumeWithCode(trade.getTradeVolume()) + " to the BTC seller.\n\n" +
|
||||||
"Here are the payment account details of the bitcoin seller:\n" +
|
"Here are the trading account details of the bitcoin seller:\n" +
|
||||||
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n\n" +
|
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n\n" +
|
||||||
"(You can copy & paste the values from the main screen after closing that popup.)";
|
"(You can copy & paste the values from the main screen after closing that popup.)";
|
||||||
else if (paymentAccountContractData != null)
|
else if (paymentAccountContractData != null)
|
||||||
|
@ -80,7 +80,7 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
"(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 go to a bank and pay " +
|
"Please go to a bank and pay " +
|
||||||
model.formatter.formatVolumeWithCode(trade.getTradeVolume()) + " to the BTC seller.\n\n" +
|
model.formatter.formatVolumeWithCode(trade.getTradeVolume()) + " to the BTC seller.\n\n" +
|
||||||
"Here are the payment account details of the BTC seller:\n" +
|
"Here are the trading account details of the BTC seller:\n" +
|
||||||
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n" +
|
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n" +
|
||||||
"(You can copy & paste the values from the main screen after closing that popup.)\n\n" +
|
"(You can copy & paste the values from the main screen after closing that popup.)\n\n" +
|
||||||
"Please don't forget to add the trade ID \"" + trade.getShortId() +
|
"Please don't forget to add the trade ID \"" + trade.getShortId() +
|
||||||
|
@ -96,7 +96,7 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
"(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 send " +
|
"Please send " +
|
||||||
model.formatter.formatVolumeWithCode(trade.getTradeVolume()) + " by \"US Postal Money Order\" to the BTC seller.\n\n" +
|
model.formatter.formatVolumeWithCode(trade.getTradeVolume()) + " by \"US Postal Money Order\" to the BTC seller.\n\n" +
|
||||||
"Here are the payment account details of the BTC seller:\n" +
|
"Here are the trading account details of the BTC seller:\n" +
|
||||||
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n" +
|
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n" +
|
||||||
"(You can copy & paste the values from the main screen after closing that popup.)\n\n" +
|
"(You can copy & paste the values from the main screen after closing that popup.)\n\n" +
|
||||||
"Please don't forget to add the trade ID \"" + trade.getShortId() +
|
"Please don't forget to add the trade ID \"" + trade.getShortId() +
|
||||||
|
@ -108,7 +108,7 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
"(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 go to your online banking web page and pay " +
|
"Please go to your online banking web page and pay " +
|
||||||
model.formatter.formatVolumeWithCode(trade.getTradeVolume()) + " to the BTC seller.\n\n" +
|
model.formatter.formatVolumeWithCode(trade.getTradeVolume()) + " to the BTC seller.\n\n" +
|
||||||
"Here are the payment account details of the BTC seller:\n" +
|
"Here are the trading account details of the BTC seller:\n" +
|
||||||
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n" +
|
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n" +
|
||||||
"(You can copy & paste the values from the main screen after closing that popup.)\n\n" +
|
"(You can copy & paste the values from the main screen after closing that popup.)\n\n" +
|
||||||
"Please don't forget to add the trade ID \"" + trade.getShortId() +
|
"Please don't forget to add the trade ID \"" + trade.getShortId() +
|
||||||
|
|
|
@ -170,8 +170,8 @@ public class SellerStep3View extends TradeStepView {
|
||||||
} else {
|
} else {
|
||||||
myPaymentDetails = myPaymentAccountContractData.getPaymentDetails();
|
myPaymentDetails = myPaymentAccountContractData.getPaymentDetails();
|
||||||
peersPaymentDetails = peersPaymentAccountContractData.getPaymentDetails();
|
peersPaymentDetails = peersPaymentAccountContractData.getPaymentDetails();
|
||||||
myTitle = "Your payment account:";
|
myTitle = "Your trading account:";
|
||||||
peersTitle = "Buyers payment account:";
|
peersTitle = "Buyers trading account:";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ public class SellerStep3View extends TradeStepView {
|
||||||
"confirm the payment when you have sufficient blockchain confirmations.";
|
"confirm the payment when you have sufficient blockchain confirmations.";
|
||||||
} else {
|
} else {
|
||||||
return "The BTC buyer has started the " + model.dataModel.getCurrencyCode() + " payment.\n" +
|
return "The BTC buyer has started the " + model.dataModel.getCurrencyCode() + " payment.\n" +
|
||||||
"Check at your payment account (e.g. bank account) and confirm when you have " +
|
"Check at your trading account (e.g. bank account) and confirm when you have " +
|
||||||
"received the payment.";
|
"received the payment.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,8 @@ public class AboutView extends ActivatableViewAndModel<GridPane, Activatable> {
|
||||||
|
|
||||||
titledGroupBg = addTitledGroupBg(root, ++gridRow, 3, "Support Bitsquare", Layout.GROUP_DISTANCE);
|
titledGroupBg = addTitledGroupBg(root, ++gridRow, 3, "Support Bitsquare", Layout.GROUP_DISTANCE);
|
||||||
GridPane.setColumnSpan(titledGroupBg, 2);
|
GridPane.setColumnSpan(titledGroupBg, 2);
|
||||||
label = addLabel(root, gridRow, "Bitsquare is not a company but a community project and open for participation. If you want to participate or support Bitsquare please follow the links below.", Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
label = addLabel(root, gridRow, "Bitsquare is not a company but a community project and open for participation.\n" +
|
||||||
|
"If you want to participate or support Bitsquare please follow the links below.", Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
label.setWrapText(true);
|
label.setWrapText(true);
|
||||||
GridPane.setColumnSpan(label, 2);
|
GridPane.setColumnSpan(label, 2);
|
||||||
GridPane.setHalignment(label, HPos.LEFT);
|
GridPane.setHalignment(label, HPos.LEFT);
|
||||||
|
|
|
@ -343,8 +343,8 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Activatab
|
||||||
showOwnOffersInOfferBook = addLabelCheckBox(root, gridRow, "Show my own offers in offer book:", "", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
showOwnOffersInOfferBook = addLabelCheckBox(root, gridRow, "Show my own offers in offer book:", "", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||||
useAnimationsCheckBox = addLabelCheckBox(root, ++gridRow, "Use animations:", "").second;
|
useAnimationsCheckBox = addLabelCheckBox(root, ++gridRow, "Use animations:", "").second;
|
||||||
// useStickyMarketPriceCheckBox = addLabelCheckBox(root, ++gridRow, "Use sticky market price:", "").second;
|
// useStickyMarketPriceCheckBox = addLabelCheckBox(root, ++gridRow, "Use sticky market price:", "").second;
|
||||||
sortMarketCurrenciesNumericallyCheckBox = addLabelCheckBox(root, ++gridRow, "Sort market lists with nr. of offers/trades:", "").second;
|
sortMarketCurrenciesNumericallyCheckBox = addLabelCheckBox(root, ++gridRow, "Sort market lists with no. of offers/trades:", "").second;
|
||||||
resetDontShowAgainButton = addLabelButton(root, ++gridRow, "Reset all don't show again flags:", "Reset", 0).second;
|
resetDontShowAgainButton = addLabelButton(root, ++gridRow, "Reset all 'Don't show again' flags:", "Reset", 0).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -557,11 +557,11 @@ public class BSFormatter {
|
||||||
|
|
||||||
public String getOfferDirectionForCreateOffer(Offer.Direction direction, String currencyCode) {
|
public String getOfferDirectionForCreateOffer(Offer.Direction direction, String currencyCode) {
|
||||||
if (CurrencyUtil.isFiatCurrency(currencyCode))
|
if (CurrencyUtil.isFiatCurrency(currencyCode))
|
||||||
return direction == Offer.Direction.BUY ? "You are creating an offer for buying BTC" :
|
return direction == Offer.Direction.BUY ? "You are creating an offer to buy BTC" :
|
||||||
"You are creating an offer for selling BTC";
|
"You are creating an offer to sell BTC";
|
||||||
else
|
else
|
||||||
return direction == Offer.Direction.SELL ? "You are creating an offer for buying " + currencyCode + " (selling BTC)" :
|
return direction == Offer.Direction.SELL ? "You are creating an offer to buy " + currencyCode + " (selling BTC)" :
|
||||||
"You are creating an offer for selling " + currencyCode + " (buying BTC)";
|
"You are creating an offer to sell " + currencyCode + " (buying BTC)";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRole(boolean isBuyerOffererAndSellerTaker, boolean isOfferer, String currencyCode) {
|
public String getRole(boolean isBuyerOffererAndSellerTaker, boolean isOfferer, String currencyCode) {
|
||||||
|
|
|
@ -96,9 +96,9 @@ public class GUIUtil {
|
||||||
Storage<ArrayList<PaymentAccount>> paymentAccountsStorage = new Storage<>(new File(directory));
|
Storage<ArrayList<PaymentAccount>> paymentAccountsStorage = new Storage<>(new File(directory));
|
||||||
paymentAccountsStorage.initAndGetPersisted(accounts, fileName);
|
paymentAccountsStorage.initAndGetPersisted(accounts, fileName);
|
||||||
paymentAccountsStorage.queueUpForSave();
|
paymentAccountsStorage.queueUpForSave();
|
||||||
new Popup<>().feedback("Payment accounts saved to path:\n" + Paths.get(directory, fileName).toAbsolutePath()).show();
|
new Popup<>().feedback("Trading accounts saved to path:\n" + Paths.get(directory, fileName).toAbsolutePath()).show();
|
||||||
} else {
|
} else {
|
||||||
new Popup<>().warning("You don't have payment accounts set up for exporting.").show();
|
new Popup<>().warning("You don't have trading accounts set up for exporting.").show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,15 +120,15 @@ public class GUIUtil {
|
||||||
final String id = paymentAccount.getId();
|
final String id = paymentAccount.getId();
|
||||||
if (user.getPaymentAccount(id) == null) {
|
if (user.getPaymentAccount(id) == null) {
|
||||||
user.addPaymentAccount(paymentAccount);
|
user.addPaymentAccount(paymentAccount);
|
||||||
msg.append("Payment account with id ").append(id).append("\n");
|
msg.append("Trading account with id ").append(id).append("\n");
|
||||||
} else {
|
} else {
|
||||||
msg.append("We did not import payment account with id ").append(id).append(" because it exists already.\n");
|
msg.append("We did not import trading account with id ").append(id).append(" because it exists already.\n");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
new Popup<>().feedback("Payment account imported from path:\n" + path + "\n\nImported accounts:\n" + msg).show();
|
new Popup<>().feedback("Trading account imported from path:\n" + path + "\n\nImported accounts:\n" + msg).show();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
new Popup<>().warning("No exported payment accounts has been found at path: " + path + ".\n" + "File name is " + fileName + ".").show();
|
new Popup<>().warning("No exported trading accounts has been found at path: " + path + ".\n" + "File name is " + fileName + ".").show();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
new Popup<>().warning("The selected file is not the expected file for import. The expected file name is: " + fileName + ".").show();
|
new Popup<>().warning("The selected file is not the expected file for import. The expected file name is: " + fileName + ".").show();
|
||||||
|
@ -209,6 +209,32 @@ public class GUIUtil {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StringConverter<TradeCurrency> getTradeCurrencyConverter() {
|
||||||
|
return new StringConverter<TradeCurrency>() {
|
||||||
|
@Override
|
||||||
|
public String toString(TradeCurrency tradeCurrency) {
|
||||||
|
String code = tradeCurrency.getCode();
|
||||||
|
final String displayString = CurrencyUtil.getNameAndCode(code);
|
||||||
|
// http://boschista.deviantart.com/journal/Cool-ASCII-Symbols-214218618
|
||||||
|
if (code.equals(GUIUtil.SHOW_ALL_FLAG))
|
||||||
|
return "▶ Show all";
|
||||||
|
else if (code.equals(GUIUtil.EDIT_FLAG))
|
||||||
|
return "▼ Edit currency list";
|
||||||
|
else if (tradeCurrency instanceof FiatCurrency)
|
||||||
|
return "★ " + displayString;
|
||||||
|
else if (tradeCurrency instanceof CryptoCurrency) {
|
||||||
|
return "✦ " + displayString;
|
||||||
|
} else
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TradeCurrency fromString(String s) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static void fillCurrencyListItems(List<TradeCurrency> tradeCurrencyList, ObservableList<CurrencyListItem> currencyListItems, @Nullable CurrencyListItem showAllCurrencyListItem, Preferences preferences) {
|
public static void fillCurrencyListItems(List<TradeCurrency> tradeCurrencyList, ObservableList<CurrencyListItem> currencyListItems, @Nullable CurrencyListItem showAllCurrencyListItem, Preferences preferences) {
|
||||||
Set<TradeCurrency> tradeCurrencySet = new HashSet<>();
|
Set<TradeCurrency> tradeCurrencySet = new HashSet<>();
|
||||||
Map<String, Integer> tradesPerCurrencyMap = new HashMap<>();
|
Map<String, Integer> tradesPerCurrencyMap = new HashMap<>();
|
||||||
|
|
|
@ -21,12 +21,12 @@ validation.empty=Empty input is not allowed.
|
||||||
validation.NaN=Input is not a valid number.
|
validation.NaN=Input is not a valid number.
|
||||||
validation.zero=Input of 0 is not allowed.
|
validation.zero=Input of 0 is not allowed.
|
||||||
validation.negative=A negative value is not allowed.
|
validation.negative=A negative value is not allowed.
|
||||||
validation.fiat.toSmall=Input smaller as minimum possible amount is not allowed.
|
validation.fiat.toSmall=Input smaller than minimum possible amount is not allowed.
|
||||||
validation.fiat.toLarge=Input larger as maximum possible amount is not allowed.
|
validation.fiat.toLarge=Input larger than maximum possible amount is not allowed.
|
||||||
validation.btc.toSmall=Input results in a bitcoin value with a fraction of the smallest unit (Satoshi).
|
validation.btc.toSmall=Input results in a bitcoin value with a fraction of the smallest unit (Satoshi).
|
||||||
validation.btc.toLarge=Input larger as maximum trading amount of {0} is not allowed.
|
validation.btc.toLarge=Input larger than maximum trading amount of {0} is not allowed.
|
||||||
validation.passwordTooShort=The password you entered is too short. It needs to have min. 8 characters.
|
validation.passwordTooShort=The password you entered is too short. It needs to have min. 8 characters.
|
||||||
validation.passwordTooLong=The password you entered is too long. It cannot be longer as 50 characters.
|
validation.passwordTooLong=The password you entered is too long. It cannot be longer than 50 characters.
|
||||||
validation.sortCodeNumber={0} must consist of {1} numbers
|
validation.sortCodeNumber={0} must consist of {1} numbers
|
||||||
validation.sortCodeChars={0} must consist of {1} characters
|
validation.sortCodeChars={0} must consist of {1} characters
|
||||||
validation.bankIdNumber={0} must consist of {1} numbers
|
validation.bankIdNumber={0} must consist of {1} numbers
|
||||||
|
@ -45,8 +45,8 @@ createOffer.amountPriceBox.priceDescriptionFiat=Fixed price per {0}
|
||||||
createOffer.amountPriceBox.buy.volumeDescription=Amount in {0} to spend
|
createOffer.amountPriceBox.buy.volumeDescription=Amount in {0} to spend
|
||||||
createOffer.amountPriceBox.sell.volumeDescription=Amount in {0} to receive
|
createOffer.amountPriceBox.sell.volumeDescription=Amount in {0} to receive
|
||||||
createOffer.amountPriceBox.minAmountDescription=Minimum amount of bitcoin
|
createOffer.amountPriceBox.minAmountDescription=Minimum amount of bitcoin
|
||||||
createOffer.amountPriceBox.buy.info=Define a price for which you want to buy bitcoin and either enter the amount or the trade volume. With the minimum amount you can attract more potential traders with giving them more flexibility. But note that there is no automatic creation of a new offer for the remaining amount in the case that a trader takes your offer with a lower amount as defined in the amount field. Your offer will be removed from the offerbook once a trader has taken your offer.
|
createOffer.amountPriceBox.buy.info=Define a price for which you want to buy bitcoin and either enter the amount or the trade volume. With the minimum amount you can attract more potential traders by giving them more flexibility. But note that there is no automatic creation of a new offer for the remaining amount in the case that a trader takes your offer with a lower amount as defined in the amount field. Your offer will be removed from the offerbook once a trader has taken your offer.
|
||||||
createOffer.amountPriceBox.sell.info=Define a price for which you want to sell bitcoin and either enter the amount or the trade volume. With the minimum amount you can attract more potential traders with giving them more flexibility. But note that there is no automatic creation of a new offer for the remaining amount in the case that a trader takes your offer with a lower amount as defined in the amount field. Your offer will be removed from the offerbook once a trader has taken your offer.
|
createOffer.amountPriceBox.sell.info=Define a price for which you want to sell bitcoin and either enter the amount or the trade volume. With the minimum amount you can attract more potential traders by giving them more flexibility. But note that there is no automatic creation of a new offer for the remaining amount in the case that a trader takes your offer with a lower amount as defined in the amount field. Your offer will be removed from the offerbook once a trader has taken your offer.
|
||||||
createOffer.amountPriceBox.next=Next step
|
createOffer.amountPriceBox.next=Next step
|
||||||
createOffer.amountPriceBox.warning.invalidBtcDecimalPlaces=The amount you have entered exceeds the number of allowed decimal places.\nThe amount has been adjusted to 4 decimal places.
|
createOffer.amountPriceBox.warning.invalidBtcDecimalPlaces=The amount you have entered exceeds the number of allowed decimal places.\nThe amount has been adjusted to 4 decimal places.
|
||||||
createOffer.amountPriceBox.warning.invalidFiatDecimalPlaces=The amount you have entered exceeds the number of allowed decimal places.\nThe amount has been adjusted.
|
createOffer.amountPriceBox.warning.invalidFiatDecimalPlaces=The amount you have entered exceeds the number of allowed decimal places.\nThe amount has been adjusted.
|
||||||
|
@ -60,7 +60,7 @@ createOffer.fundsBox.totalsNeeded=Funds needed:
|
||||||
createOffer.fundsBox.totalsNeeded.prompt=Will be calculated from the bitcoin amount entered above
|
createOffer.fundsBox.totalsNeeded.prompt=Will be calculated from the bitcoin amount entered above
|
||||||
createOffer.fundsBox.address=Trade wallet address:
|
createOffer.fundsBox.address=Trade wallet address:
|
||||||
createOffer.fundsBox.balance=Trade wallet balance:
|
createOffer.fundsBox.balance=Trade wallet balance:
|
||||||
createOffer.fundsBox.info=For every offer there is a dedicated trade wallet. You need to fund that trade wallet with the necessary bitcoin amount. Those funds are reserved and will be used in the case that your offer gets executed. If you cancel your offer you can withdraw your funds from that trading wallet. The only payment which will be done now when placing the offer is the offer fee payment.
|
createOffer.fundsBox.info=For every offer there is a dedicated trade wallet. You need to fund that trade wallet with the necessary bitcoin amount. Those funds are reserved and will be used in the case that your offer gets executed. If you cancel your offer you can withdraw your funds from that trading wallet. The only payment made when placing an offer is the offer fee payment. https://bitsquare.io/faq/#6
|
||||||
createOffer.fundsBox.tradeAmount=Trade amount:
|
createOffer.fundsBox.tradeAmount=Trade amount:
|
||||||
createOffer.fundsBox.securityDeposit=Security deposit:
|
createOffer.fundsBox.securityDeposit=Security deposit:
|
||||||
createOffer.fundsBox.offerFee=Create offer fee:
|
createOffer.fundsBox.offerFee=Create offer fee:
|
||||||
|
@ -107,7 +107,7 @@ takeOffer.amountPriceBox.next=Next step
|
||||||
takeOffer.amountPriceBox.warning.invalidBtcDecimalPlaces=The amount you have entered exceeds the number of allowed decimal places.\nThe amount has been adjusted to 4 decimal places.
|
takeOffer.amountPriceBox.warning.invalidBtcDecimalPlaces=The amount you have entered exceeds the number of allowed decimal places.\nThe amount has been adjusted to 4 decimal places.
|
||||||
takeOffer.validation.amountSmallerThanMinAmount=Amount cannot be smaller than minimum amount defined in the offer.
|
takeOffer.validation.amountSmallerThanMinAmount=Amount cannot be smaller than minimum amount defined in the offer.
|
||||||
takeOffer.validation.amountLargerThanOfferAmount=Input amount cannot be higher than the amount defined in the offer.
|
takeOffer.validation.amountLargerThanOfferAmount=Input amount cannot be higher than the amount defined in the offer.
|
||||||
takeOffer.validation.amountLargerThanOfferAmountMinusFee=That input amount would create a dust change for the BTC seller.
|
takeOffer.validation.amountLargerThanOfferAmountMinusFee=That input amount would create dust change for the BTC seller.
|
||||||
|
|
||||||
takeOffer.fundsBox.title=Fund your trade
|
takeOffer.fundsBox.title=Fund your trade
|
||||||
takeOffer.fundsBox.isOfferAvailable=Check if offer is available...
|
takeOffer.fundsBox.isOfferAvailable=Check if offer is available...
|
||||||
|
@ -115,11 +115,11 @@ takeOffer.fundsBox.totalsNeeded=Funds needed:
|
||||||
takeOffer.fundsBox.totalsNeeded.prompt=Will be calculated from the bitcoin amount entered above
|
takeOffer.fundsBox.totalsNeeded.prompt=Will be calculated from the bitcoin amount entered above
|
||||||
takeOffer.fundsBox.address=Trade wallet address:
|
takeOffer.fundsBox.address=Trade wallet address:
|
||||||
takeOffer.fundsBox.balance=Trade wallet balance:
|
takeOffer.fundsBox.balance=Trade wallet balance:
|
||||||
takeOffer.fundsBox.buy.info=For every offer there is a dedicated trade wallet. You need to fund that trade wallet with the necessary bitcoin amount. Those \
|
takeOffer.fundsBox.buy.info=For every offer there is a dedicated trade wallet. You need to fund that trade wallet with the necessary bitcoin amount. \
|
||||||
funds will be paid in to a locked deposit address. At the end of a successful trade you will get back your security deposit and the bitcoin amount you sold will be transferred to the \
|
Those funds will be paid in to a locked deposit address. At the end of a successful trade you will get back your security deposit and the bitcoin amount you sold will be transferred \
|
||||||
BTC buyer.
|
to the BTC buyer.
|
||||||
takeOffer.fundsBox.sell.info=For every offer there is a dedicated trade wallet. You need to fund that trade wallet with the necessary bitcoin amount. Those \
|
takeOffer.fundsBox.sell.info=For every offer there is a dedicated trade wallet. You need to fund that trade wallet with the necessary bitcoin amount. \
|
||||||
funds will be paid in to a locked deposit address. At the end of a successful trade you will get back your security deposit.
|
Those funds will be paid into a locked deposit address. At the end of a successful trade you will get back your security deposit.
|
||||||
takeOffer.fundsBox.tradeAmount=Amount to sell:
|
takeOffer.fundsBox.tradeAmount=Amount to sell:
|
||||||
takeOffer.fundsBox.securityDeposit=Security deposit:
|
takeOffer.fundsBox.securityDeposit=Security deposit:
|
||||||
takeOffer.fundsBox.offerFee=Take offer fee:
|
takeOffer.fundsBox.offerFee=Take offer fee:
|
||||||
|
@ -138,8 +138,8 @@ takeOffer.advancedBox.arbitrators=Accepted arbitrators:
|
||||||
takeOffer.advancedBox.txType=Payments method:
|
takeOffer.advancedBox.txType=Payments method:
|
||||||
takeOffer.advancedBox.currency=Currency:
|
takeOffer.advancedBox.currency=Currency:
|
||||||
takeOffer.advancedBox.county=Payments account country:
|
takeOffer.advancedBox.county=Payments account country:
|
||||||
takeOffer.advancedBox.info=These are the offer restrictions your trading partner has defined in his offer. Your \
|
takeOffer.advancedBox.info=These are the offer restrictions your trading partner has defined in his offer. \
|
||||||
settings are matching those constraints and you are able to trade with him.
|
Your settings match those constraints and you are able to trade with him.
|
||||||
|
|
||||||
takeOffer.success.headline=You have successfully taken an offer
|
takeOffer.success.headline=You have successfully taken an offer
|
||||||
takeOffer.success.info=You can see the status of your trade at the \"Portfolio\" screen under \"Open trades\".
|
takeOffer.success.info=You can see the status of your trade at the \"Portfolio\" screen under \"Open trades\".
|
||||||
|
|
|
@ -35,6 +35,7 @@ public abstract class Connection implements Closeable {
|
||||||
private final AtomicBoolean heartBeating;
|
private final AtomicBoolean heartBeating;
|
||||||
|
|
||||||
public Connection(String peer, Socket socket) throws IOException {
|
public Connection(String peer, Socket socket) throws IOException {
|
||||||
|
// LookAheadObjectInputStream not needed here as the class it not used in Bitsquare (used to test the library)
|
||||||
this(peer, socket, Node.prepareOOSForSocket(socket), new ObjectInputStream(socket.getInputStream()));
|
this(peer, socket, Node.prepareOOSForSocket(socket), new ObjectInputStream(socket.getInputStream()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -235,6 +235,7 @@ public class Node {
|
||||||
// get incoming data
|
// get incoming data
|
||||||
try {
|
try {
|
||||||
out = prepareOOSForSocket(socket);
|
out = prepareOOSForSocket(socket);
|
||||||
|
// LookAheadObjectInputStream not needed here as the class it not used in Bitsquare (used to test the library)
|
||||||
objectInputStream = new ObjectInputStream(socket.getInputStream());
|
objectInputStream = new ObjectInputStream(socket.getInputStream());
|
||||||
} catch (EOFException e) {
|
} catch (EOFException e) {
|
||||||
log.debug("Got bogus incoming connection");
|
log.debug("Got bogus incoming connection");
|
||||||
|
|
|
@ -668,7 +668,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
|
||||||
// does not arrive.
|
// does not arrive.
|
||||||
// We could use onBroadcastCompleted instead but it might take too long if one peer
|
// We could use onBroadcastCompleted instead but it might take too long if one peer
|
||||||
// is very badly connected.
|
// is very badly connected.
|
||||||
// TODO We could check for a certain threshold of nr. of incoming messages of the same msg
|
// TODO We could check for a certain threshold of no. of incoming messages of the same msg
|
||||||
// to see how well it is propagated. BitcoinJ uses such an approach for tx propagation.
|
// to see how well it is propagated. BitcoinJ uses such an approach for tx propagation.
|
||||||
UserThread.runAfter(() -> {
|
UserThread.runAfter(() -> {
|
||||||
log.info("Broadcasted to first peer (with 3 sec. delayed): Message = {}", Utilities.toTruncatedString(message));
|
log.info("Broadcasted to first peer (with 3 sec. delayed): Message = {}", Utilities.toTruncatedString(message));
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class Utils {
|
||||||
return bos.toByteArray();
|
return bos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Serializable decompress(byte[] compressedData) {
|
public static Serializable decompress(byte[] compressedData) throws IOException, ClassNotFoundException {
|
||||||
return (Serializable) ByteArrayUtils.byteArrayToObject(decompress(compressedData, compressedData.length));
|
return (Serializable) ByteArrayUtils.byteArrayToObject(decompress(compressedData, compressedData.length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,8 @@ public enum CloseConnectionReason {
|
||||||
|
|
||||||
// illegal requests
|
// illegal requests
|
||||||
RULE_VIOLATION(true, false),
|
RULE_VIOLATION(true, false),
|
||||||
PEER_BANNED(true, false);
|
PEER_BANNED(true, false),
|
||||||
|
INVALID_CLASS_RECEIVED(false, false);
|
||||||
|
|
||||||
public final boolean sendCloseMessage;
|
public final boolean sendCloseMessage;
|
||||||
public boolean isIntended;
|
public boolean isIntended;
|
||||||
|
|
|
@ -9,6 +9,7 @@ import io.bitsquare.common.ByteArrayUtils;
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.common.UserThread;
|
||||||
import io.bitsquare.common.util.Tuple2;
|
import io.bitsquare.common.util.Tuple2;
|
||||||
import io.bitsquare.common.util.Utilities;
|
import io.bitsquare.common.util.Utilities;
|
||||||
|
import io.bitsquare.io.LookAheadObjectInputStream;
|
||||||
import io.bitsquare.p2p.Message;
|
import io.bitsquare.p2p.Message;
|
||||||
import io.bitsquare.p2p.NodeAddress;
|
import io.bitsquare.p2p.NodeAddress;
|
||||||
import io.bitsquare.p2p.messaging.PrefixedSealedAndSignedMessage;
|
import io.bitsquare.p2p.messaging.PrefixedSealedAndSignedMessage;
|
||||||
|
@ -146,24 +147,24 @@ public class Connection implements MessageListener {
|
||||||
// the associated ObjectOutputStream on the other end of the connection has written.
|
// the associated ObjectOutputStream on the other end of the connection has written.
|
||||||
// It will not return until that header has been read.
|
// It will not return until that header has been read.
|
||||||
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
|
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
|
||||||
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
|
ObjectInputStream objectInputStream = new LookAheadObjectInputStream(socket.getInputStream(), true);
|
||||||
|
|
||||||
// We create a thread for handling inputStream data
|
// We create a thread for handling inputStream data
|
||||||
inputHandler = new InputHandler(sharedModel, objectInputStream, portInfo, this);
|
inputHandler = new InputHandler(sharedModel, objectInputStream, portInfo, this);
|
||||||
singleThreadExecutor.submit(inputHandler);
|
singleThreadExecutor.submit(inputHandler);
|
||||||
} catch (IOException e) {
|
|
||||||
|
// Use Peer as default, in case of other types they will set it as soon as possible.
|
||||||
|
peerType = PeerType.PEER;
|
||||||
|
|
||||||
|
if (peersNodeAddress != null)
|
||||||
|
setPeersNodeAddress(peersNodeAddress);
|
||||||
|
|
||||||
|
log.trace("New connection created: " + this.toString());
|
||||||
|
|
||||||
|
UserThread.execute(() -> connectionListener.onConnection(this));
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
sharedModel.handleConnectionException(e);
|
sharedModel.handleConnectionException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use Peer as default, in case of other types they will set it as soon as possible.
|
|
||||||
peerType = PeerType.PEER;
|
|
||||||
|
|
||||||
if (peersNodeAddress != null)
|
|
||||||
setPeersNodeAddress(peersNodeAddress);
|
|
||||||
|
|
||||||
log.trace("New connection created: " + this.toString());
|
|
||||||
|
|
||||||
UserThread.execute(() -> connectionListener.onConnection(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -590,6 +591,8 @@ public class Connection implements MessageListener {
|
||||||
if (ruleViolation == RuleViolation.PEER_BANNED) {
|
if (ruleViolation == RuleViolation.PEER_BANNED) {
|
||||||
log.warn("We detected a connection to a banned peer. We will close that connection. (reportInvalidRequest)");
|
log.warn("We detected a connection to a banned peer. We will close that connection. (reportInvalidRequest)");
|
||||||
shutDown(CloseConnectionReason.PEER_BANNED);
|
shutDown(CloseConnectionReason.PEER_BANNED);
|
||||||
|
} else if (ruleViolation == RuleViolation.INVALID_CLASS) {
|
||||||
|
shutDown(CloseConnectionReason.INVALID_CLASS_RECEIVED);
|
||||||
} else {
|
} else {
|
||||||
shutDown(CloseConnectionReason.RULE_VIOLATION);
|
shutDown(CloseConnectionReason.RULE_VIOLATION);
|
||||||
}
|
}
|
||||||
|
@ -888,6 +891,11 @@ public class Connection implements MessageListener {
|
||||||
|
|
||||||
messageListener.onMessage(message, connection);
|
messageListener.onMessage(message, connection);
|
||||||
}
|
}
|
||||||
|
} catch (InvalidClassException e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
reportInvalidRequest(RuleViolation.INVALID_CLASS);
|
||||||
|
return;
|
||||||
} catch (ClassNotFoundException | NoClassDefFoundError e) {
|
} catch (ClassNotFoundException | NoClassDefFoundError e) {
|
||||||
log.warn(e.getMessage());
|
log.warn(e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
@ -6,7 +6,8 @@ public enum RuleViolation {
|
||||||
MAX_MSG_SIZE_EXCEEDED(2),
|
MAX_MSG_SIZE_EXCEEDED(2),
|
||||||
THROTTLE_LIMIT_EXCEEDED(2),
|
THROTTLE_LIMIT_EXCEEDED(2),
|
||||||
TOO_MANY_REPORTED_PEERS_SENT(2),
|
TOO_MANY_REPORTED_PEERS_SENT(2),
|
||||||
PEER_BANNED(0);
|
PEER_BANNED(0),
|
||||||
|
INVALID_CLASS(0);
|
||||||
|
|
||||||
public final int maxTolerance;
|
public final int maxTolerance;
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ public class PeerManager implements ConnectionListener {
|
||||||
public void onConnection(Connection connection) {
|
public void onConnection(Connection connection) {
|
||||||
Log.logIfStressTests("onConnection to peer " +
|
Log.logIfStressTests("onConnection to peer " +
|
||||||
(connection.getPeersNodeAddressOptional().isPresent() ? connection.getPeersNodeAddressOptional().get() : "PeersNode unknown") +
|
(connection.getPeersNodeAddressOptional().isPresent() ? connection.getPeersNodeAddressOptional().get() : "PeersNode unknown") +
|
||||||
" / Nr. of connections: " + networkNode.getAllConnections().size());
|
" / No. of connections: " + networkNode.getAllConnections().size());
|
||||||
|
|
||||||
final boolean seedNode = isSeedNode(connection);
|
final boolean seedNode = isSeedNode(connection);
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ public class PeerManager implements ConnectionListener {
|
||||||
public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) {
|
public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) {
|
||||||
Log.logIfStressTests("onDisconnect of peer " +
|
Log.logIfStressTests("onDisconnect of peer " +
|
||||||
(connection.getPeersNodeAddressOptional().isPresent() ? connection.getPeersNodeAddressOptional().get() : "PeersNode unknown") +
|
(connection.getPeersNodeAddressOptional().isPresent() ? connection.getPeersNodeAddressOptional().get() : "PeersNode unknown") +
|
||||||
" / Nr. of connections: " + networkNode.getAllConnections().size() +
|
" / No. of connections: " + networkNode.getAllConnections().size() +
|
||||||
" / closeConnectionReason: " + closeConnectionReason);
|
" / closeConnectionReason: " + closeConnectionReason);
|
||||||
|
|
||||||
final Optional<NodeAddress> addressOptional = connection.getPeersNodeAddressOptional();
|
final Optional<NodeAddress> addressOptional = connection.getPeersNodeAddressOptional();
|
||||||
|
|
|
@ -16,7 +16,7 @@ import java.security.spec.X509EncodedKeySpec;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Envelope message which support a time to live and sender and receivers pub keys for storage operations.
|
* Envelope message which support a time to live and sender and receiver's pub keys for storage operations.
|
||||||
* It differs from the ProtectedExpirableMessage in the way that the sender is permitted to do an add operation
|
* It differs from the ProtectedExpirableMessage in the way that the sender is permitted to do an add operation
|
||||||
* but only the receiver is permitted to remove the data.
|
* but only the receiver is permitted to remove the data.
|
||||||
* That is the typical requirement for a mailbox like system.
|
* That is the typical requirement for a mailbox like system.
|
||||||
|
|
|
@ -58,13 +58,13 @@ public class DummySeedNode {
|
||||||
// BitcoinNetworkId: The id for the bitcoin network (Mainnet = 0, TestNet = 1, Regtest = 2)
|
// BitcoinNetworkId: The id for the bitcoin network (Mainnet = 0, TestNet = 1, Regtest = 2)
|
||||||
// localhost:3002 2 50 true
|
// localhost:3002 2 50 true
|
||||||
// localhost:3002 2 50 localhost:4442|localhost:4443 true
|
// localhost:3002 2 50 localhost:4442|localhost:4443 true
|
||||||
// Usage: -myAddress=<my onion address> -networkId=<networkId (Mainnet = 0, TestNet = 1, Regtest = 2)> -maxConnections=<Nr. of max. connections allowed> -useLocalhost=false -seedNodes=si3uu56adkyqkldl.onion:8002|eo5ay2lyzrfvx2nr.onion:8002 -ignore=4543y2lyzrfvx2nr.onion:8002|876572lyzrfvx2nr.onion:8002
|
// Usage: -myAddress=<my onion address> -networkId=<networkId (Mainnet = 0, TestNet = 1, Regtest = 2)> -maxConnections=<No. of max. connections allowed> -useLocalhost=false -seedNodes=si3uu56adkyqkldl.onion:8002|eo5ay2lyzrfvx2nr.onion:8002 -ignore=4543y2lyzrfvx2nr.onion:8002|876572lyzrfvx2nr.onion:8002
|
||||||
// Example usage: -myAddress=lmvdenjkyvx2ovga.onion:8001 -networkId=0 -maxConnections=20 -useLocalhost=false -seedNodes=si3uu56adkyqkldl.onion:8002|eo5ay2lyzrfvx2nr.onion:8002 -ignore=4543y2lyzrfvx2nr.onion:8002|876572lyzrfvx2nr.onion:8002
|
// Example usage: -myAddress=lmvdenjkyvx2ovga.onion:8001 -networkId=0 -maxConnections=20 -useLocalhost=false -seedNodes=si3uu56adkyqkldl.onion:8002|eo5ay2lyzrfvx2nr.onion:8002 -ignore=4543y2lyzrfvx2nr.onion:8002|876572lyzrfvx2nr.onion:8002
|
||||||
|
|
||||||
public static final String USAGE = "Usage:\n" +
|
public static final String USAGE = "Usage:\n" +
|
||||||
"--myAddress=<my onion address>\n" +
|
"--myAddress=<my onion address>\n" +
|
||||||
"--networkId=[0|1|2] (Mainnet = 0, TestNet = 1, Regtest = 2)\n" +
|
"--networkId=[0|1|2] (Mainnet = 0, TestNet = 1, Regtest = 2)\n" +
|
||||||
"--maxConnections=<Nr. of max. connections allowed>\n" +
|
"--maxConnections=<No. of max. connections allowed>\n" +
|
||||||
"--useLocalhost=[true|false]\n" +
|
"--useLocalhost=[true|false]\n" +
|
||||||
"--logLevel=Log level [OFF, ALL, ERROR, WARN, INFO, DEBUG, TRACE]\n" +
|
"--logLevel=Log level [OFF, ALL, ERROR, WARN, INFO, DEBUG, TRACE]\n" +
|
||||||
"--seedNodes=[onion addresses separated with comma]\n" +
|
"--seedNodes=[onion addresses separated with comma]\n" +
|
||||||
|
|
|
@ -451,8 +451,8 @@ public class PeerServiceTest {
|
||||||
log.debug("total authentications " + authentications);
|
log.debug("total authentications " + authentications);
|
||||||
Profiler.printSystemLoad(log);
|
Profiler.printSystemLoad(log);
|
||||||
// total authentications at 8 nodes = 56
|
// total authentications at 8 nodes = 56
|
||||||
// total authentications at com nodes = 90, System load (nr. threads/used memory (MB)): 170/20
|
// total authentications at com nodes = 90, System load (no. threads/used memory (MB)): 170/20
|
||||||
// total authentications at 20 nodes = 380, System load (nr. threads/used memory (MB)): 525/46
|
// total authentications at 20 nodes = 380, System load (no. threads/used memory (MB)): 525/46
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
nodes[i].getP2PService().getPeerGroup().printAuthenticatedPeers();
|
nodes[i].getP2PService().getPeerGroup().printAuthenticatedPeers();
|
||||||
nodes[i].getP2PService().getPeerGroup().printReportedPeers();
|
nodes[i].getP2PService().getPeerGroup().printReportedPeers();
|
||||||
|
|
|
@ -414,8 +414,8 @@ public class PeerManagerTest {
|
||||||
log.debug("total authentications " + authentications);
|
log.debug("total authentications " + authentications);
|
||||||
Profiler.printSystemLoad(log);
|
Profiler.printSystemLoad(log);
|
||||||
// total authentications at 8 nodes = 56
|
// total authentications at 8 nodes = 56
|
||||||
// total authentications at com nodes = 90, System load (nr. threads/used memory (MB)): 170/20
|
// total authentications at com nodes = 90, System load (no. threads/used memory (MB)): 170/20
|
||||||
// total authentications at 20 nodes = 380, System load (nr. threads/used memory (MB)): 525/46
|
// total authentications at 20 nodes = 380, System load (no. threads/used memory (MB)): 525/46
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
nodes[i].getP2PService().getPeerGroup().printAuthenticatedPeers();
|
nodes[i].getP2PService().getPeerGroup().printAuthenticatedPeers();
|
||||||
nodes[i].getP2PService().getPeerGroup().printReportedPeers();
|
nodes[i].getP2PService().getPeerGroup().printReportedPeers();
|
||||||
|
|
|
@ -33,13 +33,16 @@ cp "/Users/mk/vm_shared_windows/bundles/$exe" "/Users/mk/vm_shared_win10/$win64"
|
||||||
|
|
||||||
cd "$target_dir"
|
cd "$target_dir"
|
||||||
|
|
||||||
#shasum -a 256 "$mac" "$deb64" "$deb32" "$rpm64" "$rpm32" "$win64" "$win32" > sha256_hashes.txt
|
gpg --digest-algo SHA256 --local-user manfred@bitsquare.io --output $mac.asc --detach-sig --armor $mac
|
||||||
shasum -a 256 "$mac" "$deb64" "$deb32" "$win64" "$win32" > sha256_hashes.txt
|
gpg --digest-algo SHA256 --local-user manfred@bitsquare.io --output $deb64.asc --detach-sig --armor $deb64
|
||||||
|
gpg --digest-algo SHA256 --local-user manfred@bitsquare.io --output $deb32.asc --detach-sig --armor $deb32
|
||||||
|
gpg --digest-algo SHA256 --local-user manfred@bitsquare.io --output $win64.asc --detach-sig --armor $win64
|
||||||
|
gpg --digest-algo SHA256 --local-user manfred@bitsquare.io --output $win32.asc --detach-sig --armor $win32
|
||||||
|
|
||||||
gpg --digest-algo SHA256 --local-user manfred@bitsquare.io --output signed_sha256_hashes.txt --clearsign sha256_hashes.txt
|
gpg --digest-algo SHA256 --verify $mac{.asc*,}
|
||||||
|
gpg --digest-algo SHA256 --verify $deb64{.asc*,}
|
||||||
gpg --digest-algo SHA256 --verify signed_sha256_hashes.txt
|
gpg --digest-algo SHA256 --verify $deb32{.asc*,}
|
||||||
|
gpg --digest-algo SHA256 --verify $win64{.asc*,}
|
||||||
rm "$target_dir/sha256_hashes.txt"
|
gpg --digest-algo SHA256 --verify $win32{.asc*,}
|
||||||
|
|
||||||
open "$target_dir"
|
open "$target_dir"
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
|
:: Invoke from bitsquare home directory
|
||||||
:: edit iss file -> AppVersion
|
:: edit iss file -> AppVersion
|
||||||
|
|
||||||
:: Copy gui/deploy.Bitsquare.jar file from mac build to windows
|
|
||||||
:: edit -> -BappVersion and -srcfiles
|
:: edit -> -BappVersion and -srcfiles
|
||||||
|
|
||||||
:: 64 bit build
|
:: 32 bit build
|
||||||
:: Needs Inno Setup 5 or later (http://www.jrsoftware.org/isdl.php)
|
:: Needs Inno Setup 5 or later (http://www.jrsoftware.org/isdl.php)
|
||||||
|
|
||||||
SET version=0.4.9.6
|
SET version=0.4.9.6
|
||||||
SET jdk=C:\Program Files\Java\jdk1.8.0_92
|
|
||||||
SET outdir=\\VBOXSVR\vm_shared_windows_32bit
|
|
||||||
|
|
||||||
call "%jdk%\bin\javapackager.exe" -deploy ^
|
:: Private setup
|
||||||
|
SET outdir=\\VBOXSVR\vm_shared_windows_32bit
|
||||||
|
:: Others might use the following
|
||||||
|
:: SET outdir=.
|
||||||
|
|
||||||
|
copy gui\target\shaded.jar Bitsquare-%version%.jar
|
||||||
|
call "%JAVA_HOME%\bin\javapackager.exe" -deploy ^
|
||||||
-BappVersion="%version%" ^
|
-BappVersion="%version%" ^
|
||||||
-native exe ^
|
-native exe ^
|
||||||
-name Bitsquare ^
|
-name Bitsquare ^
|
||||||
|
@ -20,5 +23,5 @@ call "%jdk%\bin\javapackager.exe" -deploy ^
|
||||||
-appclass io.bitsquare.app.BitsquareAppMain ^
|
-appclass io.bitsquare.app.BitsquareAppMain ^
|
||||||
-srcfiles %outdir%\Bitsquare-%version%.jar ^
|
-srcfiles %outdir%\Bitsquare-%version%.jar ^
|
||||||
-outfile Bitsquare ^
|
-outfile Bitsquare ^
|
||||||
-Bruntime="%jdk%\jre" ^
|
-Bruntime="%JAVA_HOME%\jre" ^
|
||||||
-BjvmProperties=-Djava.net.preferIPv4Stack=true
|
-BjvmProperties=-Djava.net.preferIPv4Stack=true
|
|
@ -1,6 +1,5 @@
|
||||||
|
:: Invoke from bitsquare home directory
|
||||||
:: edit iss file -> AppVersion
|
:: edit iss file -> AppVersion
|
||||||
|
|
||||||
:: Copy gui/deploy.Bitsquare.jar file from mac build to windows
|
|
||||||
:: edit -> -BappVersion and -srcfiles
|
:: edit -> -BappVersion and -srcfiles
|
||||||
|
|
||||||
:: 64 bit build
|
:: 64 bit build
|
||||||
|
@ -9,10 +8,14 @@
|
||||||
:: Did not get -BjvmOptions=-Xbootclasspath working on windows, but if the jdkfix jar is copied into the jdk/jre dir it will override the default classes
|
:: Did not get -BjvmOptions=-Xbootclasspath working on windows, but if the jdkfix jar is copied into the jdk/jre dir it will override the default classes
|
||||||
|
|
||||||
SET version=0.4.9.6
|
SET version=0.4.9.6
|
||||||
SET jdk=C:\Program Files\Java\jdk1.8.0_92
|
|
||||||
SET outdir=\\VBOXSVR\vm_shared_windows
|
|
||||||
|
|
||||||
call "%jdk%\bin\javapackager.exe" -deploy ^
|
:: Private setup
|
||||||
|
SET outdir=\\VBOXSVR\vm_shared_windows
|
||||||
|
:: Others might use the following
|
||||||
|
:: SET outdir=.
|
||||||
|
|
||||||
|
|
||||||
|
call "%JAVA_HOME%\bin\javapackager.exe" -deploy ^
|
||||||
-BappVersion="%version%" ^
|
-BappVersion="%version%" ^
|
||||||
-native exe ^
|
-native exe ^
|
||||||
-name Bitsquare ^
|
-name Bitsquare ^
|
||||||
|
@ -22,5 +25,5 @@ call "%jdk%\bin\javapackager.exe" -deploy ^
|
||||||
-appclass io.bitsquare.app.BitsquareAppMain ^
|
-appclass io.bitsquare.app.BitsquareAppMain ^
|
||||||
-srcfiles %outdir%\Bitsquare-%version%.jar ^
|
-srcfiles %outdir%\Bitsquare-%version%.jar ^
|
||||||
-outfile Bitsquare ^
|
-outfile Bitsquare ^
|
||||||
-Bruntime="%jdk%\jre" ^
|
-Bruntime="%JAVA_HOME%\jre" ^
|
||||||
-BjvmProperties=-Djava.net.preferIPv4Stack=true
|
-BjvmProperties=-Djava.net.preferIPv4Stack=true
|
5
pom.xml
5
pom.xml
|
@ -156,6 +156,11 @@
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>1.16.10</version>
|
<version>1.16.10</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.findbugs</groupId>
|
||||||
|
<artifactId>jsr305</artifactId>
|
||||||
|
<version>3.0.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!--logging-->
|
<!--logging-->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
Loading…
Add table
Reference in a new issue