mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-05-20 07:20:41 -04:00
add missing files
This commit is contained in:
parent
c6ece486ed
commit
9ef8b42509
239 changed files with 20558 additions and 51 deletions
|
@ -0,0 +1,16 @@
|
|||
package io.bitsquare.p2p.seed;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class SeedNodeMain {
|
||||
|
||||
// args: port useLocalhost seedNodes
|
||||
// eg. 4444 true localhost:7777 localhost:8888
|
||||
// To stop enter: q
|
||||
public static void main(String[] args) throws NoSuchAlgorithmException {
|
||||
SeedNode seedNode = new SeedNode();
|
||||
seedNode.processArgs(args);
|
||||
seedNode.createAndStartP2PService();
|
||||
seedNode.listenForExitCommand();
|
||||
}
|
||||
}
|
28
common/pom.xml
Normal file
28
common/pom.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>io.bitsquare</groupId>
|
||||
<version>0.3.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>common</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.2.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.1.1.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
65
common/src/main/java/io/bitsquare/app/AppModule.java
Normal file
65
common/src/main/java/io/bitsquare/app/AppModule.java
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.app;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Injector;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AppModule extends AbstractModule {
|
||||
protected final Environment env;
|
||||
|
||||
private final List<AppModule> modules = new ArrayList<>();
|
||||
|
||||
protected AppModule(Environment env) {
|
||||
Preconditions.checkNotNull(env, "Environment must not be null");
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
protected void install(AppModule module) {
|
||||
super.install(module);
|
||||
modules.add(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close any instances this module is responsible for and recursively close any
|
||||
* sub-modules installed via {@link #install(AppModule)}. This method
|
||||
* must be called manually, e.g. at the end of a main() method or in the stop() method
|
||||
* of a JavaFX Application; alternatively it may be registered as a JVM shutdown hook.
|
||||
*
|
||||
* @param injector the Injector originally initialized with this module
|
||||
* @see #doClose(com.google.inject.Injector)
|
||||
*/
|
||||
public final void close(Injector injector) {
|
||||
modules.forEach(module -> module.close(injector));
|
||||
doClose(injector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually perform closing of any instances this module is responsible for. Called by
|
||||
* {@link #close(Injector)}.
|
||||
*
|
||||
* @param injector the Injector originally initialized with this module
|
||||
*/
|
||||
protected void doClose(Injector injector) {
|
||||
}
|
||||
}
|
19
common/src/main/java/io/bitsquare/app/ProgramArguments.java
Normal file
19
common/src/main/java/io/bitsquare/app/ProgramArguments.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
package io.bitsquare.app;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
// TODO too app specific for common...
|
||||
public class ProgramArguments {
|
||||
// program arg names
|
||||
public static final String TOR_DIR = "torDir";
|
||||
public static final String USE_LOCALHOST = "useLocalhost";
|
||||
public static final String DEV_TEST = "devTest";
|
||||
|
||||
|
||||
public static final String NAME_KEY = "node.name";
|
||||
public static final String PORT_KEY = "node.port";
|
||||
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ProgramArguments.class);
|
||||
}
|
45
common/src/main/java/io/bitsquare/app/Version.java
Normal file
45
common/src/main/java/io/bitsquare/app/Version.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.app;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Version {
|
||||
private static final Logger log = LoggerFactory.getLogger(Version.class);
|
||||
|
||||
// The application versions
|
||||
private static final int MAJOR_VERSION = 0;
|
||||
private static final int MINOR_VERSION = 3;
|
||||
// used as updateFX index
|
||||
public static final int PATCH_VERSION = 2;
|
||||
|
||||
public static final String VERSION = MAJOR_VERSION + "." + MINOR_VERSION + "." + PATCH_VERSION;
|
||||
|
||||
// The version nr. for the objects sent over the network. A change will break the serialization of old objects.
|
||||
// If objects are used for both network and database the network version is applied.
|
||||
public static final long NETWORK_PROTOCOL_VERSION = 1;
|
||||
|
||||
// The version nr. of the serialized data stored to disc. A change will break the serialization of old objects.
|
||||
public static final long LOCAL_DB_VERSION = 1;
|
||||
|
||||
// The version nr. of the current protocol. The offer holds that version. A taker will check the version of the offers to see if he his version is
|
||||
// compatible.
|
||||
public static final long PROTOCOL_VERSION = 1;
|
||||
|
||||
}
|
81
common/src/main/java/io/bitsquare/common/ByteArrayUtils.java
Normal file
81
common/src/main/java/io/bitsquare/common/ByteArrayUtils.java
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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.common;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class ByteArrayUtils {
|
||||
private static final Logger log = LoggerFactory.getLogger(ByteArrayUtils.class);
|
||||
private static long lastTimeStamp = System.currentTimeMillis();
|
||||
|
||||
public static <T> T byteArrayToObject(byte[] data) {
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
||||
ObjectInput in = null;
|
||||
Object result = null;
|
||||
try {
|
||||
in = new ObjectInputStream(bis);
|
||||
result = in.readObject();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
}
|
||||
return (T) result;
|
||||
}
|
||||
|
||||
public static byte[] objectToByteArray(Object object) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutput out = null;
|
||||
byte[] result = null;
|
||||
try {
|
||||
out = new ObjectOutputStream(bos);
|
||||
out.writeObject(object);
|
||||
result = bos.toByteArray();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
try {
|
||||
bos.close();
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
38
common/src/main/java/io/bitsquare/common/UserThread.java
Normal file
38
common/src/main/java/io/bitsquare/common/UserThread.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.common;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class UserThread {
|
||||
|
||||
public static Executor getExecutor() {
|
||||
return executor;
|
||||
}
|
||||
|
||||
public static void setExecutor(Executor executor) {
|
||||
UserThread.executor = executor;
|
||||
}
|
||||
|
||||
public static Executor executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
public static void execute(Runnable command) {
|
||||
UserThread.executor.execute(command);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.common.handlers;
|
||||
|
||||
/**
|
||||
* For reporting error message only (UI)
|
||||
*/
|
||||
public interface ErrorMessageHandler {
|
||||
void handleErrorMessage(String errorMessage);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.common.handlers;
|
||||
|
||||
/**
|
||||
* For reporting throwable objects only
|
||||
*/
|
||||
public interface ExceptionHandler {
|
||||
void handleException(Throwable throwable);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.common.handlers;
|
||||
|
||||
/**
|
||||
* For reporting a description message and throwable
|
||||
*/
|
||||
public interface FaultHandler {
|
||||
void handleFault(String errorMessage, Throwable throwable);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.common.handlers;
|
||||
|
||||
public interface ResultHandler extends Runnable {
|
||||
void handleResult();
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.common.taskrunner;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class InterceptTaskException extends RuntimeException {
|
||||
private static final Logger log = LoggerFactory.getLogger(InterceptTaskException.class);
|
||||
private static final long serialVersionUID = 5216202440370333534L;
|
||||
|
||||
public InterceptTaskException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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.common.taskrunner;
|
||||
|
||||
public interface Model {
|
||||
void persist();
|
||||
|
||||
void onComplete();
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.common.taskrunner;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class Task<T extends Model> {
|
||||
private static final Logger log = LoggerFactory.getLogger(Task.class);
|
||||
|
||||
public static Class<? extends Task> taskToIntercept;
|
||||
|
||||
private final TaskRunner taskHandler;
|
||||
protected final T model;
|
||||
protected String errorMessage = "An error occurred at task: " + getClass().getSimpleName();
|
||||
|
||||
public Task(TaskRunner taskHandler, T model) {
|
||||
this.taskHandler = taskHandler;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
abstract protected void run();
|
||||
|
||||
protected void runInterceptHook() {
|
||||
if (getClass() == taskToIntercept)
|
||||
throw new InterceptTaskException("Task intercepted for testing purpose. Task = " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
protected void appendToErrorMessage(String message) {
|
||||
errorMessage += "\n" + message;
|
||||
}
|
||||
|
||||
protected void appendExceptionToErrorMessage(Throwable t) {
|
||||
if (t.getMessage() != null)
|
||||
errorMessage += "\nException message: " + t.getMessage();
|
||||
else
|
||||
errorMessage += "\nException: " + t.toString();
|
||||
}
|
||||
|
||||
protected void complete() {
|
||||
taskHandler.handleComplete();
|
||||
}
|
||||
|
||||
protected void failed(String message) {
|
||||
appendToErrorMessage(message);
|
||||
failed();
|
||||
}
|
||||
|
||||
protected void failed(Throwable t) {
|
||||
t.printStackTrace();
|
||||
appendExceptionToErrorMessage(t);
|
||||
failed();
|
||||
}
|
||||
|
||||
protected void failed() {
|
||||
taskHandler.handleErrorMessage(errorMessage);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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.common.taskrunner;
|
||||
|
||||
import io.bitsquare.common.handlers.ErrorMessageHandler;
|
||||
import io.bitsquare.common.handlers.ResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class TaskRunner<T extends Model> {
|
||||
private static final Logger log = LoggerFactory.getLogger(TaskRunner.class);
|
||||
|
||||
private final Queue<Class<? extends Task>> tasks = new LinkedBlockingQueue<>();
|
||||
private final T sharedModel;
|
||||
private final Class<T> sharedModelClass;
|
||||
private final ResultHandler resultHandler;
|
||||
private final ErrorMessageHandler errorMessageHandler;
|
||||
private boolean failed = false;
|
||||
private boolean isCanceled;
|
||||
|
||||
private Class<? extends Task> currentTask;
|
||||
|
||||
|
||||
public TaskRunner(T sharedModel, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
this(sharedModel, (Class<T>) sharedModel.getClass(), resultHandler, errorMessageHandler);
|
||||
}
|
||||
|
||||
public TaskRunner(T sharedModel, Class<T> sharedModelClass, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
this.sharedModel = sharedModel;
|
||||
this.resultHandler = resultHandler;
|
||||
this.errorMessageHandler = errorMessageHandler;
|
||||
this.sharedModelClass = sharedModelClass;
|
||||
}
|
||||
|
||||
public final void addTasks(Class<? extends Task<T>>... items) {
|
||||
tasks.addAll(Arrays.asList(items));
|
||||
}
|
||||
|
||||
public void run() {
|
||||
next();
|
||||
}
|
||||
|
||||
private void next() {
|
||||
if (!failed && !isCanceled) {
|
||||
if (tasks.size() > 0) {
|
||||
try {
|
||||
currentTask = tasks.poll();
|
||||
log.trace("Run task: " + currentTask.getSimpleName());
|
||||
currentTask.getDeclaredConstructor(TaskRunner.class, sharedModelClass).newInstance(this, sharedModel).run();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
handleErrorMessage("Error at taskRunner: " + throwable.getMessage());
|
||||
}
|
||||
} else {
|
||||
resultHandler.handleResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
isCanceled = true;
|
||||
}
|
||||
|
||||
void handleComplete() {
|
||||
log.trace("Task completed: " + currentTask.getSimpleName());
|
||||
sharedModel.persist();
|
||||
next();
|
||||
}
|
||||
|
||||
void handleErrorMessage(String errorMessage) {
|
||||
log.error("Task failed: " + currentTask.getSimpleName());
|
||||
log.error("errorMessage: " + errorMessage);
|
||||
failed = true;
|
||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.common.util;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface JsonExclude {
|
||||
}
|
34
common/src/main/java/io/bitsquare/common/util/Profiler.java
Normal file
34
common/src/main/java/io/bitsquare/common/util/Profiler.java
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.common.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Profiler {
|
||||
private static final Logger log = LoggerFactory.getLogger(Profiler.class);
|
||||
|
||||
public static void printSystemLoad(Logger log) {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
long free = runtime.freeMemory() / 1024 / 1024;
|
||||
long total = runtime.totalMemory() / 1024 / 1024;
|
||||
long used = total - free;
|
||||
log.info("System load (nr. threads/used memory (MB)): " + Thread.activeCount() + "/" + used);
|
||||
}
|
||||
|
||||
}
|
47
common/src/main/java/io/bitsquare/common/util/Tuple2.java
Normal file
47
common/src/main/java/io/bitsquare/common/util/Tuple2.java
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.common.util;
|
||||
|
||||
public class Tuple2<A, B> {
|
||||
final public A first;
|
||||
final public B second;
|
||||
|
||||
public Tuple2(A first, B second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Tuple2)) return false;
|
||||
|
||||
Tuple2<?, ?> tuple2 = (Tuple2<?, ?>) o;
|
||||
|
||||
if (first != null ? !first.equals(tuple2.first) : tuple2.first != null) return false;
|
||||
return !(second != null ? !second.equals(tuple2.second) : tuple2.second != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = first != null ? first.hashCode() : 0;
|
||||
result = 31 * result + (second != null ? second.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
51
common/src/main/java/io/bitsquare/common/util/Tuple3.java
Normal file
51
common/src/main/java/io/bitsquare/common/util/Tuple3.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.common.util;
|
||||
|
||||
public class Tuple3<A, B, C> {
|
||||
final public A first;
|
||||
final public B second;
|
||||
final public C third;
|
||||
|
||||
public Tuple3(A first, B second, C third) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
this.third = third;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Tuple3)) return false;
|
||||
|
||||
Tuple3<?, ?, ?> tuple3 = (Tuple3<?, ?, ?>) o;
|
||||
|
||||
if (first != null ? !first.equals(tuple3.first) : tuple3.first != null) return false;
|
||||
if (second != null ? !second.equals(tuple3.second) : tuple3.second != null) return false;
|
||||
return !(third != null ? !third.equals(tuple3.third) : tuple3.third != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = first != null ? first.hashCode() : 0;
|
||||
result = 31 * result + (second != null ? second.hashCode() : 0);
|
||||
result = 31 * result + (third != null ? third.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
84
core/src/main/java/io/bitsquare/alert/Alert.java
Normal file
84
core/src/main/java/io/bitsquare/alert/Alert.java
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.alert;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.p2p.storage.data.PubKeyProtectedExpirablePayload;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
public final class Alert implements PubKeyProtectedExpirablePayload {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
public static final long TTL = 10 * 24 * 60 * 60 * 1000; // 10 days
|
||||
|
||||
public final String message;
|
||||
private String signatureAsBase64;
|
||||
private PublicKey storagePublicKey;
|
||||
|
||||
public Alert(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public void setSigAndStoragePubKey(String signatureAsBase64, PublicKey storagePublicKey) {
|
||||
this.signatureAsBase64 = signatureAsBase64;
|
||||
this.storagePublicKey = storagePublicKey;
|
||||
}
|
||||
|
||||
public String getSignatureAsBase64() {
|
||||
return signatureAsBase64;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTTL() {
|
||||
return TTL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublicKey getPubKey() {
|
||||
return storagePublicKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Alert)) return false;
|
||||
|
||||
Alert that = (Alert) o;
|
||||
|
||||
if (message != null ? !message.equals(that.message) : that.message != null) return false;
|
||||
return !(getSignatureAsBase64() != null ? !getSignatureAsBase64().equals(that.getSignatureAsBase64()) : that.getSignatureAsBase64() != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = message != null ? message.hashCode() : 0;
|
||||
result = 31 * result + (getSignatureAsBase64() != null ? getSignatureAsBase64().hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AlertMessage{" +
|
||||
"message='" + message + '\'' +
|
||||
", signature.hashCode()='" + signatureAsBase64.hashCode() + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
144
core/src/main/java/io/bitsquare/alert/AlertManager.java
Normal file
144
core/src/main/java/io/bitsquare/alert/AlertManager.java
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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.alert;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.common.crypto.KeyRing;
|
||||
import io.bitsquare.p2p.storage.HashSetChangedListener;
|
||||
import io.bitsquare.p2p.storage.data.ProtectedData;
|
||||
import io.bitsquare.user.User;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.core.Utils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.security.SignatureException;
|
||||
|
||||
import static org.bitcoinj.core.Utils.HEX;
|
||||
|
||||
public class AlertManager {
|
||||
transient private static final Logger log = LoggerFactory.getLogger(AlertManager.class);
|
||||
|
||||
private final AlertService alertService;
|
||||
private KeyRing keyRing;
|
||||
private User user;
|
||||
private final ObjectProperty<Alert> alertMessageProperty = new SimpleObjectProperty<>();
|
||||
|
||||
// Pub key for developer global alert message
|
||||
private static final String devPubKeyAsHex = "02682880ae61fc1ea9375198bf2b5594fc3ed28074d3f5f0ed907e38acc5fb1fdc";
|
||||
private ECKey alertSigningKey;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public AlertManager(AlertService alertService, KeyRing keyRing, User user) {
|
||||
this.alertService = alertService;
|
||||
this.keyRing = keyRing;
|
||||
this.user = user;
|
||||
|
||||
alertService.addHashSetChangedListener(new HashSetChangedListener() {
|
||||
@Override
|
||||
public void onAdded(ProtectedData entry) {
|
||||
Serializable data = entry.expirablePayload;
|
||||
if (data instanceof Alert) {
|
||||
Alert alert = (Alert) data;
|
||||
if (verifySignature(alert))
|
||||
alertMessageProperty.set(alert);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoved(ProtectedData entry) {
|
||||
Serializable data = entry.expirablePayload;
|
||||
if (data instanceof Alert) {
|
||||
Alert alert = (Alert) data;
|
||||
if (verifySignature(alert))
|
||||
alertMessageProperty.set(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public ReadOnlyObjectProperty<Alert> alertMessageProperty() {
|
||||
return alertMessageProperty;
|
||||
}
|
||||
|
||||
public boolean addAlertMessageIfKeyIsValid(Alert alert, String privKeyString) {
|
||||
// if there is a previous message we remove that first
|
||||
if (user.getDevelopersAlert() != null)
|
||||
removeAlertMessageIfKeyIsValid(privKeyString);
|
||||
|
||||
boolean isKeyValid = isKeyValid(privKeyString);
|
||||
if (isKeyValid) {
|
||||
signAndAddSignatureToAlertMessage(alert);
|
||||
user.setDevelopersAlert(alert);
|
||||
alertService.addAlertMessage(alert, null, null);
|
||||
}
|
||||
return isKeyValid;
|
||||
}
|
||||
|
||||
public boolean removeAlertMessageIfKeyIsValid(String privKeyString) {
|
||||
Alert developersAlert = user.getDevelopersAlert();
|
||||
if (isKeyValid(privKeyString) && developersAlert != null) {
|
||||
alertService.removeAlertMessage(developersAlert, null, null);
|
||||
user.setDevelopersAlert(null);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isKeyValid(String privKeyString) {
|
||||
try {
|
||||
alertSigningKey = ECKey.fromPrivate(new BigInteger(1, HEX.decode(privKeyString)));
|
||||
return devPubKeyAsHex.equals(Utils.HEX.encode(alertSigningKey.getPubKey()));
|
||||
} catch (Throwable t) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void signAndAddSignatureToAlertMessage(Alert alert) {
|
||||
String alertMessageAsHex = Utils.HEX.encode(alert.message.getBytes());
|
||||
String signatureAsBase64 = alertSigningKey.signMessage(alertMessageAsHex);
|
||||
alert.setSigAndStoragePubKey(signatureAsBase64, keyRing.getStorageSignatureKeyPair().getPublic());
|
||||
}
|
||||
|
||||
private boolean verifySignature(Alert alert) {
|
||||
String alertMessageAsHex = Utils.HEX.encode(alert.message.getBytes());
|
||||
try {
|
||||
ECKey.fromPublicOnly(HEX.decode(devPubKeyAsHex)).verifyMessage(alertMessageAsHex, alert.getSignatureAsBase64());
|
||||
return true;
|
||||
} catch (SignatureException e) {
|
||||
log.warn("verifySignature failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
38
core/src/main/java/io/bitsquare/alert/AlertModule.java
Normal file
38
core/src/main/java/io/bitsquare/alert/AlertModule.java
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.alert;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
import io.bitsquare.app.AppModule;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
public class AlertModule extends AppModule {
|
||||
private static final Logger log = LoggerFactory.getLogger(AlertModule.class);
|
||||
|
||||
public AlertModule(Environment env) {
|
||||
super(env);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void configure() {
|
||||
bind(AlertManager.class).in(Singleton.class);
|
||||
bind(AlertService.class).in(Singleton.class);
|
||||
}
|
||||
}
|
71
core/src/main/java/io/bitsquare/alert/AlertService.java
Normal file
71
core/src/main/java/io/bitsquare/alert/AlertService.java
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.alert;
|
||||
|
||||
import io.bitsquare.common.handlers.ErrorMessageHandler;
|
||||
import io.bitsquare.common.handlers.ResultHandler;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.p2p.storage.HashSetChangedListener;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Used to load global alert messages.
|
||||
* The message is signed by the project developers private key and use data protection.
|
||||
*/
|
||||
public class AlertService {
|
||||
private static final Logger log = LoggerFactory.getLogger(AlertService.class);
|
||||
private P2PService p2PService;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public AlertService(P2PService p2PService) {
|
||||
this.p2PService = p2PService;
|
||||
}
|
||||
|
||||
public void addHashSetChangedListener(HashSetChangedListener hashSetChangedListener) {
|
||||
p2PService.addHashSetChangedListener(hashSetChangedListener);
|
||||
}
|
||||
|
||||
public void addAlertMessage(Alert alert, @Nullable ResultHandler resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) {
|
||||
boolean result = p2PService.addData(alert);
|
||||
if (result) {
|
||||
log.trace("Add alertMessage to network was successful. AlertMessage = " + alert);
|
||||
if (resultHandler != null) resultHandler.handleResult();
|
||||
} else {
|
||||
if (errorMessageHandler != null) errorMessageHandler.handleErrorMessage("Add alertMessage failed");
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAlertMessage(Alert alert, @Nullable ResultHandler resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) {
|
||||
if (p2PService.removeData(alert)) {
|
||||
log.trace("Remove alertMessage from network was successful. AlertMessage = " + alert);
|
||||
if (resultHandler != null) resultHandler.handleResult();
|
||||
} else {
|
||||
if (errorMessageHandler != null) errorMessageHandler.handleErrorMessage("Remove alertMessage failed");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
* 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.arbitration;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
import io.bitsquare.app.ProgramArguments;
|
||||
import io.bitsquare.common.crypto.KeyRing;
|
||||
import io.bitsquare.common.handlers.ErrorMessageHandler;
|
||||
import io.bitsquare.common.handlers.ResultHandler;
|
||||
import io.bitsquare.p2p.Address;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.p2p.P2PServiceListener;
|
||||
import io.bitsquare.p2p.storage.HashSetChangedListener;
|
||||
import io.bitsquare.p2p.storage.data.ProtectedData;
|
||||
import io.bitsquare.user.User;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableMap;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.core.Utils;
|
||||
import org.reactfx.util.FxTimer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.math.BigInteger;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SignatureException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.bitcoinj.core.Utils.HEX;
|
||||
|
||||
public class ArbitratorManager {
|
||||
transient private static final Logger log = LoggerFactory.getLogger(ArbitratorManager.class);
|
||||
|
||||
private final KeyRing keyRing;
|
||||
private final ArbitratorService arbitratorService;
|
||||
private final User user;
|
||||
private final ObservableMap<Address, Arbitrator> arbitratorsObservableMap = FXCollections.observableHashMap();
|
||||
|
||||
// Keys for invited arbitrators in bootstrapping phase (before registration is open to anyone and security payment is implemented)
|
||||
// For testing purpose here is a private key so anyone can setup an arbitrator for now.
|
||||
// The matching pubkey will be removed once we use real arbitrators.
|
||||
// PrivKey for testing: 6ac43ea1df2a290c1c8391736aa42e4339c5cb4f110ff0257a13b63211977b7a
|
||||
// Matching pubKey: 027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee
|
||||
private static final List<String> publicKeys = new ArrayList<>(Arrays.asList(
|
||||
"03697a499d24f497b3c46bf716318231e46c4e6a685a4e122d8e2a2b229fa1f4b8",
|
||||
"0365c6af94681dbee69de1851f98d4684063bf5c2d64b1c73ed5d90434f375a054",
|
||||
"031c502a60f9dbdb5ae5e438a79819e4e1f417211dd537ac12c9bc23246534c4bd",
|
||||
"02c1e5a242387b6d5319ce27246cea6edaaf51c3550591b528d2578a4753c56c2c",
|
||||
"025c319faf7067d9299590dd6c97fe7e56cd4dac61205ccee1cd1fc390142390a2",
|
||||
"038f6e24c2bfe5d51d0a290f20a9a657c270b94ef2b9c12cd15ca3725fa798fc55",
|
||||
"0255256ff7fb615278c4544a9bbd3f5298b903b8a011cd7889be19b6b1c45cbefe",
|
||||
"024a3a37289f08c910fbd925ebc72b946f33feaeff451a4738ee82037b4cda2e95",
|
||||
"02a88b75e9f0f8afba1467ab26799dcc38fd7a6468fb2795444b425eb43e2c10bd",
|
||||
"02349a51512c1c04c67118386f4d27d768c5195a83247c150a4b722d161722ba81",
|
||||
"03f718a2e0dc672c7cdec0113e72c3322efc70412bb95870750d25c32cd98de17d",
|
||||
"028ff47ee2c56e66313928975c58fa4f1b19a0f81f3a96c4e9c9c3c6768075509e",
|
||||
"02b517c0cbc3a49548f448ddf004ed695c5a1c52ec110be1bfd65fa0ca0761c94b",
|
||||
"03df837a3a0f3d858e82f3356b71d1285327f101f7c10b404abed2abc1c94e7169",
|
||||
"0203a90fb2ab698e524a5286f317a183a84327b8f8c3f7fa4a98fec9e1cefd6b72",
|
||||
"023c99cc073b851c892d8c43329ca3beb5d2213ee87111af49884e3ce66cbd5ba5",
|
||||
"0274f772a98d23e7a0251ab30d7121897b5aebd11a2f1e45ab654aa57503173245",
|
||||
"036d8a1dfcb406886037d2381da006358722823e1940acc2598c844bbc0fd1026f"
|
||||
));
|
||||
private static final String publicKeyForTesting = "027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee";
|
||||
private final boolean isDevTest;
|
||||
private P2PServiceListener p2PServiceListener;
|
||||
|
||||
@Inject
|
||||
public ArbitratorManager(@Named(ProgramArguments.DEV_TEST) boolean isDevTest, KeyRing keyRing, ArbitratorService arbitratorService, User user) {
|
||||
this.isDevTest = isDevTest;
|
||||
this.keyRing = keyRing;
|
||||
this.arbitratorService = arbitratorService;
|
||||
this.user = user;
|
||||
|
||||
arbitratorService.addHashSetChangedListener(new HashSetChangedListener() {
|
||||
@Override
|
||||
public void onAdded(ProtectedData entry) {
|
||||
applyArbitrators();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoved(ProtectedData entry) {
|
||||
applyArbitrators();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onAllServicesInitialized() {
|
||||
if (user.getRegisteredArbitrator() != null) {
|
||||
|
||||
P2PService p2PService = arbitratorService.getP2PService();
|
||||
if (!p2PService.isAuthenticated()) {
|
||||
p2PServiceListener = new P2PServiceListener() {
|
||||
@Override
|
||||
public void onTorNodeReady() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHiddenServiceReady() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetupFailed(Throwable throwable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllDataReceived() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticated() {
|
||||
republishArbitrator();
|
||||
}
|
||||
};
|
||||
p2PService.addP2PServiceListener(p2PServiceListener);
|
||||
|
||||
} else {
|
||||
republishArbitrator();
|
||||
}
|
||||
|
||||
// re-publish periodically
|
||||
FxTimer.runPeriodically(
|
||||
Duration.ofMillis(Arbitrator.TTL / 2),
|
||||
() -> republishArbitrator()
|
||||
);
|
||||
}
|
||||
|
||||
applyArbitrators();
|
||||
}
|
||||
|
||||
private void republishArbitrator() {
|
||||
if (p2PServiceListener != null) arbitratorService.getP2PService().removeP2PServiceListener(p2PServiceListener);
|
||||
|
||||
Arbitrator registeredArbitrator = user.getRegisteredArbitrator();
|
||||
if (registeredArbitrator != null) {
|
||||
addArbitrator(registeredArbitrator,
|
||||
this::applyArbitrators,
|
||||
log::error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void applyArbitrators() {
|
||||
Map<Address, Arbitrator> map = arbitratorService.getArbitrators();
|
||||
log.trace("Arbitrators . size=" + (map.values() != null ? map.values().size() : "0"));
|
||||
arbitratorsObservableMap.clear();
|
||||
Map<Address, Arbitrator> filtered = map.values().stream()
|
||||
.filter(e -> isPublicKeyInList(Utils.HEX.encode(e.getRegistrationPubKey()))
|
||||
&& verifySignature(e.getPubKeyRing().getStorageSignaturePubKey(), e.getRegistrationPubKey(), e.getRegistrationSignature()))
|
||||
.collect(Collectors.toMap(Arbitrator::getArbitratorAddress, Function.identity()));
|
||||
|
||||
arbitratorsObservableMap.putAll(filtered);
|
||||
|
||||
log.debug("filtered arbitrators: " + arbitratorsObservableMap.values());
|
||||
log.trace("user.getAcceptedArbitrators(): " + user.getAcceptedArbitrators().toString());
|
||||
|
||||
// we need to remove accepted arbitrators which are not available anymore
|
||||
if (user.getAcceptedArbitrators() != null) {
|
||||
List<Arbitrator> removeList = user.getAcceptedArbitrators().stream()
|
||||
.filter(e -> !arbitratorsObservableMap.containsValue(e))
|
||||
.collect(Collectors.toList());
|
||||
removeList.stream().forEach(user::removeAcceptedArbitrator);
|
||||
log.trace("removeList arbitrators: " + removeList.toString());
|
||||
log.trace("user.getAcceptedArbitrators(): " + user.getAcceptedArbitrators().toString());
|
||||
|
||||
// if we don't have any arbitrator anymore we set all matching
|
||||
if (user.getAcceptedArbitrators().isEmpty()) {
|
||||
arbitratorsObservableMap.values().stream()
|
||||
.filter(arbitrator -> user.hasMatchingLanguage(arbitrator))
|
||||
.forEach(arbitrator -> user.addAcceptedArbitrator(arbitrator));
|
||||
}
|
||||
|
||||
log.trace("user.getAcceptedArbitrators(): " + user.getAcceptedArbitrators().toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void addArbitrator(Arbitrator arbitrator, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
user.setRegisteredArbitrator(arbitrator);
|
||||
arbitratorsObservableMap.put(arbitrator.getArbitratorAddress(), arbitrator);
|
||||
arbitratorService.addArbitrator(arbitrator,
|
||||
() -> {
|
||||
log.debug("Arbitrator successfully saved in P2P network");
|
||||
resultHandler.handleResult();
|
||||
|
||||
if (arbitratorsObservableMap.size() > 0)
|
||||
FxTimer.runLater(Duration.ofMillis(1000), this::applyArbitrators);
|
||||
},
|
||||
errorMessageHandler::handleErrorMessage);
|
||||
}
|
||||
|
||||
public void removeArbitrator(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
Arbitrator registeredArbitrator = user.getRegisteredArbitrator();
|
||||
if (registeredArbitrator != null) {
|
||||
user.setRegisteredArbitrator(null);
|
||||
arbitratorsObservableMap.remove(registeredArbitrator.getArbitratorAddress());
|
||||
arbitratorService.removeArbitrator(registeredArbitrator,
|
||||
() -> {
|
||||
log.debug("Arbitrator successfully removed from P2P network");
|
||||
resultHandler.handleResult();
|
||||
},
|
||||
errorMessageHandler::handleErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableMap<Address, Arbitrator> getArbitratorsObservableMap() {
|
||||
return arbitratorsObservableMap;
|
||||
}
|
||||
|
||||
// A private key is handed over to selected arbitrators for registration.
|
||||
// An invited arbitrator will sign at registration his storageSignaturePubKey with that private key and attach the signature and pubKey to his data.
|
||||
// Other users will check the signature with the list of public keys hardcoded in the app.
|
||||
public String signStorageSignaturePubKey(ECKey key) {
|
||||
String keyToSignAsHex = Utils.HEX.encode(keyRing.getPubKeyRing().getStorageSignaturePubKey().getEncoded());
|
||||
return key.signMessage(keyToSignAsHex);
|
||||
}
|
||||
|
||||
private boolean verifySignature(PublicKey storageSignaturePubKey, byte[] registrationPubKey, String signature) {
|
||||
String keyToSignAsHex = Utils.HEX.encode(storageSignaturePubKey.getEncoded());
|
||||
try {
|
||||
ECKey key = ECKey.fromPublicOnly(registrationPubKey);
|
||||
key.verifyMessage(keyToSignAsHex, signature);
|
||||
return true;
|
||||
} catch (SignatureException e) {
|
||||
log.warn("verifySignature failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ECKey getRegistrationKey(String privKeyBigIntString) {
|
||||
try {
|
||||
return ECKey.fromPrivate(new BigInteger(1, HEX.decode(privKeyBigIntString)));
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPublicKeyInList(String pubKeyAsHex) {
|
||||
return isDevTest && pubKeyAsHex.equals(publicKeyForTesting) || publicKeys.contains(pubKeyAsHex);
|
||||
}
|
||||
}
|
354
core/src/main/java/io/bitsquare/arbitration/Dispute.java
Normal file
354
core/src/main/java/io/bitsquare/arbitration/Dispute.java
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* 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.arbitration;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.arbitration.messages.DisputeMailMessage;
|
||||
import io.bitsquare.common.crypto.PubKeyRing;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.trade.Contract;
|
||||
import javafx.beans.property.*;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class Dispute implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
transient private static final Logger log = LoggerFactory.getLogger(Dispute.class);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fields
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private final String tradeId;
|
||||
private final int traderId;
|
||||
private final boolean disputeOpenerIsBuyer;
|
||||
private final boolean disputeOpenerIsOfferer;
|
||||
private final long openingDate;
|
||||
private final PubKeyRing traderPubKeyRing;
|
||||
private final long tradeDate;
|
||||
private final Contract contract;
|
||||
private final byte[] contractHash;
|
||||
@Nullable
|
||||
private final byte[] depositTxSerialized;
|
||||
@Nullable
|
||||
private final byte[] payoutTxSerialized;
|
||||
@Nullable
|
||||
private final String depositTxId;
|
||||
@Nullable
|
||||
private final String payoutTxId;
|
||||
private final String contractAsJson;
|
||||
private final String offererContractSignature;
|
||||
private final String takerContractSignature;
|
||||
private final PubKeyRing arbitratorPubKeyRing;
|
||||
private final boolean isSupportTicket;
|
||||
|
||||
private final List<DisputeMailMessage> disputeMailMessages = new ArrayList<>();
|
||||
|
||||
private boolean isClosed;
|
||||
private DisputeResult disputeResult;
|
||||
|
||||
transient private Storage<DisputeList<Dispute>> storage;
|
||||
transient private ObservableList<DisputeMailMessage> disputeMailMessagesAsObservableList = FXCollections.observableArrayList(disputeMailMessages);
|
||||
transient private BooleanProperty isClosedProperty = new SimpleBooleanProperty(isClosed);
|
||||
transient private ObjectProperty<DisputeResult> disputeResultProperty = new SimpleObjectProperty<>(disputeResult);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Dispute(Storage<DisputeList<Dispute>> storage,
|
||||
String tradeId,
|
||||
int traderId,
|
||||
boolean disputeOpenerIsBuyer,
|
||||
boolean disputeOpenerIsOfferer,
|
||||
PubKeyRing traderPubKeyRing,
|
||||
Date tradeDate,
|
||||
Contract contract,
|
||||
byte[] contractHash,
|
||||
@Nullable byte[] depositTxSerialized,
|
||||
@Nullable byte[] payoutTxSerialized,
|
||||
@Nullable String depositTxId,
|
||||
@Nullable String payoutTxId,
|
||||
String contractAsJson,
|
||||
String offererContractSignature,
|
||||
String takerContractSignature,
|
||||
PubKeyRing arbitratorPubKeyRing,
|
||||
boolean isSupportTicket) {
|
||||
this.storage = storage;
|
||||
this.tradeId = tradeId;
|
||||
this.traderId = traderId;
|
||||
this.disputeOpenerIsBuyer = disputeOpenerIsBuyer;
|
||||
this.disputeOpenerIsOfferer = disputeOpenerIsOfferer;
|
||||
this.traderPubKeyRing = traderPubKeyRing;
|
||||
this.tradeDate = tradeDate.getTime();
|
||||
this.contract = contract;
|
||||
this.contractHash = contractHash;
|
||||
this.depositTxSerialized = depositTxSerialized;
|
||||
this.payoutTxSerialized = payoutTxSerialized;
|
||||
this.depositTxId = depositTxId;
|
||||
this.payoutTxId = payoutTxId;
|
||||
this.contractAsJson = contractAsJson;
|
||||
this.offererContractSignature = offererContractSignature;
|
||||
this.takerContractSignature = takerContractSignature;
|
||||
this.arbitratorPubKeyRing = arbitratorPubKeyRing;
|
||||
this.isSupportTicket = isSupportTicket;
|
||||
this.openingDate = new Date().getTime();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
try {
|
||||
in.defaultReadObject();
|
||||
disputeMailMessagesAsObservableList = FXCollections.observableArrayList(disputeMailMessages);
|
||||
disputeResultProperty = new SimpleObjectProperty<>(disputeResult);
|
||||
isClosedProperty = new SimpleBooleanProperty(isClosed);
|
||||
} catch (Throwable t) {
|
||||
log.trace("Cannot be deserialized." + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void addDisputeMessage(DisputeMailMessage disputeMailMessage) {
|
||||
if (!disputeMailMessages.contains(disputeMailMessage)) {
|
||||
disputeMailMessages.add(disputeMailMessage);
|
||||
disputeMailMessagesAsObservableList.add(disputeMailMessage);
|
||||
storage.queueUpForSave();
|
||||
} else {
|
||||
log.error("disputeMailMessage already exists");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// In case we get the object via the network storage is not set as its transient, so we need to set it.
|
||||
public void setStorage(Storage<DisputeList<Dispute>> storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
public void setIsClosed(boolean isClosed) {
|
||||
this.isClosed = isClosed;
|
||||
isClosedProperty.set(isClosed);
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
public void setDisputeResult(DisputeResult disputeResult) {
|
||||
this.disputeResult = disputeResult;
|
||||
disputeResultProperty.set(disputeResult);
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getTradeId() {
|
||||
return tradeId;
|
||||
}
|
||||
|
||||
public String getShortTradeId() {
|
||||
return tradeId.substring(0, 8);
|
||||
}
|
||||
|
||||
public int getTraderId() {
|
||||
return traderId;
|
||||
}
|
||||
|
||||
public boolean isDisputeOpenerIsBuyer() {
|
||||
return disputeOpenerIsBuyer;
|
||||
}
|
||||
|
||||
public boolean isDisputeOpenerIsOfferer() {
|
||||
return disputeOpenerIsOfferer;
|
||||
}
|
||||
|
||||
public Date getOpeningDate() {
|
||||
return new Date(openingDate);
|
||||
}
|
||||
|
||||
public PubKeyRing getTraderPubKeyRing() {
|
||||
return traderPubKeyRing;
|
||||
}
|
||||
|
||||
public Contract getContract() {
|
||||
return contract;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public byte[] getDepositTxSerialized() {
|
||||
return depositTxSerialized;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public byte[] getPayoutTxSerialized() {
|
||||
return payoutTxSerialized;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDepositTxId() {
|
||||
return depositTxId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getPayoutTxId() {
|
||||
return payoutTxId;
|
||||
}
|
||||
|
||||
public String getContractAsJson() {
|
||||
return contractAsJson;
|
||||
}
|
||||
|
||||
public String getOffererContractSignature() {
|
||||
return offererContractSignature;
|
||||
}
|
||||
|
||||
public String getTakerContractSignature() {
|
||||
return takerContractSignature;
|
||||
}
|
||||
|
||||
public ObservableList<DisputeMailMessage> getDisputeMailMessagesAsObservableList() {
|
||||
return disputeMailMessagesAsObservableList;
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return isClosedProperty.get();
|
||||
}
|
||||
|
||||
public ReadOnlyBooleanProperty isClosedProperty() {
|
||||
return isClosedProperty;
|
||||
}
|
||||
|
||||
public PubKeyRing getArbitratorPubKeyRing() {
|
||||
return arbitratorPubKeyRing;
|
||||
}
|
||||
|
||||
public ObjectProperty<DisputeResult> disputeResultProperty() {
|
||||
return disputeResultProperty;
|
||||
}
|
||||
|
||||
public boolean isSupportTicket() {
|
||||
return isSupportTicket;
|
||||
}
|
||||
|
||||
public byte[] getContractHash() {
|
||||
return contractHash;
|
||||
}
|
||||
|
||||
public Date getTradeDate() {
|
||||
return new Date(tradeDate);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Dispute)) return false;
|
||||
|
||||
Dispute dispute = (Dispute) o;
|
||||
|
||||
if (traderId != dispute.traderId) return false;
|
||||
if (disputeOpenerIsBuyer != dispute.disputeOpenerIsBuyer) return false;
|
||||
if (disputeOpenerIsOfferer != dispute.disputeOpenerIsOfferer) return false;
|
||||
if (openingDate != dispute.openingDate) return false;
|
||||
if (tradeDate != dispute.tradeDate) return false;
|
||||
if (isSupportTicket != dispute.isSupportTicket) return false;
|
||||
if (isClosed != dispute.isClosed) return false;
|
||||
if (tradeId != null ? !tradeId.equals(dispute.tradeId) : dispute.tradeId != null) return false;
|
||||
if (traderPubKeyRing != null ? !traderPubKeyRing.equals(dispute.traderPubKeyRing) : dispute.traderPubKeyRing != null)
|
||||
return false;
|
||||
if (contract != null ? !contract.equals(dispute.contract) : dispute.contract != null) return false;
|
||||
if (!Arrays.equals(contractHash, dispute.contractHash)) return false;
|
||||
if (!Arrays.equals(depositTxSerialized, dispute.depositTxSerialized)) return false;
|
||||
if (!Arrays.equals(payoutTxSerialized, dispute.payoutTxSerialized)) return false;
|
||||
if (depositTxId != null ? !depositTxId.equals(dispute.depositTxId) : dispute.depositTxId != null) return false;
|
||||
if (payoutTxId != null ? !payoutTxId.equals(dispute.payoutTxId) : dispute.payoutTxId != null) return false;
|
||||
if (contractAsJson != null ? !contractAsJson.equals(dispute.contractAsJson) : dispute.contractAsJson != null)
|
||||
return false;
|
||||
if (offererContractSignature != null ? !offererContractSignature.equals(dispute.offererContractSignature) : dispute.offererContractSignature != null)
|
||||
return false;
|
||||
if (takerContractSignature != null ? !takerContractSignature.equals(dispute.takerContractSignature) : dispute.takerContractSignature != null)
|
||||
return false;
|
||||
if (arbitratorPubKeyRing != null ? !arbitratorPubKeyRing.equals(dispute.arbitratorPubKeyRing) : dispute.arbitratorPubKeyRing != null)
|
||||
return false;
|
||||
if (disputeMailMessages != null ? !disputeMailMessages.equals(dispute.disputeMailMessages) : dispute.disputeMailMessages != null)
|
||||
return false;
|
||||
return !(disputeResult != null ? !disputeResult.equals(dispute.disputeResult) : dispute.disputeResult != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = tradeId != null ? tradeId.hashCode() : 0;
|
||||
result = 31 * result + traderId;
|
||||
result = 31 * result + (disputeOpenerIsBuyer ? 1 : 0);
|
||||
result = 31 * result + (disputeOpenerIsOfferer ? 1 : 0);
|
||||
result = 31 * result + (int) (openingDate ^ (openingDate >>> 32));
|
||||
result = 31 * result + (traderPubKeyRing != null ? traderPubKeyRing.hashCode() : 0);
|
||||
result = 31 * result + (int) (tradeDate ^ (tradeDate >>> 32));
|
||||
result = 31 * result + (contract != null ? contract.hashCode() : 0);
|
||||
result = 31 * result + (contractHash != null ? Arrays.hashCode(contractHash) : 0);
|
||||
result = 31 * result + (depositTxSerialized != null ? Arrays.hashCode(depositTxSerialized) : 0);
|
||||
result = 31 * result + (payoutTxSerialized != null ? Arrays.hashCode(payoutTxSerialized) : 0);
|
||||
result = 31 * result + (depositTxId != null ? depositTxId.hashCode() : 0);
|
||||
result = 31 * result + (payoutTxId != null ? payoutTxId.hashCode() : 0);
|
||||
result = 31 * result + (contractAsJson != null ? contractAsJson.hashCode() : 0);
|
||||
result = 31 * result + (offererContractSignature != null ? offererContractSignature.hashCode() : 0);
|
||||
result = 31 * result + (takerContractSignature != null ? takerContractSignature.hashCode() : 0);
|
||||
result = 31 * result + (arbitratorPubKeyRing != null ? arbitratorPubKeyRing.hashCode() : 0);
|
||||
result = 31 * result + (isSupportTicket ? 1 : 0);
|
||||
result = 31 * result + (disputeMailMessages != null ? disputeMailMessages.hashCode() : 0);
|
||||
result = 31 * result + (isClosed ? 1 : 0);
|
||||
result = 31 * result + (disputeResult != null ? disputeResult.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Dispute{" +
|
||||
", tradeId='" + tradeId + '\'' +
|
||||
", traderId='" + traderId + '\'' +
|
||||
", disputeOpenerIsBuyer=" + disputeOpenerIsBuyer +
|
||||
", disputeOpenerIsOfferer=" + disputeOpenerIsOfferer +
|
||||
", openingDate=" + openingDate +
|
||||
", traderPubKeyRing=" + traderPubKeyRing +
|
||||
", contract=" + contract +
|
||||
", contractAsJson='" + contractAsJson + '\'' +
|
||||
", buyerContractSignature='" + offererContractSignature + '\'' +
|
||||
", sellerContractSignature='" + takerContractSignature + '\'' +
|
||||
", arbitratorPubKeyRing=" + arbitratorPubKeyRing +
|
||||
", disputeMailMessages=" + disputeMailMessages +
|
||||
", disputeMailMessagesAsObservableList=" + disputeMailMessagesAsObservableList +
|
||||
", isClosed=" + isClosed +
|
||||
", disputeResult=" + disputeResult +
|
||||
", disputeResultProperty=" + disputeResultProperty +
|
||||
'}';
|
||||
}
|
||||
}
|
93
core/src/main/java/io/bitsquare/arbitration/DisputeList.java
Normal file
93
core/src/main/java/io/bitsquare/arbitration/DisputeList.java
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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.arbitration;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DisputeList<DisputeCase> extends ArrayList<DisputeCase> implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DisputeList.class);
|
||||
|
||||
final transient private Storage<DisputeList<DisputeCase>> storage;
|
||||
transient private ObservableList<DisputeCase> observableList;
|
||||
|
||||
public DisputeList(Storage<DisputeList<DisputeCase>> storage) {
|
||||
this.storage = storage;
|
||||
|
||||
DisputeList persisted = storage.initAndGetPersisted(this);
|
||||
if (persisted != null) {
|
||||
this.addAll(persisted);
|
||||
}
|
||||
observableList = FXCollections.observableArrayList(this);
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
try {
|
||||
in.defaultReadObject();
|
||||
} catch (Throwable t) {
|
||||
log.trace("Cannot be deserialized." + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(DisputeCase disputeCase) {
|
||||
if (!super.contains(disputeCase)) {
|
||||
boolean result = super.add(disputeCase);
|
||||
getObservableList().add(disputeCase);
|
||||
storage.queueUpForSave();
|
||||
return result;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object disputeCase) {
|
||||
boolean result = super.remove(disputeCase);
|
||||
getObservableList().remove(disputeCase);
|
||||
storage.queueUpForSave();
|
||||
return result;
|
||||
}
|
||||
|
||||
private ObservableList<DisputeCase> getObservableList() {
|
||||
if (observableList == null)
|
||||
observableList = FXCollections.observableArrayList(this);
|
||||
return observableList;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DisputeList{" +
|
||||
", observableList=" + observableList +
|
||||
'}';
|
||||
}
|
||||
}
|
608
core/src/main/java/io/bitsquare/arbitration/DisputeManager.java
Normal file
608
core/src/main/java/io/bitsquare/arbitration/DisputeManager.java
Normal file
|
@ -0,0 +1,608 @@
|
|||
/*
|
||||
* 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.arbitration;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.arbitration.messages.*;
|
||||
import io.bitsquare.btc.TradeWalletService;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.btc.exceptions.TransactionVerificationException;
|
||||
import io.bitsquare.btc.exceptions.WalletException;
|
||||
import io.bitsquare.common.crypto.KeyRing;
|
||||
import io.bitsquare.common.crypto.PubKeyRing;
|
||||
import io.bitsquare.p2p.Address;
|
||||
import io.bitsquare.p2p.Message;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.p2p.P2PServiceListener;
|
||||
import io.bitsquare.p2p.messaging.DecryptedMessageWithPubKey;
|
||||
import io.bitsquare.p2p.messaging.SendMailboxMessageListener;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.trade.Contract;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
import io.bitsquare.trade.offer.OpenOffer;
|
||||
import io.bitsquare.trade.offer.OpenOfferManager;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.bitcoinj.core.AddressFormatException;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Named;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DisputeManager {
|
||||
private static final Logger log = LoggerFactory.getLogger(DisputeManager.class);
|
||||
|
||||
private final TradeWalletService tradeWalletService;
|
||||
private final WalletService walletService;
|
||||
private final TradeManager tradeManager;
|
||||
private final OpenOfferManager openOfferManager;
|
||||
private final P2PService p2PService;
|
||||
private final KeyRing keyRing;
|
||||
private final Storage<DisputeList<Dispute>> disputeStorage;
|
||||
private final DisputeList<Dispute> disputes;
|
||||
transient private final ObservableList<Dispute> disputesObservableList;
|
||||
private final String disputeInfo;
|
||||
private final P2PServiceListener p2PServiceListener;
|
||||
private final List<DecryptedMessageWithPubKey> decryptedMailboxMessageWithPubKeys = new CopyOnWriteArrayList<>();
|
||||
private final List<DecryptedMessageWithPubKey> decryptedMailMessageWithPubKeys = new CopyOnWriteArrayList<>();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public DisputeManager(P2PService p2PService,
|
||||
TradeWalletService tradeWalletService,
|
||||
WalletService walletService,
|
||||
TradeManager tradeManager,
|
||||
OpenOfferManager openOfferManager,
|
||||
KeyRing keyRing,
|
||||
@Named("storage.dir") File storageDir) {
|
||||
this.p2PService = p2PService;
|
||||
this.tradeWalletService = tradeWalletService;
|
||||
this.walletService = walletService;
|
||||
this.tradeManager = tradeManager;
|
||||
this.openOfferManager = openOfferManager;
|
||||
this.keyRing = keyRing;
|
||||
|
||||
disputeStorage = new Storage<>(storageDir);
|
||||
disputes = new DisputeList<>(disputeStorage);
|
||||
disputesObservableList = FXCollections.observableArrayList(disputes);
|
||||
disputes.stream().forEach(e -> e.setStorage(getDisputeStorage()));
|
||||
|
||||
disputeInfo = "Please note the basic rules for the dispute process:\n" +
|
||||
"1. You need to respond to the arbitrators requests in between 2 days.\n" +
|
||||
"2. The maximum period for the dispute is 14 days.\n" +
|
||||
"3. You need to fulfill what the arbitrator is requesting from you to deliver evidence for your case.\n" +
|
||||
"4. You accepted the rules outlined in the wiki in the user agreement when you first started the application.\n\n" +
|
||||
"Please read more in detail about the dispute process in our wiki:\nhttps://github" +
|
||||
".com/bitsquare/bitsquare/wiki/Dispute-process";
|
||||
|
||||
p2PService.addDecryptedMailListener((decryptedMessageWithPubKey, senderAddress) -> {
|
||||
decryptedMailMessageWithPubKeys.add(decryptedMessageWithPubKey);
|
||||
if (p2PService.isAuthenticated())
|
||||
applyMessages();
|
||||
});
|
||||
p2PService.addDecryptedMailboxListener((decryptedMessageWithPubKey, senderAddress) -> {
|
||||
decryptedMailboxMessageWithPubKeys.add(decryptedMessageWithPubKey);
|
||||
if (p2PService.isAuthenticated())
|
||||
applyMessages();
|
||||
});
|
||||
|
||||
p2PServiceListener = new P2PServiceListener() {
|
||||
@Override
|
||||
public void onTorNodeReady() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHiddenServiceReady() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetupFailed(Throwable throwable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllDataReceived() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticated() {
|
||||
applyMessages();
|
||||
}
|
||||
};
|
||||
p2PService.addP2PServiceListener(p2PServiceListener);
|
||||
}
|
||||
|
||||
private void applyMessages() {
|
||||
decryptedMailMessageWithPubKeys.forEach(decryptedMessageWithPubKey -> {
|
||||
Message message = decryptedMessageWithPubKey.message;
|
||||
if (message instanceof DisputeMessage)
|
||||
dispatchMessage((DisputeMessage) message);
|
||||
});
|
||||
decryptedMailMessageWithPubKeys.clear();
|
||||
|
||||
decryptedMailboxMessageWithPubKeys.forEach(decryptedMessageWithPubKey -> {
|
||||
Message message = decryptedMessageWithPubKey.message;
|
||||
log.debug("decryptedMessageWithPubKey.message " + message);
|
||||
if (message instanceof DisputeMessage) {
|
||||
dispatchMessage((DisputeMessage) message);
|
||||
p2PService.removeEntryFromMailbox(decryptedMessageWithPubKey);
|
||||
}
|
||||
});
|
||||
decryptedMailboxMessageWithPubKeys.clear();
|
||||
|
||||
p2PService.removeP2PServiceListener(p2PServiceListener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onAllServicesInitialized() {
|
||||
}
|
||||
|
||||
private void dispatchMessage(DisputeMessage message) {
|
||||
if (message instanceof OpenNewDisputeMessage)
|
||||
onOpenNewDisputeMessage((OpenNewDisputeMessage) message);
|
||||
else if (message instanceof PeerOpenedDisputeMessage)
|
||||
onPeerOpenedDisputeMessage((PeerOpenedDisputeMessage) message);
|
||||
else if (message instanceof DisputeMailMessage)
|
||||
onDisputeMailMessage((DisputeMailMessage) message);
|
||||
else if (message instanceof DisputeResultMessage)
|
||||
onDisputeResultMessage((DisputeResultMessage) message);
|
||||
else if (message instanceof PeerPublishedPayoutTxMessage)
|
||||
onDisputedPayoutTxMessage((PeerPublishedPayoutTxMessage) message);
|
||||
}
|
||||
|
||||
public void sendOpenNewDisputeMessage(Dispute dispute) {
|
||||
if (!disputes.contains(dispute)) {
|
||||
DisputeMailMessage disputeMailMessage = new DisputeMailMessage(dispute.getTradeId(),
|
||||
keyRing.getPubKeyRing().hashCode(),
|
||||
true,
|
||||
"System message: " + (dispute.isSupportTicket() ?
|
||||
"You opened a request for support."
|
||||
: "You opened a request for a dispute.\n\n" + disputeInfo),
|
||||
p2PService.getAddress());
|
||||
disputeMailMessage.setIsSystemMessage(true);
|
||||
dispute.addDisputeMessage(disputeMailMessage);
|
||||
disputes.add(dispute);
|
||||
disputesObservableList.add(dispute);
|
||||
|
||||
p2PService.sendEncryptedMailboxMessage(dispute.getContract().arbitratorAddress,
|
||||
dispute.getArbitratorPubKeyRing(),
|
||||
new OpenNewDisputeMessage(dispute, p2PService.getAddress()),
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
disputeMailMessage.setArrived(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
disputeMailMessage.setStoredInMailbox(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault() {
|
||||
log.error("sendEncryptedMessage failed");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
} else {
|
||||
log.warn("We got a dispute msg what we have already stored. TradeId = " + dispute.getTradeId());
|
||||
}
|
||||
}
|
||||
|
||||
// arbitrator sends that to trading peer when he received openDispute request
|
||||
private void sendPeerOpenedDisputeMessage(Dispute disputeFromOpener) {
|
||||
Contract contractFromOpener = disputeFromOpener.getContract();
|
||||
PubKeyRing pubKeyRing = disputeFromOpener.isDisputeOpenerIsBuyer() ? contractFromOpener.getSellerPubKeyRing() : contractFromOpener.getBuyerPubKeyRing();
|
||||
Dispute dispute = new Dispute(
|
||||
disputeStorage,
|
||||
disputeFromOpener.getTradeId(),
|
||||
pubKeyRing.hashCode(),
|
||||
!disputeFromOpener.isDisputeOpenerIsBuyer(),
|
||||
!disputeFromOpener.isDisputeOpenerIsOfferer(),
|
||||
pubKeyRing,
|
||||
disputeFromOpener.getTradeDate(),
|
||||
contractFromOpener,
|
||||
disputeFromOpener.getContractHash(),
|
||||
disputeFromOpener.getDepositTxSerialized(),
|
||||
disputeFromOpener.getPayoutTxSerialized(),
|
||||
disputeFromOpener.getDepositTxId(),
|
||||
disputeFromOpener.getPayoutTxId(),
|
||||
disputeFromOpener.getContractAsJson(),
|
||||
disputeFromOpener.getOffererContractSignature(),
|
||||
disputeFromOpener.getTakerContractSignature(),
|
||||
disputeFromOpener.getArbitratorPubKeyRing(),
|
||||
disputeFromOpener.isSupportTicket()
|
||||
);
|
||||
DisputeMailMessage disputeMailMessage = new DisputeMailMessage(dispute.getTradeId(),
|
||||
keyRing.getPubKeyRing().hashCode(),
|
||||
true,
|
||||
"System message: " + (dispute.isSupportTicket() ?
|
||||
"Your trading peer has requested support due technical problems. Please wait for further instructions."
|
||||
: "Your trading peer has requested a dispute.\n\n" + disputeInfo),
|
||||
p2PService.getAddress());
|
||||
disputeMailMessage.setIsSystemMessage(true);
|
||||
dispute.addDisputeMessage(disputeMailMessage);
|
||||
disputes.add(dispute);
|
||||
disputesObservableList.add(dispute);
|
||||
|
||||
// we mirrored dispute already!
|
||||
Contract contract = dispute.getContract();
|
||||
PubKeyRing peersPubKeyRing = dispute.isDisputeOpenerIsBuyer() ? contract.getBuyerPubKeyRing() : contract.getSellerPubKeyRing();
|
||||
Address peerAddress = dispute.isDisputeOpenerIsBuyer() ? contract.getBuyerAddress() : contract.getSellerAddress();
|
||||
log.trace("sendPeerOpenedDisputeMessage to peerAddress " + peerAddress);
|
||||
p2PService.sendEncryptedMailboxMessage(peerAddress,
|
||||
peersPubKeyRing,
|
||||
new PeerOpenedDisputeMessage(dispute, p2PService.getAddress()),
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
disputeMailMessage.setArrived(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
disputeMailMessage.setStoredInMailbox(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault() {
|
||||
log.error("sendEncryptedMessage failed");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// traders send msg to the arbitrator or arbitrator to 1 trader (trader to trader is not allowed)
|
||||
public DisputeMailMessage sendDisputeMailMessage(Dispute dispute, String text, ArrayList<DisputeMailMessage.Attachment> attachments) {
|
||||
DisputeMailMessage disputeMailMessage = new DisputeMailMessage(dispute.getTradeId(),
|
||||
dispute.getTraderPubKeyRing().hashCode(),
|
||||
isTrader(dispute),
|
||||
text,
|
||||
p2PService.getAddress());
|
||||
disputeMailMessage.addAllAttachments(attachments);
|
||||
PubKeyRing receiverPubKeyRing = null;
|
||||
Address peerAddress = null;
|
||||
if (isTrader(dispute)) {
|
||||
dispute.addDisputeMessage(disputeMailMessage);
|
||||
receiverPubKeyRing = dispute.getArbitratorPubKeyRing();
|
||||
peerAddress = dispute.getContract().arbitratorAddress;
|
||||
} else if (isArbitrator(dispute)) {
|
||||
if (!disputeMailMessage.isSystemMessage())
|
||||
dispute.addDisputeMessage(disputeMailMessage);
|
||||
receiverPubKeyRing = dispute.getTraderPubKeyRing();
|
||||
Contract contract = dispute.getContract();
|
||||
if (contract.getBuyerPubKeyRing().equals(receiverPubKeyRing))
|
||||
peerAddress = contract.getBuyerAddress();
|
||||
else
|
||||
peerAddress = contract.getSellerAddress();
|
||||
} else {
|
||||
log.error("That must not happen. Trader cannot communicate to other trader.");
|
||||
}
|
||||
if (receiverPubKeyRing != null) {
|
||||
log.trace("sendDisputeMailMessage to peerAddress " + peerAddress);
|
||||
p2PService.sendEncryptedMailboxMessage(peerAddress,
|
||||
receiverPubKeyRing,
|
||||
disputeMailMessage,
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
disputeMailMessage.setArrived(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
disputeMailMessage.setStoredInMailbox(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault() {
|
||||
log.error("sendEncryptedMessage failed");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return disputeMailMessage;
|
||||
}
|
||||
|
||||
// arbitrator send result to trader
|
||||
public void sendDisputeResultMessage(DisputeResult disputeResult, Dispute dispute, String text) {
|
||||
DisputeMailMessage disputeMailMessage = new DisputeMailMessage(dispute.getTradeId(),
|
||||
dispute.getTraderPubKeyRing().hashCode(),
|
||||
false,
|
||||
text,
|
||||
p2PService.getAddress());
|
||||
dispute.addDisputeMessage(disputeMailMessage);
|
||||
disputeResult.setResultMailMessage(disputeMailMessage);
|
||||
|
||||
Address peerAddress;
|
||||
Contract contract = dispute.getContract();
|
||||
if (contract.getBuyerPubKeyRing().equals(dispute.getTraderPubKeyRing()))
|
||||
peerAddress = contract.getBuyerAddress();
|
||||
else
|
||||
peerAddress = contract.getSellerAddress();
|
||||
p2PService.sendEncryptedMailboxMessage(peerAddress,
|
||||
dispute.getTraderPubKeyRing(),
|
||||
new DisputeResultMessage(disputeResult, p2PService.getAddress()),
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
disputeMailMessage.setArrived(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
disputeMailMessage.setStoredInMailbox(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault() {
|
||||
log.error("sendEncryptedMessage failed");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// winner (or buyer in case of 50/50) sends tx to other peer
|
||||
private void sendPeerPublishedPayoutTxMessage(Transaction transaction, Dispute dispute, Contract contract) {
|
||||
PubKeyRing peersPubKeyRing = dispute.isDisputeOpenerIsBuyer() ? contract.getSellerPubKeyRing() : contract.getBuyerPubKeyRing();
|
||||
Address peerAddress = dispute.isDisputeOpenerIsBuyer() ? contract.getSellerAddress() : contract.getBuyerAddress();
|
||||
log.trace("sendPeerPublishedPayoutTxMessage to peerAddress " + peerAddress);
|
||||
p2PService.sendEncryptedMailboxMessage(peerAddress,
|
||||
peersPubKeyRing,
|
||||
new PeerPublishedPayoutTxMessage(transaction.bitcoinSerialize(), dispute.getTradeId(), p2PService.getAddress()),
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault() {
|
||||
log.error("sendEncryptedMessage failed");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Incoming message
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// arbitrator receives that from trader who opens dispute
|
||||
private void onOpenNewDisputeMessage(OpenNewDisputeMessage openNewDisputeMessage) {
|
||||
Dispute dispute = openNewDisputeMessage.dispute;
|
||||
if (isArbitrator(dispute)) {
|
||||
if (!disputes.contains(dispute)) {
|
||||
dispute.setStorage(getDisputeStorage());
|
||||
disputes.add(dispute);
|
||||
disputesObservableList.add(dispute);
|
||||
sendPeerOpenedDisputeMessage(dispute);
|
||||
} else {
|
||||
log.warn("We got a dispute msg what we have already stored. TradeId = " + dispute.getTradeId());
|
||||
}
|
||||
} else {
|
||||
log.error("Trader received openNewDisputeMessage. That must never happen.");
|
||||
}
|
||||
}
|
||||
|
||||
// not dispute requester receives that from arbitrator
|
||||
private void onPeerOpenedDisputeMessage(PeerOpenedDisputeMessage peerOpenedDisputeMessage) {
|
||||
Dispute dispute = peerOpenedDisputeMessage.dispute;
|
||||
if (!isArbitrator(dispute)) {
|
||||
Optional<Trade> tradeOptional = tradeManager.getTradeById(dispute.getTradeId());
|
||||
if (tradeOptional.isPresent())
|
||||
tradeOptional.get().setDisputeState(Trade.DisputeState.DISPUTE_STARTED_BY_PEER);
|
||||
|
||||
if (!disputes.contains(dispute)) {
|
||||
dispute.setStorage(getDisputeStorage());
|
||||
disputes.add(dispute);
|
||||
disputesObservableList.add(dispute);
|
||||
} else {
|
||||
log.warn("We got a dispute msg what we have already stored. TradeId = " + dispute.getTradeId());
|
||||
}
|
||||
} else {
|
||||
log.error("Arbitrator received peerOpenedDisputeMessage. That must never happen.");
|
||||
}
|
||||
}
|
||||
|
||||
// a trader can receive a msg from the arbitrator or the arbitrator form a trader. Trader to trader is not allowed.
|
||||
private void onDisputeMailMessage(DisputeMailMessage disputeMailMessage) {
|
||||
log.debug("onDisputeMailMessage " + disputeMailMessage);
|
||||
Optional<Dispute> disputeOptional = findDispute(disputeMailMessage.getTradeId(), disputeMailMessage.getTraderId());
|
||||
if (disputeOptional.isPresent()) {
|
||||
Dispute dispute = disputeOptional.get();
|
||||
if (!dispute.getDisputeMailMessagesAsObservableList().contains(disputeMailMessage))
|
||||
dispute.addDisputeMessage(disputeMailMessage);
|
||||
else
|
||||
log.warn("We got a dispute mail msg what we have already stored. TradeId = " + disputeMailMessage.getTradeId());
|
||||
} else {
|
||||
log.warn("We got a dispute mail msg but we don't have a matching dispute. TradeId = " + disputeMailMessage.getTradeId());
|
||||
}
|
||||
}
|
||||
|
||||
// We get that message at both peers. The dispute object is in context of the trader
|
||||
private void onDisputeResultMessage(DisputeResultMessage disputeResultMessage) {
|
||||
DisputeResult disputeResult = disputeResultMessage.disputeResult;
|
||||
if (!isArbitrator(disputeResult)) {
|
||||
Optional<Dispute> disputeOptional = findDispute(disputeResult.tradeId, disputeResult.traderId);
|
||||
if (disputeOptional.isPresent()) {
|
||||
Dispute dispute = disputeOptional.get();
|
||||
|
||||
DisputeMailMessage disputeMailMessage = disputeResult.getResultMailMessage();
|
||||
if (!dispute.getDisputeMailMessagesAsObservableList().contains(disputeMailMessage))
|
||||
dispute.addDisputeMessage(disputeMailMessage);
|
||||
else
|
||||
log.warn("We got a dispute mail msg what we have already stored. TradeId = " + disputeMailMessage.getTradeId());
|
||||
|
||||
dispute.setIsClosed(true);
|
||||
if (tradeManager.getTradeById(dispute.getTradeId()).isPresent())
|
||||
tradeManager.closeDisputedTrade(dispute.getTradeId());
|
||||
else {
|
||||
Optional<OpenOffer> openOfferOptional = openOfferManager.getOpenOfferById(dispute.getTradeId());
|
||||
if (openOfferOptional.isPresent())
|
||||
openOfferManager.closeOpenOffer(openOfferOptional.get().getOffer());
|
||||
}
|
||||
|
||||
if (dispute.disputeResultProperty().get() == null) {
|
||||
dispute.setDisputeResult(disputeResult);
|
||||
|
||||
// We need to avoid publishing the tx from both traders as it would create problems with zero confirmation withdrawals
|
||||
// There would be different transactions if both sign and publish (signers: once buyer+arb, once seller+arb)
|
||||
// The tx publisher is the winner or in case both get 50% the buyer, as the buyer has more inventive to publish the tx as he receives
|
||||
// more BTC as he has deposited
|
||||
final Contract contract = dispute.getContract();
|
||||
|
||||
boolean isBuyer = keyRing.getPubKeyRing().equals(contract.getBuyerPubKeyRing());
|
||||
if ((isBuyer && disputeResult.getWinner() == DisputeResult.Winner.BUYER)
|
||||
|| (!isBuyer && disputeResult.getWinner() == DisputeResult.Winner.SELLER)
|
||||
|| (isBuyer && disputeResult.getWinner() == DisputeResult.Winner.STALE_MATE)) {
|
||||
|
||||
if (dispute.getDepositTxSerialized() != null) {
|
||||
try {
|
||||
log.debug("do payout Transaction ");
|
||||
|
||||
Transaction signedDisputedPayoutTx = tradeWalletService.signAndFinalizeDisputedPayoutTx(
|
||||
dispute.getDepositTxSerialized(),
|
||||
disputeResult.getArbitratorSignature(),
|
||||
disputeResult.getBuyerPayoutAmount(),
|
||||
disputeResult.getSellerPayoutAmount(),
|
||||
disputeResult.getArbitratorPayoutAmount(),
|
||||
contract.getBuyerPayoutAddressString(),
|
||||
contract.getSellerPayoutAddressString(),
|
||||
disputeResult.getArbitratorAddressAsString(),
|
||||
walletService.getAddressEntryByOfferId(dispute.getTradeId()),
|
||||
contract.getBuyerBtcPubKey(),
|
||||
contract.getSellerBtcPubKey(),
|
||||
disputeResult.getArbitratorPubKey()
|
||||
);
|
||||
Transaction committedDisputedPayoutTx = tradeWalletService.addTransactionToWallet(signedDisputedPayoutTx);
|
||||
log.debug("broadcast committedDisputedPayoutTx");
|
||||
tradeWalletService.broadcastTx(committedDisputedPayoutTx, new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
log.debug("BroadcastTx succeeded. Transaction:" + transaction);
|
||||
|
||||
// after successful publish we send peer the tx
|
||||
|
||||
sendPeerPublishedPayoutTxMessage(transaction, dispute, contract);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
// TODO error handling
|
||||
log.error(t.getMessage());
|
||||
}
|
||||
});
|
||||
} catch (AddressFormatException | WalletException | TransactionVerificationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
log.warn("DepositTx is null. TradeId = " + disputeResult.tradeId);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("We got a dispute msg what we have already stored. TradeId = " + disputeResult.tradeId);
|
||||
}
|
||||
|
||||
/* DisputeMailMessage disputeMailMessage = disputeResult.getResultMailMessage();
|
||||
if (!dispute.getDisputeMailMessagesAsObservableList().contains(disputeMailMessage))
|
||||
dispute.addDisputeMessage(disputeMailMessage);
|
||||
else
|
||||
log.warn("We got a dispute mail msg what we have already stored. TradeId = " + disputeMailMessage.getTradeId());*/
|
||||
|
||||
} else {
|
||||
log.warn("We got a dispute result msg but we don't have a matching dispute. TradeId = " + disputeResult.tradeId);
|
||||
}
|
||||
} else {
|
||||
log.error("Arbitrator received disputeResultMessage. That must never happen.");
|
||||
}
|
||||
}
|
||||
|
||||
// losing trader or in case of 50/50 the seller gets the tx sent from the winner or buyer
|
||||
private void onDisputedPayoutTxMessage(PeerPublishedPayoutTxMessage peerPublishedPayoutTxMessage) {
|
||||
tradeWalletService.addTransactionToWallet(peerPublishedPayoutTxMessage.transaction);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Storage<DisputeList<Dispute>> getDisputeStorage() {
|
||||
return disputeStorage;
|
||||
}
|
||||
|
||||
public ObservableList<Dispute> getDisputesAsObservableList() {
|
||||
return disputesObservableList;
|
||||
}
|
||||
|
||||
public boolean isTrader(Dispute dispute) {
|
||||
return keyRing.getPubKeyRing().equals(dispute.getTraderPubKeyRing());
|
||||
}
|
||||
|
||||
private boolean isArbitrator(Dispute dispute) {
|
||||
return keyRing.getPubKeyRing().equals(dispute.getArbitratorPubKeyRing());
|
||||
}
|
||||
|
||||
private boolean isArbitrator(DisputeResult disputeResult) {
|
||||
return walletService.getArbitratorAddressEntry().getAddressString().equals(disputeResult.getArbitratorAddressAsString());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private Optional<Dispute> findDispute(String tradeId, int traderId) {
|
||||
return disputes.stream().filter(e -> e.getTradeId().equals(tradeId) && e.getTraderId() == traderId).findFirst();
|
||||
}
|
||||
|
||||
public Optional<Dispute> findOwnDispute(String tradeId) {
|
||||
return disputes.stream().filter(e -> e.getTradeId().equals(tradeId)).findFirst();
|
||||
}
|
||||
|
||||
public List<Dispute> findDisputesByTradeId(String tradeId) {
|
||||
return disputes.stream().filter(e -> e.getTradeId().equals(tradeId)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
265
core/src/main/java/io/bitsquare/arbitration/DisputeResult.java
Normal file
265
core/src/main/java/io/bitsquare/arbitration/DisputeResult.java
Normal file
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* 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.arbitration;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.arbitration.messages.DisputeMailMessage;
|
||||
import javafx.beans.property.*;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
public class DisputeResult implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
transient private static final Logger log = LoggerFactory.getLogger(DisputeResult.class);
|
||||
|
||||
public enum FeePaymentPolicy {
|
||||
LOSER,
|
||||
SPLIT,
|
||||
WAIVE
|
||||
}
|
||||
|
||||
public enum Winner {
|
||||
BUYER,
|
||||
SELLER,
|
||||
STALE_MATE
|
||||
}
|
||||
|
||||
public final String tradeId;
|
||||
public final int traderId;
|
||||
private FeePaymentPolicy feePaymentPolicy;
|
||||
|
||||
private boolean tamperProofEvidence;
|
||||
private boolean idVerification;
|
||||
private boolean screenCast;
|
||||
private String summaryNotes;
|
||||
private DisputeMailMessage resultMailMessage;
|
||||
private byte[] arbitratorSignature;
|
||||
private long buyerPayoutAmount;
|
||||
private long sellerPayoutAmount;
|
||||
private long arbitratorPayoutAmount;
|
||||
private String arbitratorAddressAsString;
|
||||
private byte[] arbitratorPubKey;
|
||||
private long closeDate;
|
||||
private Winner winner;
|
||||
|
||||
transient private BooleanProperty tamperProofEvidenceProperty = new SimpleBooleanProperty();
|
||||
transient private BooleanProperty idVerificationProperty = new SimpleBooleanProperty();
|
||||
transient private BooleanProperty screenCastProperty = new SimpleBooleanProperty();
|
||||
transient private ObjectProperty<FeePaymentPolicy> feePaymentPolicyProperty = new SimpleObjectProperty<>();
|
||||
transient private StringProperty summaryNotesProperty = new SimpleStringProperty();
|
||||
|
||||
public DisputeResult(String tradeId, int traderId) {
|
||||
this.tradeId = tradeId;
|
||||
this.traderId = traderId;
|
||||
|
||||
feePaymentPolicy = FeePaymentPolicy.LOSER;
|
||||
init();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
try {
|
||||
in.defaultReadObject();
|
||||
init();
|
||||
} catch (Throwable t) {
|
||||
log.trace("Cannot be deserialized." + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
tamperProofEvidenceProperty = new SimpleBooleanProperty(tamperProofEvidence);
|
||||
idVerificationProperty = new SimpleBooleanProperty(idVerification);
|
||||
screenCastProperty = new SimpleBooleanProperty(screenCast);
|
||||
feePaymentPolicyProperty = new SimpleObjectProperty<>(feePaymentPolicy);
|
||||
summaryNotesProperty = new SimpleStringProperty(summaryNotes);
|
||||
|
||||
tamperProofEvidenceProperty.addListener((observable, oldValue, newValue) -> {
|
||||
tamperProofEvidence = newValue;
|
||||
});
|
||||
idVerificationProperty.addListener((observable, oldValue, newValue) -> {
|
||||
idVerification = newValue;
|
||||
});
|
||||
screenCastProperty.addListener((observable, oldValue, newValue) -> {
|
||||
screenCast = newValue;
|
||||
});
|
||||
feePaymentPolicyProperty.addListener((observable, oldValue, newValue) -> {
|
||||
feePaymentPolicy = newValue;
|
||||
});
|
||||
summaryNotesProperty.addListener((observable, oldValue, newValue) -> {
|
||||
summaryNotes = newValue;
|
||||
});
|
||||
}
|
||||
|
||||
public BooleanProperty tamperProofEvidenceProperty() {
|
||||
return tamperProofEvidenceProperty;
|
||||
}
|
||||
|
||||
public BooleanProperty idVerificationProperty() {
|
||||
return idVerificationProperty;
|
||||
}
|
||||
|
||||
public BooleanProperty screenCastProperty() {
|
||||
return screenCastProperty;
|
||||
}
|
||||
|
||||
public void setFeePaymentPolicy(FeePaymentPolicy feePaymentPolicy) {
|
||||
this.feePaymentPolicy = feePaymentPolicy;
|
||||
feePaymentPolicyProperty.set(feePaymentPolicy);
|
||||
}
|
||||
|
||||
public ReadOnlyObjectProperty<FeePaymentPolicy> feePaymentPolicyProperty() {
|
||||
return feePaymentPolicyProperty;
|
||||
}
|
||||
|
||||
public FeePaymentPolicy getFeePaymentPolicy() {
|
||||
return feePaymentPolicy;
|
||||
}
|
||||
|
||||
|
||||
public StringProperty summaryNotesProperty() {
|
||||
return summaryNotesProperty;
|
||||
}
|
||||
|
||||
public void setResultMailMessage(DisputeMailMessage resultMailMessage) {
|
||||
this.resultMailMessage = resultMailMessage;
|
||||
}
|
||||
|
||||
public DisputeMailMessage getResultMailMessage() {
|
||||
return resultMailMessage;
|
||||
}
|
||||
|
||||
public void setArbitratorSignature(byte[] arbitratorSignature) {
|
||||
this.arbitratorSignature = arbitratorSignature;
|
||||
}
|
||||
|
||||
public byte[] getArbitratorSignature() {
|
||||
return arbitratorSignature;
|
||||
}
|
||||
|
||||
public void setBuyerPayoutAmount(Coin buyerPayoutAmount) {
|
||||
this.buyerPayoutAmount = buyerPayoutAmount.value;
|
||||
}
|
||||
|
||||
public Coin getBuyerPayoutAmount() {
|
||||
return Coin.valueOf(buyerPayoutAmount);
|
||||
}
|
||||
|
||||
public void setSellerPayoutAmount(Coin sellerPayoutAmount) {
|
||||
this.sellerPayoutAmount = sellerPayoutAmount.value;
|
||||
}
|
||||
|
||||
public Coin getSellerPayoutAmount() {
|
||||
return Coin.valueOf(sellerPayoutAmount);
|
||||
}
|
||||
|
||||
public void setArbitratorPayoutAmount(Coin arbitratorPayoutAmount) {
|
||||
this.arbitratorPayoutAmount = arbitratorPayoutAmount.value;
|
||||
}
|
||||
|
||||
public Coin getArbitratorPayoutAmount() {
|
||||
return Coin.valueOf(arbitratorPayoutAmount);
|
||||
}
|
||||
|
||||
public void setArbitratorAddressAsString(String arbitratorAddressAsString) {
|
||||
this.arbitratorAddressAsString = arbitratorAddressAsString;
|
||||
}
|
||||
|
||||
public String getArbitratorAddressAsString() {
|
||||
return arbitratorAddressAsString;
|
||||
}
|
||||
|
||||
public void setArbitratorPubKey(byte[] arbitratorPubKey) {
|
||||
this.arbitratorPubKey = arbitratorPubKey;
|
||||
}
|
||||
|
||||
public byte[] getArbitratorPubKey() {
|
||||
return arbitratorPubKey;
|
||||
}
|
||||
|
||||
public void setCloseDate(Date closeDate) {
|
||||
this.closeDate = closeDate.getTime();
|
||||
}
|
||||
|
||||
public Date getCloseDate() {
|
||||
return new Date(closeDate);
|
||||
}
|
||||
|
||||
public void setWinner(Winner winner) {
|
||||
this.winner = winner;
|
||||
}
|
||||
|
||||
public Winner getWinner() {
|
||||
return winner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof DisputeResult)) return false;
|
||||
|
||||
DisputeResult that = (DisputeResult) o;
|
||||
|
||||
if (traderId != that.traderId) return false;
|
||||
if (tamperProofEvidence != that.tamperProofEvidence) return false;
|
||||
if (idVerification != that.idVerification) return false;
|
||||
if (screenCast != that.screenCast) return false;
|
||||
if (buyerPayoutAmount != that.buyerPayoutAmount) return false;
|
||||
if (sellerPayoutAmount != that.sellerPayoutAmount) return false;
|
||||
if (arbitratorPayoutAmount != that.arbitratorPayoutAmount) return false;
|
||||
if (closeDate != that.closeDate) return false;
|
||||
if (tradeId != null ? !tradeId.equals(that.tradeId) : that.tradeId != null) return false;
|
||||
if (feePaymentPolicy != that.feePaymentPolicy) return false;
|
||||
if (summaryNotes != null ? !summaryNotes.equals(that.summaryNotes) : that.summaryNotes != null) return false;
|
||||
if (resultMailMessage != null ? !resultMailMessage.equals(that.resultMailMessage) : that.resultMailMessage != null)
|
||||
return false;
|
||||
if (!Arrays.equals(arbitratorSignature, that.arbitratorSignature)) return false;
|
||||
if (arbitratorAddressAsString != null ? !arbitratorAddressAsString.equals(that.arbitratorAddressAsString) : that.arbitratorAddressAsString != null)
|
||||
return false;
|
||||
if (!Arrays.equals(arbitratorPubKey, that.arbitratorPubKey)) return false;
|
||||
return winner == that.winner;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = tradeId != null ? tradeId.hashCode() : 0;
|
||||
result = 31 * result + traderId;
|
||||
result = 31 * result + (feePaymentPolicy != null ? feePaymentPolicy.hashCode() : 0);
|
||||
result = 31 * result + (tamperProofEvidence ? 1 : 0);
|
||||
result = 31 * result + (idVerification ? 1 : 0);
|
||||
result = 31 * result + (screenCast ? 1 : 0);
|
||||
result = 31 * result + (summaryNotes != null ? summaryNotes.hashCode() : 0);
|
||||
result = 31 * result + (resultMailMessage != null ? resultMailMessage.hashCode() : 0);
|
||||
result = 31 * result + (arbitratorSignature != null ? Arrays.hashCode(arbitratorSignature) : 0);
|
||||
result = 31 * result + (int) (buyerPayoutAmount ^ (buyerPayoutAmount >>> 32));
|
||||
result = 31 * result + (int) (sellerPayoutAmount ^ (sellerPayoutAmount >>> 32));
|
||||
result = 31 * result + (int) (arbitratorPayoutAmount ^ (arbitratorPayoutAmount >>> 32));
|
||||
result = 31 * result + (arbitratorAddressAsString != null ? arbitratorAddressAsString.hashCode() : 0);
|
||||
result = 31 * result + (arbitratorPubKey != null ? Arrays.hashCode(arbitratorPubKey) : 0);
|
||||
result = 31 * result + (int) (closeDate ^ (closeDate >>> 32));
|
||||
result = 31 * result + (winner != null ? winner.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* 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.arbitration.messages;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.p2p.Address;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class DisputeMailMessage implements DisputeMessage {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
transient private static final Logger log = LoggerFactory.getLogger(DisputeMailMessage.class);
|
||||
|
||||
private final long date;
|
||||
private final String tradeId;
|
||||
|
||||
private final int traderId;
|
||||
private final boolean senderIsTrader;
|
||||
private final String message;
|
||||
private final List<Attachment> attachments = new ArrayList<>();
|
||||
private boolean arrived;
|
||||
private boolean storedInMailbox;
|
||||
private boolean isSystemMessage;
|
||||
private final Address myAddress;
|
||||
|
||||
transient private BooleanProperty arrivedProperty = new SimpleBooleanProperty();
|
||||
transient private BooleanProperty storedInMailboxProperty = new SimpleBooleanProperty();
|
||||
|
||||
public DisputeMailMessage(String tradeId, int traderId, boolean senderIsTrader, String message, Address myAddress) {
|
||||
this.tradeId = tradeId;
|
||||
this.traderId = traderId;
|
||||
this.senderIsTrader = senderIsTrader;
|
||||
this.message = message;
|
||||
this.myAddress = myAddress;
|
||||
date = new Date().getTime();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
try {
|
||||
in.defaultReadObject();
|
||||
arrivedProperty = new SimpleBooleanProperty(arrived);
|
||||
storedInMailboxProperty = new SimpleBooleanProperty(storedInMailbox);
|
||||
} catch (Throwable t) {
|
||||
log.trace("Cannot be deserialized." + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getSenderAddress() {
|
||||
return myAddress;
|
||||
}
|
||||
|
||||
public void addAttachment(Attachment attachment) {
|
||||
attachments.add(attachment);
|
||||
}
|
||||
|
||||
public void addAllAttachments(List<Attachment> attachments) {
|
||||
this.attachments.addAll(attachments);
|
||||
}
|
||||
|
||||
public void setArrived(boolean arrived) {
|
||||
this.arrived = arrived;
|
||||
this.arrivedProperty.set(arrived);
|
||||
}
|
||||
|
||||
public void setStoredInMailbox(boolean storedInMailbox) {
|
||||
this.storedInMailbox = storedInMailbox;
|
||||
this.storedInMailboxProperty.set(storedInMailbox);
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return new Date(date);
|
||||
}
|
||||
|
||||
public boolean isSenderIsTrader() {
|
||||
return senderIsTrader;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public int getTraderId() {
|
||||
return traderId;
|
||||
}
|
||||
|
||||
public BooleanProperty arrivedProperty() {
|
||||
return arrivedProperty;
|
||||
}
|
||||
|
||||
public BooleanProperty storedInMailboxProperty() {
|
||||
return storedInMailboxProperty;
|
||||
}
|
||||
|
||||
public List<Attachment> getAttachments() {
|
||||
return attachments;
|
||||
}
|
||||
|
||||
public String getTradeId() {
|
||||
return tradeId;
|
||||
}
|
||||
|
||||
public boolean isSystemMessage() {
|
||||
return isSystemMessage;
|
||||
}
|
||||
|
||||
public void setIsSystemMessage(boolean isSystemMessage) {
|
||||
this.isSystemMessage = isSystemMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof DisputeMailMessage)) return false;
|
||||
|
||||
DisputeMailMessage that = (DisputeMailMessage) o;
|
||||
|
||||
if (date != that.date) return false;
|
||||
if (traderId != that.traderId) return false;
|
||||
if (senderIsTrader != that.senderIsTrader) return false;
|
||||
if (arrived != that.arrived) return false;
|
||||
if (storedInMailbox != that.storedInMailbox) return false;
|
||||
if (isSystemMessage != that.isSystemMessage) return false;
|
||||
if (tradeId != null ? !tradeId.equals(that.tradeId) : that.tradeId != null) return false;
|
||||
if (message != null ? !message.equals(that.message) : that.message != null) return false;
|
||||
if (attachments != null ? !attachments.equals(that.attachments) : that.attachments != null) return false;
|
||||
return !(myAddress != null ? !myAddress.equals(that.myAddress) : that.myAddress != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (int) (date ^ (date >>> 32));
|
||||
result = 31 * result + (tradeId != null ? tradeId.hashCode() : 0);
|
||||
result = 31 * result + traderId;
|
||||
result = 31 * result + (senderIsTrader ? 1 : 0);
|
||||
result = 31 * result + (message != null ? message.hashCode() : 0);
|
||||
result = 31 * result + (attachments != null ? attachments.hashCode() : 0);
|
||||
result = 31 * result + (arrived ? 1 : 0);
|
||||
result = 31 * result + (storedInMailbox ? 1 : 0);
|
||||
result = 31 * result + (isSystemMessage ? 1 : 0);
|
||||
result = 31 * result + (myAddress != null ? myAddress.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DisputeMailMessage{" +
|
||||
"date=" + date +
|
||||
", tradeId='" + tradeId + '\'' +
|
||||
", traderId='" + traderId + '\'' +
|
||||
", senderIsTrader=" + senderIsTrader +
|
||||
", message='" + message + '\'' +
|
||||
", attachments=" + attachments +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Static classes
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static class Attachment implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
transient private static final Logger log = LoggerFactory.getLogger(Attachment.class);
|
||||
|
||||
private final byte[] bytes;
|
||||
private final String fileName;
|
||||
|
||||
public Attachment(String fileName, byte[] bytes) {
|
||||
this.fileName = fileName;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Attachment)) return false;
|
||||
|
||||
Attachment that = (Attachment) o;
|
||||
|
||||
if (!Arrays.equals(bytes, that.bytes)) return false;
|
||||
return !(fileName != null ? !fileName.equals(that.fileName) : that.fileName != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = bytes != null ? Arrays.hashCode(bytes) : 0;
|
||||
result = 31 * result + (fileName != null ? fileName.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Attachment{" +
|
||||
"description=" + fileName +
|
||||
", data=" + Arrays.toString(bytes) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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.arbitration.messages;
|
||||
|
||||
import io.bitsquare.p2p.messaging.MailboxMessage;
|
||||
|
||||
public interface DisputeMessage extends MailboxMessage {
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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.arbitration.messages;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.arbitration.DisputeResult;
|
||||
import io.bitsquare.p2p.Address;
|
||||
|
||||
public class DisputeResultMessage implements DisputeMessage {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
public final DisputeResult disputeResult;
|
||||
private final Address myAddress;
|
||||
|
||||
public DisputeResultMessage(DisputeResult disputeResult, Address myAddress) {
|
||||
this.disputeResult = disputeResult;
|
||||
this.myAddress = myAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof DisputeResultMessage)) return false;
|
||||
|
||||
DisputeResultMessage that = (DisputeResultMessage) o;
|
||||
|
||||
if (disputeResult != null ? !disputeResult.equals(that.disputeResult) : that.disputeResult != null)
|
||||
return false;
|
||||
return !(myAddress != null ? !myAddress.equals(that.myAddress) : that.myAddress != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = disputeResult != null ? disputeResult.hashCode() : 0;
|
||||
result = 31 * result + (myAddress != null ? myAddress.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getSenderAddress() {
|
||||
return myAddress;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.arbitration.messages;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.arbitration.Dispute;
|
||||
import io.bitsquare.p2p.Address;
|
||||
|
||||
public class OpenNewDisputeMessage implements DisputeMessage {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
public final Dispute dispute;
|
||||
private final Address myAddress;
|
||||
|
||||
public OpenNewDisputeMessage(Dispute dispute, Address myAddress) {
|
||||
this.dispute = dispute;
|
||||
this.myAddress = myAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof OpenNewDisputeMessage)) return false;
|
||||
|
||||
OpenNewDisputeMessage that = (OpenNewDisputeMessage) o;
|
||||
|
||||
if (dispute != null ? !dispute.equals(that.dispute) : that.dispute != null) return false;
|
||||
return !(myAddress != null ? !myAddress.equals(that.myAddress) : that.myAddress != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = dispute != null ? dispute.hashCode() : 0;
|
||||
result = 31 * result + (myAddress != null ? myAddress.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getSenderAddress() {
|
||||
return myAddress;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.arbitration.messages;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.arbitration.Dispute;
|
||||
import io.bitsquare.p2p.Address;
|
||||
|
||||
public class PeerOpenedDisputeMessage implements DisputeMessage {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
public final Dispute dispute;
|
||||
private final Address myAddress;
|
||||
|
||||
public PeerOpenedDisputeMessage(Dispute dispute, Address myAddress) {
|
||||
this.dispute = dispute;
|
||||
this.myAddress = myAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof PeerOpenedDisputeMessage)) return false;
|
||||
|
||||
PeerOpenedDisputeMessage that = (PeerOpenedDisputeMessage) o;
|
||||
|
||||
if (dispute != null ? !dispute.equals(that.dispute) : that.dispute != null) return false;
|
||||
return !(myAddress != null ? !myAddress.equals(that.myAddress) : that.myAddress != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = dispute != null ? dispute.hashCode() : 0;
|
||||
result = 31 * result + (myAddress != null ? myAddress.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getSenderAddress() {
|
||||
return myAddress;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.arbitration.messages;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.p2p.Address;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PeerPublishedPayoutTxMessage implements DisputeMessage {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
public final byte[] transaction;
|
||||
public final String tradeId;
|
||||
private final Address myAddress;
|
||||
|
||||
public PeerPublishedPayoutTxMessage(byte[] transaction, String tradeId, Address myAddress) {
|
||||
this.transaction = transaction;
|
||||
this.tradeId = tradeId;
|
||||
this.myAddress = myAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof PeerPublishedPayoutTxMessage)) return false;
|
||||
|
||||
PeerPublishedPayoutTxMessage that = (PeerPublishedPayoutTxMessage) o;
|
||||
|
||||
if (!Arrays.equals(transaction, that.transaction)) return false;
|
||||
if (tradeId != null ? !tradeId.equals(that.tradeId) : that.tradeId != null) return false;
|
||||
return !(myAddress != null ? !myAddress.equals(that.myAddress) : that.myAddress != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = transaction != null ? Arrays.hashCode(transaction) : 0;
|
||||
result = 31 * result + (tradeId != null ? tradeId.hashCode() : 0);
|
||||
result = 31 * result + (myAddress != null ? myAddress.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getSenderAddress() {
|
||||
return myAddress;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.btc.data;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
public class InputsAndChangeOutput {
|
||||
public final List<RawInput> rawInputs;
|
||||
|
||||
// Is set to 0L in case we don't have an output
|
||||
public final long changeOutputValue;
|
||||
@Nullable
|
||||
public final String changeOutputAddress;
|
||||
|
||||
public InputsAndChangeOutput(List<RawInput> rawInputs, long changeOutputValue, @Nullable String changeOutputAddress) {
|
||||
checkArgument(!rawInputs.isEmpty(), "rawInputs.isEmpty()");
|
||||
|
||||
this.rawInputs = rawInputs;
|
||||
this.changeOutputValue = changeOutputValue;
|
||||
this.changeOutputAddress = changeOutputAddress;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.btc.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PreparedDepositTxAndOffererInputs {
|
||||
public final List<RawInput> rawOffererInputs;
|
||||
public final byte[] depositTransaction;
|
||||
|
||||
public PreparedDepositTxAndOffererInputs(List<RawInput> rawOffererInputs, byte[] depositTransaction) {
|
||||
this.rawOffererInputs = rawOffererInputs;
|
||||
this.depositTransaction = depositTransaction;
|
||||
}
|
||||
}
|
59
core/src/main/java/io/bitsquare/btc/data/RawInput.java
Normal file
59
core/src/main/java/io/bitsquare/btc/data/RawInput.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.btc.data;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class RawInput implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
public final long index;
|
||||
public final byte[] parentTransaction;
|
||||
public final long value;
|
||||
|
||||
public RawInput(long index, byte[] parentTransaction, long value) {
|
||||
this.index = index;
|
||||
this.parentTransaction = parentTransaction;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof RawInput)) return false;
|
||||
|
||||
RawInput rawInput = (RawInput) o;
|
||||
|
||||
if (index != rawInput.index) return false;
|
||||
if (value != rawInput.value) return false;
|
||||
return Arrays.equals(parentTransaction, rawInput.parentTransaction);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (int) (index ^ (index >>> 32));
|
||||
result = 31 * result + (parentTransaction != null ? Arrays.hashCode(parentTransaction) : 0);
|
||||
result = 31 * result + (int) (value ^ (value >>> 32));
|
||||
return result;
|
||||
}
|
||||
}
|
36
core/src/main/java/io/bitsquare/locale/CryptoCurrency.java
Normal file
36
core/src/main/java/io/bitsquare/locale/CryptoCurrency.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 io.bitsquare.app.Version;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class CryptoCurrency extends TradeCurrency implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
public CryptoCurrency(String currencyCode, String name) {
|
||||
super(currencyCode, name);
|
||||
}
|
||||
|
||||
public CryptoCurrency(String currencyCode, String name, String symbol) {
|
||||
super(currencyCode, name, symbol);
|
||||
}
|
||||
|
||||
}
|
54
core/src/main/java/io/bitsquare/locale/FiatCurrency.java
Normal file
54
core/src/main/java/io/bitsquare/locale/FiatCurrency.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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 io.bitsquare.app.Version;
|
||||
import io.bitsquare.user.Preferences;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Currency;
|
||||
|
||||
public class FiatCurrency extends TradeCurrency implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
private final Currency currency;
|
||||
|
||||
public FiatCurrency(String currencyCode) {
|
||||
this(Currency.getInstance(currencyCode));
|
||||
}
|
||||
|
||||
public FiatCurrency(Currency currency) {
|
||||
super(currency.getCurrencyCode(), currency.getDisplayName(Preferences.getDefaultLocale()), currency.getSymbol());
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
public Currency getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FiatCurrency{" +
|
||||
"currency=" + currency +
|
||||
", code='" + code + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", symbol='" + symbol + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
89
core/src/main/java/io/bitsquare/locale/TradeCurrency.java
Normal file
89
core/src/main/java/io/bitsquare/locale/TradeCurrency.java
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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 io.bitsquare.app.Version;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class TradeCurrency implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
protected final String code;
|
||||
protected final String name;
|
||||
protected String symbol;
|
||||
|
||||
|
||||
public TradeCurrency(String code) {
|
||||
this.code = code;
|
||||
this.name = CurrencyUtil.getNameByCode(code);
|
||||
}
|
||||
|
||||
protected TradeCurrency(String code, String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public TradeCurrency(String code, String name, String symbol) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public String getCodeAndName() {
|
||||
return code + " (" + name + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof TradeCurrency)) return false;
|
||||
|
||||
TradeCurrency that = (TradeCurrency) o;
|
||||
|
||||
return !(getCode() != null ? !getCode().equals(that.getCode()) : that.getCode() != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getCode() != null ? getCode().hashCode() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TradeCurrency{" +
|
||||
"code='" + code + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", symbol='" + symbol + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
43
core/src/main/java/io/bitsquare/payment/AliPayAccount.java
Normal file
43
core/src/main/java/io/bitsquare/payment/AliPayAccount.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.locale.FiatCurrency;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class AliPayAccount extends PaymentAccount implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
public AliPayAccount() {
|
||||
super(PaymentMethod.ALI_PAY);
|
||||
setSingleTradeCurrency(new FiatCurrency("CNY"));
|
||||
|
||||
contractData = new AliPayAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
|
||||
}
|
||||
|
||||
public void setAccountNr(String accountNr) {
|
||||
((AliPayAccountContractData) contractData).setAccountNr(accountNr);
|
||||
}
|
||||
|
||||
public String getAccountNr() {
|
||||
return ((AliPayAccountContractData) contractData).getAccountNr();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class AliPayAccountContractData extends PaymentAccountContractData implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
private String accountNr;
|
||||
|
||||
public AliPayAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
|
||||
super(paymentMethod, id, maxTradePeriod);
|
||||
}
|
||||
|
||||
public void setAccountNr(String accountNr) {
|
||||
this.accountNr = accountNr;
|
||||
}
|
||||
|
||||
public String getAccountNr() {
|
||||
return accountNr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentDetails() {
|
||||
return "AliPay - Account nr.: " + accountNr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AliPayAccountContractData{" +
|
||||
"accountNr='" + accountNr + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class BlockChainAccount extends PaymentAccount implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
|
||||
public BlockChainAccount() {
|
||||
super(PaymentMethod.BLOCK_CHAINS);
|
||||
|
||||
contractData = new BlockChainAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
((BlockChainAccountContractData) contractData).setAddress(address);
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return ((BlockChainAccountContractData) contractData).getAddress();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class BlockChainAccountContractData extends PaymentAccountContractData implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
private String address;
|
||||
private String paymentId;
|
||||
|
||||
public BlockChainAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
|
||||
super(paymentMethod, id, maxTradePeriod);
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentDetails() {
|
||||
return "Address: " + address;
|
||||
}
|
||||
|
||||
public void setPaymentId(String paymentId) {
|
||||
this.paymentId = paymentId;
|
||||
}
|
||||
|
||||
public String getPaymentId() {
|
||||
return paymentId;
|
||||
}
|
||||
}
|
46
core/src/main/java/io/bitsquare/payment/OKPayAccount.java
Normal file
46
core/src/main/java/io/bitsquare/payment/OKPayAccount.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class OKPayAccount extends PaymentAccount implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(OKPayAccount.class);
|
||||
|
||||
public OKPayAccount() {
|
||||
super(PaymentMethod.OK_PAY);
|
||||
tradeCurrencies.addAll(CurrencyUtil.getAllOKPayCurrencies());
|
||||
contractData = new OKPayAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
|
||||
}
|
||||
|
||||
public void setAccountNr(String accountNr) {
|
||||
((OKPayAccountContractData) contractData).setAccountNr(accountNr);
|
||||
}
|
||||
|
||||
public String getAccountNr() {
|
||||
return ((OKPayAccountContractData) contractData).getAccountNr();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class OKPayAccountContractData extends PaymentAccountContractData implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
private String accountNr;
|
||||
|
||||
public OKPayAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
|
||||
super(paymentMethod, id, maxTradePeriod);
|
||||
}
|
||||
|
||||
public void setAccountNr(String accountNr) {
|
||||
this.accountNr = accountNr;
|
||||
}
|
||||
|
||||
public String getAccountNr() {
|
||||
return accountNr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentDetails() {
|
||||
return "OKPay - Account nr.: " + accountNr;
|
||||
}
|
||||
|
||||
|
||||
}
|
168
core/src/main/java/io/bitsquare/payment/PaymentAccount.java
Normal file
168
core/src/main/java/io/bitsquare/payment/PaymentAccount.java
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.locale.Country;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PaymentAccount implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(PaymentAccount.class);
|
||||
|
||||
protected final String id;
|
||||
protected final PaymentMethod paymentMethod;
|
||||
protected String accountName;
|
||||
protected final List<TradeCurrency> tradeCurrencies = new ArrayList<>();
|
||||
protected TradeCurrency selectedTradeCurrency;
|
||||
@Nullable
|
||||
protected Country country = null;
|
||||
protected PaymentAccountContractData contractData;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
public PaymentAccount(PaymentMethod paymentMethod) {
|
||||
this.paymentMethod = paymentMethod;
|
||||
id = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void addCurrency(TradeCurrency tradeCurrency) {
|
||||
if (!tradeCurrencies.contains(tradeCurrency))
|
||||
tradeCurrencies.add(tradeCurrency);
|
||||
}
|
||||
|
||||
public void removeCurrency(TradeCurrency tradeCurrency) {
|
||||
if (tradeCurrencies.contains(tradeCurrency))
|
||||
tradeCurrencies.remove(tradeCurrency);
|
||||
}
|
||||
|
||||
public boolean hasMultipleCurrencies() {
|
||||
return tradeCurrencies.size() > 1;
|
||||
}
|
||||
|
||||
public void setSingleTradeCurrency(TradeCurrency tradeCurrency) {
|
||||
tradeCurrencies.clear();
|
||||
tradeCurrencies.add(tradeCurrency);
|
||||
setSelectedTradeCurrency(tradeCurrency);
|
||||
}
|
||||
|
||||
public TradeCurrency getSingleTradeCurrency() {
|
||||
if (!tradeCurrencies.isEmpty())
|
||||
return tradeCurrencies.get(0);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter, Setter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
public void setAccountName(String accountName) {
|
||||
this.accountName = accountName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Country getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(@Nullable Country country) {
|
||||
this.country = country;
|
||||
contractData.setCountryCode(country.code);
|
||||
}
|
||||
|
||||
public void setSelectedTradeCurrency(TradeCurrency tradeCurrency) {
|
||||
selectedTradeCurrency = tradeCurrency;
|
||||
}
|
||||
|
||||
public TradeCurrency getSelectedTradeCurrency() {
|
||||
return selectedTradeCurrency;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public PaymentMethod getPaymentMethod() {
|
||||
return paymentMethod;
|
||||
}
|
||||
|
||||
public List<TradeCurrency> getTradeCurrencies() {
|
||||
return tradeCurrencies;
|
||||
}
|
||||
|
||||
public PaymentAccountContractData getContractData() {
|
||||
return contractData;
|
||||
}
|
||||
|
||||
public String getPaymentDetails() {
|
||||
return contractData.getPaymentDetails();
|
||||
}
|
||||
|
||||
public int getMaxTradePeriod() {
|
||||
return contractData.getMaxTradePeriod();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Util
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return contractData.toString() + '\'' +
|
||||
"PaymentAccount{" +
|
||||
"id='" + id + '\'' +
|
||||
", paymentMethod=" + paymentMethod +
|
||||
", accountName='" + accountName + '\'' +
|
||||
", tradeCurrencies=" + tradeCurrencies +
|
||||
", selectedTradeCurrency=" + selectedTradeCurrency +
|
||||
", country=" + country +
|
||||
", contractData=" + contractData +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.Serializable;
|
||||
|
||||
public abstract class PaymentAccountContractData implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
private final String paymentMethodName;
|
||||
private final String id;
|
||||
private final int maxTradePeriod;
|
||||
|
||||
@Nullable
|
||||
private String countryCode;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public PaymentAccountContractData(String paymentMethodName, String id, int maxTradePeriod) {
|
||||
this.paymentMethodName = paymentMethodName;
|
||||
this.id = id;
|
||||
this.maxTradePeriod = maxTradePeriod;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter, Setter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setCountryCode(String countryCode) {
|
||||
this.countryCode = countryCode;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getCountryCode() {
|
||||
return countryCode;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getPaymentMethodName() {
|
||||
return paymentMethodName;
|
||||
}
|
||||
|
||||
abstract public String getPaymentDetails();
|
||||
|
||||
public int getMaxTradePeriod() {
|
||||
return maxTradePeriod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof PaymentAccountContractData)) return false;
|
||||
|
||||
PaymentAccountContractData that = (PaymentAccountContractData) o;
|
||||
|
||||
if (maxTradePeriod != that.maxTradePeriod) return false;
|
||||
if (paymentMethodName != null ? !paymentMethodName.equals(that.paymentMethodName) : that.paymentMethodName != null)
|
||||
return false;
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
return !(countryCode != null ? !countryCode.equals(that.countryCode) : that.countryCode != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = paymentMethodName != null ? paymentMethodName.hashCode() : 0;
|
||||
result = 31 * result + (id != null ? id.hashCode() : 0);
|
||||
result = 31 * result + maxTradePeriod;
|
||||
result = 31 * result + (countryCode != null ? countryCode.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
144
core/src/main/java/io/bitsquare/payment/PaymentMethod.java
Normal file
144
core/src/main/java/io/bitsquare/payment/PaymentMethod.java
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
// Don't use Enum as it breaks serialisation when changing entries and we want to stay flexible here
|
||||
public class PaymentMethod implements Serializable, Comparable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
// time in blocks (average 10 min for one block confirmation
|
||||
private static final int HOUR = 6;
|
||||
private static final int DAY = HOUR * 24;
|
||||
|
||||
public static final String OK_PAY_ID = "OK_PAY";
|
||||
public static final String PERFECT_MONEY_ID = "PERFECT_MONEY";
|
||||
public static final String SEPA_ID = "SEPA";
|
||||
public static final String SWISH_ID = "SWISH";
|
||||
public static final String ALI_PAY_ID = "ALI_PAY";
|
||||
/* public static final String FED_WIRE="FED_WIRE";*/
|
||||
/* public static final String TRANSFER_WISE="TRANSFER_WISE";*/
|
||||
/* public static final String US_POSTAL_MONEY_ORDER="US_POSTAL_MONEY_ORDER";*/
|
||||
public static final String BLOCK_CHAINS_ID = "BLOCK_CHAINS";
|
||||
|
||||
public static PaymentMethod OK_PAY;
|
||||
public static PaymentMethod PERFECT_MONEY;
|
||||
public static PaymentMethod SEPA;
|
||||
public static PaymentMethod SWISH;
|
||||
public static PaymentMethod ALI_PAY;
|
||||
/* public static PaymentMethod FED_WIRE;*/
|
||||
/* public static PaymentMethod TRANSFER_WISE;*/
|
||||
/* public static PaymentMethod US_POSTAL_MONEY_ORDER;*/
|
||||
public static PaymentMethod BLOCK_CHAINS;
|
||||
|
||||
public static final List<PaymentMethod> ALL_VALUES = new ArrayList<>(Arrays.asList(
|
||||
OK_PAY = new PaymentMethod(OK_PAY_ID, 0, HOUR), // tx instant so min. wait time
|
||||
PERFECT_MONEY = new PaymentMethod(PERFECT_MONEY_ID, 0, DAY),
|
||||
SEPA = new PaymentMethod(SEPA_ID, 0, 8 * DAY), // sepa takes 1-3 business days. We use 8 days to include safety for holidays
|
||||
SWISH = new PaymentMethod(SWISH_ID, 0, DAY),
|
||||
ALI_PAY = new PaymentMethod(ALI_PAY_ID, 0, DAY),
|
||||
/* FED_WIRE = new PaymentMethod(FED_WIRE_ID, 0, DAY),*/
|
||||
/* TRANSFER_WISE = new PaymentMethod(TRANSFER_WISE_ID, 0, DAY),*/
|
||||
/* US_POSTAL_MONEY_ORDER = new PaymentMethod(US_POSTAL_MONEY_ORDER_ID, 0, DAY),*/
|
||||
BLOCK_CHAINS = new PaymentMethod(BLOCK_CHAINS_ID, 0, DAY)
|
||||
));
|
||||
|
||||
|
||||
private final String id;
|
||||
|
||||
private final long lockTime;
|
||||
|
||||
private final int maxTradePeriod;
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* @param lockTime lock time when seller release BTC until the payout tx gets valid (bitcoin tx lockTime). Serves as protection
|
||||
* against charge back risk. If Bank do the charge back quickly the Arbitrator and the seller can push another
|
||||
* double spend tx to invalidate the time locked payout tx. For the moment we set all to 0 but will have it in
|
||||
* place when needed.
|
||||
* @param maxTradePeriod The min. period a trader need to wait until he gets displayed the contact form for opening a dispute.
|
||||
*/
|
||||
public PaymentMethod(String id, long lockTime, int maxTradePeriod) {
|
||||
this.id = id;
|
||||
this.lockTime = lockTime;
|
||||
this.maxTradePeriod = maxTradePeriod;
|
||||
}
|
||||
|
||||
public static PaymentMethod getPaymentMethodByName(String name) {
|
||||
return ALL_VALUES.stream().filter(e -> e.getId().equals(name)).findFirst().get();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getMaxTradePeriod() {
|
||||
return maxTradePeriod;
|
||||
}
|
||||
|
||||
public long getLockTime() {
|
||||
return lockTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Object other) {
|
||||
return this.id.compareTo(((PaymentMethod) other).id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof PaymentMethod)) return false;
|
||||
|
||||
PaymentMethod that = (PaymentMethod) o;
|
||||
|
||||
if (getLockTime() != that.getLockTime()) return false;
|
||||
if (getMaxTradePeriod() != that.getMaxTradePeriod()) return false;
|
||||
return !(getId() != null ? !getId().equals(that.getId()) : that.getId() != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = getId() != null ? getId().hashCode() : 0;
|
||||
result = 31 * result + (int) (getLockTime() ^ (getLockTime() >>> 32));
|
||||
result = 31 * result + getMaxTradePeriod();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PaymentMethod{" +
|
||||
"name='" + id + '\'' +
|
||||
", lockTime=" + lockTime +
|
||||
", waitPeriodForOpenDispute=" + maxTradePeriod +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.locale.FiatCurrency;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class PerfectMoneyAccount extends PaymentAccount implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
public PerfectMoneyAccount() {
|
||||
super(PaymentMethod.PERFECT_MONEY);
|
||||
setSingleTradeCurrency(new FiatCurrency("USD"));
|
||||
|
||||
contractData = new PerfectMoneyAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
|
||||
}
|
||||
|
||||
public String getHolderName() {
|
||||
return ((PerfectMoneyAccountContractData) contractData).getHolderName();
|
||||
}
|
||||
|
||||
public void setHolderName(String holderName) {
|
||||
((PerfectMoneyAccountContractData) contractData).setHolderName(holderName);
|
||||
}
|
||||
|
||||
public void setAccountNr(String accountNr) {
|
||||
((PerfectMoneyAccountContractData) contractData).setAccountNr(accountNr);
|
||||
}
|
||||
|
||||
public String getAccountNr() {
|
||||
return ((PerfectMoneyAccountContractData) contractData).getAccountNr();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class PerfectMoneyAccountContractData extends PaymentAccountContractData implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
private String holderName;
|
||||
private String accountNr;
|
||||
|
||||
public PerfectMoneyAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
|
||||
super(paymentMethod, id, maxTradePeriod);
|
||||
}
|
||||
|
||||
public String getHolderName() {
|
||||
return holderName;
|
||||
}
|
||||
|
||||
public void setHolderName(String holderName) {
|
||||
this.holderName = holderName;
|
||||
}
|
||||
|
||||
public void setAccountNr(String accountNr) {
|
||||
this.accountNr = accountNr;
|
||||
}
|
||||
|
||||
public String getAccountNr() {
|
||||
return accountNr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentDetails() {
|
||||
return "PerfectMoney - Holder name: " + holderName + ", account nr.: " + accountNr;
|
||||
}
|
||||
|
||||
}
|
71
core/src/main/java/io/bitsquare/payment/SepaAccount.java
Normal file
71
core/src/main/java/io/bitsquare/payment/SepaAccount.java
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
public class SepaAccount extends PaymentAccount implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
public SepaAccount() {
|
||||
super(PaymentMethod.SEPA);
|
||||
|
||||
contractData = new SepaAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
|
||||
}
|
||||
|
||||
public void setHolderName(String holderName) {
|
||||
((SepaAccountContractData) contractData).setHolderName(holderName);
|
||||
}
|
||||
|
||||
public String getHolderName() {
|
||||
return ((SepaAccountContractData) contractData).getHolderName();
|
||||
}
|
||||
|
||||
public void setIban(String iban) {
|
||||
((SepaAccountContractData) contractData).setIban(iban);
|
||||
}
|
||||
|
||||
public String getIban() {
|
||||
return ((SepaAccountContractData) contractData).getIban();
|
||||
}
|
||||
|
||||
public void setBic(String bic) {
|
||||
((SepaAccountContractData) contractData).setBic(bic);
|
||||
}
|
||||
|
||||
public String getBic() {
|
||||
return ((SepaAccountContractData) contractData).getBic();
|
||||
}
|
||||
|
||||
public List<String> getAcceptedCountryCodes() {
|
||||
return ((SepaAccountContractData) contractData).getAcceptedCountryCodes();
|
||||
}
|
||||
|
||||
public void addAcceptedCountry(String countryCode) {
|
||||
((SepaAccountContractData) contractData).addAcceptedCountry(countryCode);
|
||||
}
|
||||
|
||||
public void removeAcceptedCountry(String countryCode) {
|
||||
((SepaAccountContractData) contractData).removeAcceptedCountry(countryCode);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.locale.CountryUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SepaAccountContractData extends PaymentAccountContractData implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
transient private static final Logger log = LoggerFactory.getLogger(SepaAccountContractData.class);
|
||||
|
||||
private String holderName;
|
||||
private String iban;
|
||||
private String bic;
|
||||
private Set<String> acceptedCountryCodes;
|
||||
|
||||
public SepaAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
|
||||
super(paymentMethod, id, maxTradePeriod);
|
||||
acceptedCountryCodes = CountryUtil.getAllSepaCountries().stream().map(e -> e.code).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public void setHolderName(String holderName) {
|
||||
this.holderName = holderName;
|
||||
}
|
||||
|
||||
public String getHolderName() {
|
||||
return holderName;
|
||||
}
|
||||
|
||||
public void setIban(String iban) {
|
||||
this.iban = iban;
|
||||
}
|
||||
|
||||
public String getIban() {
|
||||
return iban;
|
||||
}
|
||||
|
||||
public void setBic(String bic) {
|
||||
this.bic = bic;
|
||||
}
|
||||
|
||||
public String getBic() {
|
||||
return bic;
|
||||
}
|
||||
|
||||
public void addAcceptedCountry(String countryCode) {
|
||||
acceptedCountryCodes.add(countryCode);
|
||||
}
|
||||
|
||||
public void removeAcceptedCountry(String countryCode) {
|
||||
acceptedCountryCodes.remove(countryCode);
|
||||
}
|
||||
|
||||
public List<String> getAcceptedCountryCodes() {
|
||||
List<String> sortedList = new ArrayList<>(acceptedCountryCodes);
|
||||
sortedList.sort((a, b) -> a.compareTo(b));
|
||||
return sortedList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentDetails() {
|
||||
return "SEPA - Holder name: " + holderName + ", IBAN: " + iban + ", BIC: " + bic + ", country code: " + getCountryCode();
|
||||
}
|
||||
}
|
51
core/src/main/java/io/bitsquare/payment/SwishAccount.java
Normal file
51
core/src/main/java/io/bitsquare/payment/SwishAccount.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.locale.FiatCurrency;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class SwishAccount extends PaymentAccount implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
public SwishAccount() {
|
||||
super(PaymentMethod.SWISH);
|
||||
setSingleTradeCurrency(new FiatCurrency("SEK"));
|
||||
|
||||
contractData = new SwishAccountContractData(paymentMethod.getId(), id, paymentMethod.getMaxTradePeriod());
|
||||
}
|
||||
|
||||
public void setMobileNr(String mobileNr) {
|
||||
((SwishAccountContractData) contractData).setMobileNr(mobileNr);
|
||||
}
|
||||
|
||||
public String getMobileNr() {
|
||||
return ((SwishAccountContractData) contractData).getMobileNr();
|
||||
}
|
||||
|
||||
public void setHolderName(String holderName) {
|
||||
((SwishAccountContractData) contractData).setHolderName(holderName);
|
||||
}
|
||||
|
||||
public String getHolderName() {
|
||||
return ((SwishAccountContractData) contractData).getHolderName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class SwishAccountContractData extends PaymentAccountContractData implements Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||
|
||||
private String mobileNr;
|
||||
private String holderName;
|
||||
|
||||
public SwishAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
|
||||
super(paymentMethod, id, maxTradePeriod);
|
||||
}
|
||||
|
||||
public void setMobileNr(String mobileNr) {
|
||||
this.mobileNr = mobileNr;
|
||||
}
|
||||
|
||||
public String getMobileNr() {
|
||||
return mobileNr;
|
||||
}
|
||||
|
||||
public String getHolderName() {
|
||||
return holderName;
|
||||
}
|
||||
|
||||
public void setHolderName(String holderName) {
|
||||
this.holderName = holderName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentDetails() {
|
||||
return "Swish - Holder name: " + holderName + ", mobile nr.: " + mobileNr;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment.unused;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import io.bitsquare.payment.PaymentMethod;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
// US only
|
||||
public class FedWireAccount extends PaymentAccount implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(FedWireAccount.class);
|
||||
|
||||
private String holderName;
|
||||
private String holderState;
|
||||
private String holderZIP;
|
||||
private String holderStreet;
|
||||
private String holderCity;
|
||||
private String holderSSN; // Optional? social security Nr only Arizona and Oklahoma?
|
||||
private String accountNr;
|
||||
private String bankCode;// SWIFT Code/BIC/RoutingNr/ABA (ABA for UD domestic)
|
||||
private String bankName;
|
||||
private String bankState;
|
||||
private String bankZIP;
|
||||
private String bankStreet;
|
||||
private String bankCity;
|
||||
|
||||
private FedWireAccount() {
|
||||
super(PaymentMethod.SEPA);
|
||||
}
|
||||
|
||||
public String getHolderName() {
|
||||
return holderName;
|
||||
}
|
||||
|
||||
public void setHolderName(String holderName) {
|
||||
this.holderName = holderName;
|
||||
}
|
||||
|
||||
public String getAccountNr() {
|
||||
return accountNr;
|
||||
}
|
||||
|
||||
public void setAccountNr(String accountNr) {
|
||||
this.accountNr = accountNr;
|
||||
}
|
||||
|
||||
public String getBankCode() {
|
||||
return bankCode;
|
||||
}
|
||||
|
||||
public void setBankCode(String bankCode) {
|
||||
this.bankCode = bankCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentDetails() {
|
||||
return "{accountName='" + accountName + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SepaAccount{" +
|
||||
"accountName='" + accountName + '\'' +
|
||||
", id='" + id + '\'' +
|
||||
", paymentMethod=" + paymentMethod +
|
||||
", holderName='" + holderName + '\'' +
|
||||
", accountNr='" + accountNr + '\'' +
|
||||
", bankCode='" + bankCode + '\'' +
|
||||
", country=" + country +
|
||||
", tradeCurrencies='" + getTradeCurrencies() + '\'' +
|
||||
", selectedTradeCurrency=" + selectedTradeCurrency +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment.unused;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import io.bitsquare.payment.PaymentMethod;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class TransferWiseAccount extends PaymentAccount implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TransferWiseAccount.class);
|
||||
|
||||
private String holderName;
|
||||
private String iban;
|
||||
private String bic;
|
||||
|
||||
|
||||
private TransferWiseAccount() {
|
||||
super(PaymentMethod.SEPA);
|
||||
}
|
||||
|
||||
public String getHolderName() {
|
||||
return holderName;
|
||||
}
|
||||
|
||||
public void setHolderName(String holderName) {
|
||||
this.holderName = holderName;
|
||||
}
|
||||
|
||||
public String getIban() {
|
||||
return iban;
|
||||
}
|
||||
|
||||
public void setIban(String iban) {
|
||||
this.iban = iban;
|
||||
}
|
||||
|
||||
public String getBic() {
|
||||
return bic;
|
||||
}
|
||||
|
||||
public void setBic(String bic) {
|
||||
this.bic = bic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentDetails() {
|
||||
return "TransferWise{accountName='" + accountName + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TransferWiseAccount{" +
|
||||
"accountName='" + accountName + '\'' +
|
||||
", id='" + id + '\'' +
|
||||
", paymentMethod=" + paymentMethod +
|
||||
", holderName='" + holderName + '\'' +
|
||||
", iban='" + iban + '\'' +
|
||||
", bic='" + bic + '\'' +
|
||||
", country=" + country +
|
||||
", tradeCurrencies='" + getTradeCurrencies() + '\'' +
|
||||
", selectedTradeCurrency=" + selectedTradeCurrency +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.payment.unused;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class USPostalMoneyOrderAccount extends PaymentAccount implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(USPostalMoneyOrderAccount.class);
|
||||
|
||||
private String holderName;
|
||||
private String iban;
|
||||
private String bic;
|
||||
|
||||
|
||||
private USPostalMoneyOrderAccount() {
|
||||
super(null /*PaymentMethod.US_POSTAL_MONEY_ORDER*/);
|
||||
}
|
||||
|
||||
public String getHolderName() {
|
||||
return holderName;
|
||||
}
|
||||
|
||||
public void setHolderName(String holderName) {
|
||||
this.holderName = holderName;
|
||||
}
|
||||
|
||||
public String getIban() {
|
||||
return iban;
|
||||
}
|
||||
|
||||
public void setIban(String iban) {
|
||||
this.iban = iban;
|
||||
}
|
||||
|
||||
public String getBic() {
|
||||
return bic;
|
||||
}
|
||||
|
||||
public void setBic(String bic) {
|
||||
this.bic = bic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentDetails() {
|
||||
return "{accountName='" + accountName + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "USPostalMoneyOrderAccount{" +
|
||||
"accountName='" + accountName + '\'' +
|
||||
", id='" + id + '\'' +
|
||||
", paymentMethod=" + paymentMethod +
|
||||
", holderName='" + holderName + '\'' +
|
||||
", iban='" + iban + '\'' +
|
||||
", bic='" + bic + '\'' +
|
||||
", country=" + country +
|
||||
", tradeCurrencies='" + getTradeCurrencies() + '\'' +
|
||||
", selectedTradeCurrency=" + selectedTradeCurrency +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.trade.handlers;
|
||||
|
||||
import io.bitsquare.trade.Trade;
|
||||
|
||||
|
||||
public interface TradeResultHandler {
|
||||
void handleResult(Trade trade);
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade;
|
||||
|
||||
import io.bitsquare.p2p.Address;
|
||||
import io.bitsquare.trade.offer.Offer;
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
public class ArbitrationSelectionRule {
|
||||
private static final Logger log = LoggerFactory.getLogger(ArbitrationSelectionRule.class);
|
||||
|
||||
public static Address select(List<Address> acceptedArbitratorAddresses, Offer offer) {
|
||||
List<Address> candidates = new ArrayList<>();
|
||||
for (Address offerArbitratorAddress : offer.getArbitratorAddresses()) {
|
||||
candidates.addAll(acceptedArbitratorAddresses.stream().filter(offerArbitratorAddress::equals).collect(Collectors.toList()));
|
||||
}
|
||||
checkArgument(candidates.size() > 0, "candidates.size() <= 0");
|
||||
|
||||
int index = Math.abs(Sha256Hash.hash(offer.getId().getBytes()).hashCode()) % candidates.size();
|
||||
Address selectedArbitrator = candidates.get(index);
|
||||
log.debug("selectedArbitrator " + selectedArbitrator);
|
||||
return selectedArbitrator;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.buyer;
|
||||
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.data.PreparedDepositTxAndOffererInputs;
|
||||
import io.bitsquare.common.crypto.CryptoUtil;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class CreateAndSignDepositTxAsBuyer extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateAndSignDepositTxAsBuyer.class);
|
||||
|
||||
public CreateAndSignDepositTxAsBuyer(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null");
|
||||
Coin buyerInputAmount = FeePolicy.SECURITY_DEPOSIT.add(FeePolicy.TX_FEE);
|
||||
Coin msOutputAmount = buyerInputAmount.add(FeePolicy.SECURITY_DEPOSIT).add(trade.getTradeAmount());
|
||||
|
||||
log.debug("getContractAsJson");
|
||||
log.debug("----------");
|
||||
log.debug(trade.getContractAsJson());
|
||||
log.debug("----------");
|
||||
|
||||
byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
|
||||
trade.setContractHash(contractHash);
|
||||
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(
|
||||
true,
|
||||
contractHash,
|
||||
buyerInputAmount,
|
||||
msOutputAmount,
|
||||
processModel.tradingPeer.getRawInputs(),
|
||||
processModel.tradingPeer.getChangeOutputValue(),
|
||||
processModel.tradingPeer.getChangeOutputAddress(),
|
||||
processModel.getAddressEntry(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
processModel.tradingPeer.getTradeWalletPubKey(),
|
||||
processModel.getArbitratorPubKey(trade.getArbitratorAddress()));
|
||||
|
||||
processModel.setPreparedDepositTx(result.depositTransaction);
|
||||
processModel.setRawInputs(result.rawOffererInputs);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.buyer;
|
||||
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.data.InputsAndChangeOutput;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CreateDepositTxInputsAsBuyer extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateDepositTxInputsAsBuyer.class);
|
||||
|
||||
public CreateDepositTxInputsAsBuyer(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
Coin takerInputAmount = FeePolicy.SECURITY_DEPOSIT.add(FeePolicy.TX_FEE);
|
||||
InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositsTxInputs(takerInputAmount, processModel.getAddressEntry());
|
||||
processModel.setRawInputs(result.rawInputs);
|
||||
processModel.setChangeOutputValue(result.changeOutputValue);
|
||||
processModel.setChangeOutputAddress(result.changeOutputAddress);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.buyer;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bitsquare.common.crypto.CryptoUtil;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class SignAndPublishDepositTxAsBuyer extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTxAsBuyer.class);
|
||||
|
||||
public SignAndPublishDepositTxAsBuyer(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
|
||||
trade.setContractHash(contractHash);
|
||||
processModel.getTradeWalletService().takerSignsAndPublishesDepositTx(
|
||||
false,
|
||||
contractHash,
|
||||
processModel.getPreparedDepositTx(),
|
||||
processModel.getRawInputs(),
|
||||
processModel.tradingPeer.getRawInputs(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
processModel.tradingPeer.getTradeWalletPubKey(),
|
||||
processModel.getArbitratorPubKey(trade.getArbitratorAddress()),
|
||||
new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
log.trace("takerSignAndPublishTx succeeded " + transaction);
|
||||
|
||||
trade.setDepositTx(transaction);
|
||||
trade.setTakeOfferDate(new Date());
|
||||
trade.setState(Trade.State.DEPOSIT_PUBLISHED);
|
||||
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.offerer;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AddDepositTxToWallet extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(AddDepositTxToWallet.class);
|
||||
|
||||
public AddDepositTxToWallet(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
// To access tx confidence we need to add that tx into our wallet.
|
||||
Transaction depositTx = processModel.getTradeWalletService().addTransactionToWallet(trade.getDepositTx());
|
||||
// update with full tx
|
||||
trade.setDepositTx(depositTx);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.offerer;
|
||||
|
||||
import io.bitsquare.common.crypto.CryptoUtil;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.p2p.Address;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import io.bitsquare.trade.BuyerAsOffererTrade;
|
||||
import io.bitsquare.trade.Contract;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.TradingPeer;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class CreateAndSignContract extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class);
|
||||
|
||||
public CreateAndSignContract(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
checkNotNull(processModel.getTakeOfferFeeTxId(), "processModel.getTakeOfferFeeTxId() must not be null");
|
||||
|
||||
TradingPeer taker = processModel.tradingPeer;
|
||||
PaymentAccountContractData offererPaymentAccountContractData = processModel.getPaymentAccountContractData(trade);
|
||||
PaymentAccountContractData takerPaymentAccountContractData = taker.getPaymentAccountContractData();
|
||||
boolean isBuyerOffererOrSellerTaker = trade instanceof BuyerAsOffererTrade;
|
||||
|
||||
Address buyerAddress = isBuyerOffererOrSellerTaker ? processModel.getMyAddress() : processModel.getTempTradingPeerAddress();
|
||||
Address sellerAddress = isBuyerOffererOrSellerTaker ? processModel.getTempTradingPeerAddress() : processModel.getMyAddress();
|
||||
log.debug("isBuyerOffererOrSellerTaker " + isBuyerOffererOrSellerTaker);
|
||||
log.debug("buyerAddress " + buyerAddress);
|
||||
log.debug("sellerAddress " + sellerAddress);
|
||||
Contract contract = new Contract(
|
||||
processModel.getOffer(),
|
||||
trade.getTradeAmount(),
|
||||
processModel.getTakeOfferFeeTxId(),
|
||||
buyerAddress,
|
||||
sellerAddress,
|
||||
trade.getArbitratorAddress(),
|
||||
isBuyerOffererOrSellerTaker,
|
||||
processModel.getAccountId(),
|
||||
taker.getAccountId(),
|
||||
offererPaymentAccountContractData,
|
||||
takerPaymentAccountContractData,
|
||||
processModel.getPubKeyRing(),
|
||||
taker.getPubKeyRing(),
|
||||
processModel.getAddressEntry().getAddressString(),
|
||||
taker.getPayoutAddressString(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
taker.getTradeWalletPubKey()
|
||||
);
|
||||
String contractAsJson = Utilities.objectToJson(contract);
|
||||
String signature = CryptoUtil.signMessage(processModel.getKeyRing().getMsgSignatureKeyPair().getPrivate(), contractAsJson);
|
||||
|
||||
trade.setContract(contract);
|
||||
trade.setContractAsJson(contractAsJson);
|
||||
trade.setOffererContractSignature(signature);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.offerer;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class LoadTakeOfferFeeTx extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(LoadTakeOfferFeeTx.class);
|
||||
|
||||
public LoadTakeOfferFeeTx(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
// TODO impl. not completed
|
||||
//processModel.getWalletService().findTxInBlockChain(processModel.getTakeOfferFeeTxId());
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.offerer;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.OffererTrade;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static io.bitsquare.util.Validator.checkTradeId;
|
||||
|
||||
public class ProcessDepositTxPublishedMessage extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(ProcessDepositTxPublishedMessage.class);
|
||||
|
||||
public ProcessDepositTxPublishedMessage(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
log.debug("current trade state " + trade.getState());
|
||||
DepositTxPublishedMessage message = (DepositTxPublishedMessage) processModel.getTradeMessage();
|
||||
checkTradeId(processModel.getId(), message);
|
||||
checkNotNull(message);
|
||||
checkArgument(message.depositTx != null);
|
||||
trade.setDepositTx(processModel.getWalletService().getTransactionFromSerializedTx(message.depositTx));
|
||||
trade.setState(Trade.State.DEPOSIT_PUBLISHED_MSG_RECEIVED);
|
||||
trade.setTakeOfferDate(new Date());
|
||||
|
||||
if (trade instanceof OffererTrade)
|
||||
processModel.getOpenOfferManager().closeOpenOffer(trade.getOffer());
|
||||
|
||||
// update to the latest peer address of our peer if the message is correct
|
||||
trade.setTradingPeerAddress(processModel.getTempTradingPeerAddress());
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.offerer;
|
||||
|
||||
import io.bitsquare.common.crypto.CryptoUtil;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.payment.BlockChainAccountContractData;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.messages.PayDepositRequest;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static io.bitsquare.util.Validator.checkTradeId;
|
||||
import static io.bitsquare.util.Validator.nonEmptyStringOf;
|
||||
|
||||
public class ProcessPayDepositRequest extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(ProcessPayDepositRequest.class);
|
||||
|
||||
public ProcessPayDepositRequest(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
log.debug("current trade state " + trade.getState());
|
||||
PayDepositRequest payDepositRequest = (PayDepositRequest) processModel.getTradeMessage();
|
||||
checkTradeId(processModel.getId(), payDepositRequest);
|
||||
checkNotNull(payDepositRequest);
|
||||
|
||||
processModel.tradingPeer.setRawInputs(checkNotNull(payDepositRequest.rawInputs));
|
||||
checkArgument(payDepositRequest.rawInputs.size() > 0);
|
||||
|
||||
processModel.tradingPeer.setChangeOutputValue(payDepositRequest.changeOutputValue);
|
||||
if (payDepositRequest.changeOutputAddress != null)
|
||||
processModel.tradingPeer.setChangeOutputAddress(payDepositRequest.changeOutputAddress);
|
||||
|
||||
processModel.tradingPeer.setTradeWalletPubKey(checkNotNull(payDepositRequest.takerTradeWalletPubKey));
|
||||
processModel.tradingPeer.setPayoutAddressString(nonEmptyStringOf(payDepositRequest.takerPayoutAddressString));
|
||||
processModel.tradingPeer.setPubKeyRing(checkNotNull(payDepositRequest.takerPubKeyRing));
|
||||
|
||||
PaymentAccountContractData paymentAccountContractData = checkNotNull(payDepositRequest.takerPaymentAccountContractData);
|
||||
processModel.tradingPeer.setPaymentAccountContractData(paymentAccountContractData);
|
||||
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
|
||||
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
|
||||
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
|
||||
String paymentId = CryptoUtil.getHashAsHex(trade.getId()).substring(0, 32);
|
||||
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
|
||||
}
|
||||
|
||||
processModel.tradingPeer.setAccountId(nonEmptyStringOf(payDepositRequest.takerAccountId));
|
||||
processModel.setTakeOfferFeeTxId(nonEmptyStringOf(payDepositRequest.takeOfferFeeTxId));
|
||||
processModel.setTakerAcceptedArbitratorAddresses(checkNotNull(payDepositRequest.acceptedArbitratorAddresses));
|
||||
if (payDepositRequest.acceptedArbitratorAddresses.size() < 1)
|
||||
failed("acceptedArbitratorNames size must be at least 1");
|
||||
trade.setArbitratorAddress(checkNotNull(payDepositRequest.arbitratorAddress));
|
||||
checkArgument(payDepositRequest.tradeAmount > 0);
|
||||
trade.setTradeAmount(Coin.valueOf(payDepositRequest.tradeAmount));
|
||||
|
||||
// update to the latest peer address of our peer if the payDepositRequest is correct
|
||||
trade.setTradingPeerAddress(processModel.getTempTradingPeerAddress());
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.offerer;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.p2p.messaging.SendMailMessageListener;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendPublishDepositTxRequest extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SendPublishDepositTxRequest.class);
|
||||
|
||||
public SendPublishDepositTxRequest(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
trade.setState(Trade.State.DEPOSIT_PUBLISH_REQUESTED);
|
||||
PublishDepositTxRequest tradeMessage = new PublishDepositTxRequest(
|
||||
processModel.getId(),
|
||||
processModel.getPaymentAccountContractData(trade),
|
||||
processModel.getAccountId(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
trade.getContractAsJson(),
|
||||
trade.getOffererContractSignature(),
|
||||
processModel.getAddressEntry().getAddressString(),
|
||||
processModel.getPreparedDepositTx(),
|
||||
processModel.getRawInputs(),
|
||||
trade.getOpenDisputeTimeAsBlockHeight(),
|
||||
trade.getCheckPaymentTimeAsBlockHeight()
|
||||
);
|
||||
|
||||
processModel.getP2PService().sendEncryptedMailMessage(
|
||||
trade.getTradingPeerAddress(),
|
||||
processModel.tradingPeer.getPubKeyRing(),
|
||||
tradeMessage,
|
||||
new SendMailMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.trace("Message arrived at peer.");
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault() {
|
||||
appendToErrorMessage("PublishDepositTxRequest sending failed");
|
||||
failed();
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.offerer;
|
||||
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.btc.listeners.BalanceListener;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.OffererTrade;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.bitcoinj.core.Address;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.fxmisc.easybind.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
// The buyer waits for the msg from the seller that he has published the deposit tx.
|
||||
// In error case he might not get that msg so we check additionally the balance of our inputs, if it is zero, it means the deposit
|
||||
// is already published. We set then the DEPOSIT_LOCKED state, so the user get informed that he is already in the critical state and need
|
||||
// to request support.
|
||||
public class SetupDepositBalanceListener extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SetupDepositBalanceListener.class);
|
||||
private Subscription tradeStateSubscription;
|
||||
private BalanceListener balanceListener;
|
||||
|
||||
public SetupDepositBalanceListener(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
WalletService walletService = processModel.getWalletService();
|
||||
Address address = walletService.getAddressEntryByOfferId(trade.getId()).getAddress();
|
||||
balanceListener = walletService.addBalanceListener(new BalanceListener(address) {
|
||||
@Override
|
||||
public void onBalanceChanged(Coin balance) {
|
||||
updateBalance(balance);
|
||||
}
|
||||
});
|
||||
walletService.addBalanceListener(balanceListener);
|
||||
|
||||
tradeStateSubscription = EasyBind.subscribe(trade.stateProperty(), newValue -> {
|
||||
log.debug("tradeStateSubscription newValue " + newValue);
|
||||
if (newValue == Trade.State.DEPOSIT_PUBLISHED_MSG_RECEIVED
|
||||
|| newValue == Trade.State.DEPOSIT_SEEN_IN_NETWORK) {
|
||||
|
||||
walletService.removeBalanceListener(balanceListener);
|
||||
log.debug(" UserThread.execute(this::unSubscribe);");
|
||||
// TODO is that allowed?
|
||||
UserThread.execute(this::unSubscribe);
|
||||
}
|
||||
});
|
||||
updateBalance(walletService.getBalanceForAddress(address));
|
||||
|
||||
// we complete immediately, our object stays alive because the balanceListener is stored in the WalletService
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
|
||||
private void unSubscribe() {
|
||||
//TODO investigate, seems to not get called sometimes
|
||||
log.debug("unSubscribe tradeStateSubscription");
|
||||
tradeStateSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
private void updateBalance(Coin balance) {
|
||||
log.debug("updateBalance " + balance.toFriendlyString());
|
||||
log.debug("pre tradeState " + trade.getState().toString());
|
||||
Trade.State tradeState = trade.getState();
|
||||
if (balance.compareTo(Coin.ZERO) == 0) {
|
||||
if (trade instanceof OffererTrade) {
|
||||
processModel.getOpenOfferManager().closeOpenOffer(trade.getOffer());
|
||||
|
||||
if (tradeState == Trade.State.DEPOSIT_PUBLISH_REQUESTED) {
|
||||
trade.setState(Trade.State.DEPOSIT_SEEN_IN_NETWORK);
|
||||
} else if (tradeState.getPhase() == Trade.Phase.PREPARATION) {
|
||||
processModel.getTradeManager().removePreparedTrade(trade);
|
||||
} else if (tradeState.getPhase().ordinal() < Trade.Phase.DEPOSIT_PAID.ordinal()) {
|
||||
processModel.getTradeManager().addTradeToFailedTrades(trade);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("tradeState " + trade.getState().toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.offerer;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.ArbitrationSelectionRule;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VerifyArbitrationSelection extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(VerifyArbitrationSelection.class);
|
||||
|
||||
public VerifyArbitrationSelection(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
if (trade.getArbitratorAddress().equals(ArbitrationSelectionRule.select(processModel.getTakerAcceptedArbitratorAddresses(),
|
||||
processModel.getOffer())))
|
||||
complete();
|
||||
else
|
||||
failed("Arbitrator selection verification failed");
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.seller;
|
||||
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.data.PreparedDepositTxAndOffererInputs;
|
||||
import io.bitsquare.common.crypto.CryptoUtil;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class CreateAndSignDepositTxAsSeller extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateAndSignDepositTxAsSeller.class);
|
||||
|
||||
public CreateAndSignDepositTxAsSeller(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null");
|
||||
Coin sellerInputAmount = FeePolicy.SECURITY_DEPOSIT.add(FeePolicy.TX_FEE).add(trade.getTradeAmount());
|
||||
Coin msOutputAmount = sellerInputAmount.add(FeePolicy.SECURITY_DEPOSIT);
|
||||
|
||||
byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
|
||||
trade.setContractHash(contractHash);
|
||||
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(
|
||||
false,
|
||||
contractHash,
|
||||
sellerInputAmount,
|
||||
msOutputAmount,
|
||||
processModel.tradingPeer.getRawInputs(),
|
||||
processModel.tradingPeer.getChangeOutputValue(),
|
||||
processModel.tradingPeer.getChangeOutputAddress(),
|
||||
processModel.getAddressEntry(),
|
||||
processModel.tradingPeer.getTradeWalletPubKey(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
processModel.getArbitratorPubKey(trade.getArbitratorAddress()));
|
||||
|
||||
processModel.setPreparedDepositTx(result.depositTransaction);
|
||||
processModel.setRawInputs(result.rawOffererInputs);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.seller;
|
||||
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.data.InputsAndChangeOutput;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CreateDepositTxInputsAsSeller extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateDepositTxInputsAsSeller.class);
|
||||
|
||||
public CreateDepositTxInputsAsSeller(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
if (trade.getTradeAmount() != null) {
|
||||
Coin takerInputAmount = FeePolicy.SECURITY_DEPOSIT.add(FeePolicy.TX_FEE).add(trade.getTradeAmount());
|
||||
|
||||
InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositsTxInputs(takerInputAmount, processModel
|
||||
.getAddressEntry());
|
||||
processModel.setRawInputs(result.rawInputs);
|
||||
processModel.setChangeOutputValue(result.changeOutputValue);
|
||||
processModel.setChangeOutputAddress(result.changeOutputAddress);
|
||||
|
||||
complete();
|
||||
} else {
|
||||
failed("trade.getTradeAmount() = null");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.seller;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bitsquare.common.crypto.CryptoUtil;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class SignAndPublishDepositTxAsSeller extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTxAsSeller.class);
|
||||
|
||||
public SignAndPublishDepositTxAsSeller(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
log.debug("getContractAsJson");
|
||||
log.debug("----------");
|
||||
log.debug(trade.getContractAsJson());
|
||||
log.debug("----------");
|
||||
byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
|
||||
trade.setContractHash(contractHash);
|
||||
processModel.getTradeWalletService().takerSignsAndPublishesDepositTx(
|
||||
true,
|
||||
contractHash,
|
||||
processModel.getPreparedDepositTx(),
|
||||
processModel.tradingPeer.getRawInputs(),
|
||||
processModel.getRawInputs(),
|
||||
processModel.tradingPeer.getTradeWalletPubKey(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
processModel.getArbitratorPubKey(trade.getArbitratorAddress()),
|
||||
new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
log.trace("takerSignAndPublishTx succeeded " + transaction);
|
||||
|
||||
trade.setDepositTx(transaction);
|
||||
trade.setTakeOfferDate(new Date());
|
||||
trade.setState(Trade.State.DEPOSIT_PUBLISHED);
|
||||
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.shared;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class InitWaitPeriodForOpenDispute extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(InitWaitPeriodForOpenDispute.class);
|
||||
|
||||
public InitWaitPeriodForOpenDispute(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
int openDisputeTimeAsBlockHeight = processModel.getTradeWalletService().getLastBlockSeenHeight()
|
||||
+ trade.getOffer().getPaymentMethod().getMaxTradePeriod();
|
||||
trade.setOpenDisputeTimeAsBlockHeight(openDisputeTimeAsBlockHeight);
|
||||
|
||||
int checkPaymentTimeAsBlockHeight = processModel.getTradeWalletService().getLastBlockSeenHeight()
|
||||
+ trade.getOffer().getPaymentMethod().getMaxTradePeriod() / 2;
|
||||
trade.setCheckPaymentTimeAsBlockHeight(checkPaymentTimeAsBlockHeight);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.shared;
|
||||
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class SignPayoutTx extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SignPayoutTx.class);
|
||||
|
||||
public SignPayoutTx(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null");
|
||||
Coin sellerPayoutAmount = FeePolicy.SECURITY_DEPOSIT;
|
||||
Coin buyerPayoutAmount = sellerPayoutAmount.add(trade.getTradeAmount());
|
||||
|
||||
long lockTimeAsBlockHeight = processModel.getTradeWalletService().getLastBlockSeenHeight() + trade.getOffer().getPaymentMethod().getLockTime();
|
||||
trade.setLockTimeAsBlockHeight(lockTimeAsBlockHeight);
|
||||
|
||||
byte[] payoutTxSignature = processModel.getTradeWalletService().sellerSignsPayoutTx(
|
||||
trade.getDepositTx(),
|
||||
buyerPayoutAmount,
|
||||
sellerPayoutAmount,
|
||||
processModel.tradingPeer.getPayoutAddressString(),
|
||||
processModel.getAddressEntry(),
|
||||
lockTimeAsBlockHeight,
|
||||
processModel.tradingPeer.getTradeWalletPubKey(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
processModel.getArbitratorPubKey(trade.getArbitratorAddress()));
|
||||
|
||||
processModel.setPayoutTxSignature(payoutTxSignature);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.taker;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class LoadCreateOfferFeeTx extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(LoadCreateOfferFeeTx.class);
|
||||
|
||||
public LoadCreateOfferFeeTx(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
// TODO impl. not completed
|
||||
///processModel.getWalletService().findTxInBlockChain(trade.getOffer().getOfferFeePaymentTxID());
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.taker;
|
||||
|
||||
import io.bitsquare.common.crypto.CryptoUtil;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.payment.BlockChainAccountContractData;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static io.bitsquare.util.Validator.checkTradeId;
|
||||
import static io.bitsquare.util.Validator.nonEmptyStringOf;
|
||||
|
||||
public class ProcessPublishDepositTxRequest extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(ProcessPublishDepositTxRequest.class);
|
||||
|
||||
public ProcessPublishDepositTxRequest(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
log.debug("current trade state " + trade.getState());
|
||||
PublishDepositTxRequest publishDepositTxRequest = (PublishDepositTxRequest) processModel.getTradeMessage();
|
||||
checkTradeId(processModel.getId(), publishDepositTxRequest);
|
||||
checkNotNull(publishDepositTxRequest);
|
||||
|
||||
PaymentAccountContractData paymentAccountContractData = checkNotNull(publishDepositTxRequest.offererPaymentAccountContractData);
|
||||
processModel.tradingPeer.setPaymentAccountContractData(paymentAccountContractData);
|
||||
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
|
||||
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
|
||||
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
|
||||
String paymentId = CryptoUtil.getHashAsHex(trade.getId()).substring(0, 32);
|
||||
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
|
||||
}
|
||||
|
||||
processModel.tradingPeer.setAccountId(nonEmptyStringOf(publishDepositTxRequest.offererAccountId));
|
||||
processModel.tradingPeer.setTradeWalletPubKey(checkNotNull(publishDepositTxRequest.offererTradeWalletPubKey));
|
||||
processModel.tradingPeer.setContractAsJson(nonEmptyStringOf(publishDepositTxRequest.offererContractAsJson));
|
||||
processModel.tradingPeer.setContractSignature(nonEmptyStringOf(publishDepositTxRequest.offererContractSignature));
|
||||
processModel.tradingPeer.setPayoutAddressString(nonEmptyStringOf(publishDepositTxRequest.offererPayoutAddressString));
|
||||
processModel.tradingPeer.setRawInputs(checkNotNull(publishDepositTxRequest.offererInputs));
|
||||
processModel.setPreparedDepositTx(checkNotNull(publishDepositTxRequest.preparedDepositTx));
|
||||
checkArgument(publishDepositTxRequest.offererInputs.size() > 0);
|
||||
if (publishDepositTxRequest.openDisputeTimeAsBlockHeight != 0) {
|
||||
trade.setOpenDisputeTimeAsBlockHeight(publishDepositTxRequest.openDisputeTimeAsBlockHeight);
|
||||
} else {
|
||||
failed("waitPeriodForOpenDisputeAsBlockHeight = 0");
|
||||
}
|
||||
|
||||
if (publishDepositTxRequest.checkPaymentTimeAsBlockHeight != 0) {
|
||||
trade.setCheckPaymentTimeAsBlockHeight(publishDepositTxRequest.checkPaymentTimeAsBlockHeight);
|
||||
} else {
|
||||
failed("notificationTimeAsBlockHeight = 0");
|
||||
}
|
||||
|
||||
// update to the latest peer address of our peer if the message is correct
|
||||
trade.setTradingPeerAddress(processModel.getTempTradingPeerAddress());
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.taker;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.ArbitrationSelectionRule;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SelectArbitrator extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SelectArbitrator.class);
|
||||
|
||||
public SelectArbitrator(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
trade.setArbitratorAddress(ArbitrationSelectionRule.select(processModel.getUser().getAcceptedArbitratorAddresses(), processModel.getOffer()));
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.taker;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.p2p.messaging.SendMailboxMessageListener;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendDepositTxPublishedMessage extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SendDepositTxPublishedMessage.class);
|
||||
|
||||
public SendDepositTxPublishedMessage(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
if (trade.getDepositTx() != null) {
|
||||
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(processModel.getId(),
|
||||
trade.getDepositTx().bitcoinSerialize(),
|
||||
processModel.getMyAddress());
|
||||
|
||||
processModel.getP2PService().sendEncryptedMailboxMessage(
|
||||
trade.getTradingPeerAddress(),
|
||||
processModel.tradingPeer.getPubKeyRing(),
|
||||
tradeMessage,
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.trace("Message arrived at peer.");
|
||||
trade.setState(Trade.State.DEPOSIT_PUBLISHED_MSG_SENT);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.trace("Message stored in mailbox.");
|
||||
trade.setState(Trade.State.DEPOSIT_PUBLISHED_MSG_SENT);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault() {
|
||||
appendToErrorMessage("DepositTxPublishedMessage sending failed");
|
||||
failed();
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
log.error("trade.getDepositTx() = " + trade.getDepositTx());
|
||||
failed("DepositTx is null");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.taker;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.p2p.messaging.SendMailboxMessageListener;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.messages.PayDepositRequest;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendPayDepositRequest extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SendPayDepositRequest.class);
|
||||
|
||||
public SendPayDepositRequest(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
if (processModel.getTakeOfferFeeTx() != null) {
|
||||
PayDepositRequest payDepositRequest = new PayDepositRequest(
|
||||
processModel.getMyAddress(),
|
||||
processModel.getId(),
|
||||
trade.getTradeAmount().value,
|
||||
processModel.getRawInputs(),
|
||||
processModel.getChangeOutputValue(),
|
||||
processModel.getChangeOutputAddress(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
processModel.getAddressEntry().getAddressString(),
|
||||
processModel.getPubKeyRing(),
|
||||
processModel.getPaymentAccountContractData(trade),
|
||||
processModel.getAccountId(),
|
||||
processModel.getTakeOfferFeeTx().getHashAsString(),
|
||||
processModel.getUser().getAcceptedArbitratorAddresses(),
|
||||
trade.getArbitratorAddress()
|
||||
);
|
||||
|
||||
processModel.getP2PService().sendEncryptedMailboxMessage(
|
||||
trade.getTradingPeerAddress(),
|
||||
processModel.tradingPeer.getPubKeyRing(),
|
||||
payDepositRequest,
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.trace("Message arrived at peer.");
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.trace("Message stored in mailbox.");
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault() {
|
||||
appendToErrorMessage("PayDepositRequest sending failed");
|
||||
failed();
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
log.error("processModel.getTakeOfferFeeTx() = " + processModel.getTakeOfferFeeTx());
|
||||
failed("TakeOfferFeeTx is null");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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.trade.protocol.trade.tasks.taker;
|
||||
|
||||
import io.bitsquare.common.crypto.CryptoUtil;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.p2p.Address;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import io.bitsquare.trade.Contract;
|
||||
import io.bitsquare.trade.SellerAsTakerTrade;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.TradingPeer;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VerifyAndSignContract extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(VerifyAndSignContract.class);
|
||||
|
||||
public VerifyAndSignContract(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
if (processModel.getTakeOfferFeeTx() != null) {
|
||||
TradingPeer offerer = processModel.tradingPeer;
|
||||
PaymentAccountContractData offererPaymentAccountContractData = offerer.getPaymentAccountContractData();
|
||||
PaymentAccountContractData takerPaymentAccountContractData = processModel.getPaymentAccountContractData(trade);
|
||||
|
||||
boolean isBuyerOffererOrSellerTaker = trade instanceof SellerAsTakerTrade;
|
||||
Address buyerAddress = isBuyerOffererOrSellerTaker ? processModel.getTempTradingPeerAddress() : processModel.getMyAddress();
|
||||
Address sellerAddress = isBuyerOffererOrSellerTaker ? processModel.getMyAddress() : processModel.getTempTradingPeerAddress();
|
||||
log.debug("isBuyerOffererOrSellerTaker " + isBuyerOffererOrSellerTaker);
|
||||
log.debug("buyerAddress " + buyerAddress);
|
||||
log.debug("sellerAddress " + sellerAddress);
|
||||
|
||||
Contract contract = new Contract(
|
||||
processModel.getOffer(),
|
||||
trade.getTradeAmount(),
|
||||
processModel.getTakeOfferFeeTx().getHashAsString(),
|
||||
buyerAddress,
|
||||
sellerAddress,
|
||||
trade.getArbitratorAddress(),
|
||||
isBuyerOffererOrSellerTaker,
|
||||
offerer.getAccountId(),
|
||||
processModel.getAccountId(),
|
||||
offererPaymentAccountContractData,
|
||||
takerPaymentAccountContractData,
|
||||
offerer.getPubKeyRing(),
|
||||
processModel.getPubKeyRing(),
|
||||
offerer.getPayoutAddressString(),
|
||||
processModel.getAddressEntry().getAddressString(),
|
||||
offerer.getTradeWalletPubKey(),
|
||||
processModel.getTradeWalletPubKey()
|
||||
);
|
||||
String contractAsJson = Utilities.objectToJson(contract);
|
||||
String signature = CryptoUtil.signMessage(processModel.getKeyRing().getMsgSignatureKeyPair().getPrivate(), contractAsJson);
|
||||
trade.setContract(contract);
|
||||
trade.setContractAsJson(contractAsJson);
|
||||
trade.setTakerContractSignature(signature);
|
||||
|
||||
try {
|
||||
CryptoUtil.verifyMessage(offerer.getPubKeyRing().getMsgSignaturePubKey(),
|
||||
contractAsJson,
|
||||
offerer.getContractSignature());
|
||||
} catch (Throwable t) {
|
||||
failed("Signature verification failed. " + t.getMessage());
|
||||
}
|
||||
|
||||
complete();
|
||||
} else {
|
||||
failed("processModel.getTakeOfferFeeTx() = null");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
41
core/src/main/java/io/bitsquare/user/BlockChainExplorer.java
Normal file
41
core/src/main/java/io/bitsquare/user/BlockChainExplorer.java
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.user;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class BlockChainExplorer implements Serializable {
|
||||
// That object is saved to disc. We need to take care of changes to not break deserialization.
|
||||
private static final long serialVersionUID = Version.LOCAL_DB_VERSION;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BlockChainExplorer.class);
|
||||
|
||||
public final String name;
|
||||
public final String txUrl;
|
||||
public final String addressUrl;
|
||||
|
||||
public BlockChainExplorer(String name, String txUrl, String addressUrl) {
|
||||
this.name = name;
|
||||
this.txUrl = txUrl;
|
||||
this.addressUrl = addressUrl;
|
||||
}
|
||||
}
|
27
core/src/main/java/io/bitsquare/user/PopupId.java
Normal file
27
core/src/main/java/io/bitsquare/user/PopupId.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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.user;
|
||||
|
||||
public class PopupId {
|
||||
|
||||
// We don't use an enum because it would break updates if we add a new item in a new version
|
||||
|
||||
public static String SEC_DEPOSIT = "SEC_DEPOSIT";
|
||||
public static String TRADE_WALLET = "TRADE_WALLET";
|
||||
|
||||
}
|
63
core/src/main/resources/logback.xml
Normal file
63
core/src/main/resources/logback.xml
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{15} - %msg %xEx%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="TRACE">
|
||||
<appender-ref ref="CONSOLE_APPENDER"/>
|
||||
</root>
|
||||
|
||||
<logger name="io.bitsquare" level="TRACE"/>
|
||||
<logger name="com.msopentech.thali.toronionproxy.OnionProxyManagerEventHandler" level="WARN"/>
|
||||
|
||||
<logger name="io.bitsquare.btc.AddressBasedCoinSelector" level="OFF"/>
|
||||
|
||||
<logger name="io.bitsquare.gui.util.Profiler" level="ERROR"/>
|
||||
<logger name="io.bitsquare.locale.BSResources" level="ERROR"/>
|
||||
<logger name="io.bitsquare.temp.storage.RemoteStorage" level="WARN"/>
|
||||
<logger name="io.bitsquare.storage.FileManager" level="WARN"/>
|
||||
|
||||
<logger name="org.bitcoinj" level="WARN"/>
|
||||
|
||||
<logger name="org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
|
||||
<logger name="org.bitcoinj.core.Peer" level="WARN"/>
|
||||
|
||||
|
||||
<!--
|
||||
<logger name="com.vinumeris.updatefx" level="OFF"/>
|
||||
<logger name="io.netty" level="OFF"/>
|
||||
<logger name="org.bitcoinj.core.BitcoinSerializer" level="ERROR"/>
|
||||
<logger name="org.bitcoinj.core.Peer" level="ERROR"/>-->
|
||||
|
||||
<!-- <logger name="net.tomp2p.message.Encoder" level="WARN"/>
|
||||
<logger name="net.tomp2p.message.Decoder" level="WARN"/>
|
||||
<logger name="net.tomp2p.message.MessageHeaderCodec" level="WARN"/>
|
||||
|
||||
|
||||
<logger name="io.netty.util" level="WARN"/>
|
||||
<logger name="io.netty.channel" level="WARN"/>
|
||||
<logger name="io.netty.buffer" level="WARN"/>-->
|
||||
|
||||
|
||||
<!-- <logger name="org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
|
||||
<logger name="org.bitcoinj.core.AbstractBlockChain" level="WARN"/>
|
||||
<logger name="org.bitcoinj.wallet.DeterministicKeyChain" level="WARN"/>-->
|
||||
<!-- <logger name="io.bitsquare.btc.WalletService" level="WARN"/>-->
|
||||
|
||||
<!--
|
||||
<logger name="org.bitcoinj.core.Wallet" level="OFF"/>
|
||||
<logger name="org.bitcoinj.core.MemoryPool" level="OFF"/>
|
||||
<logger name="org.bitcoinj.net.discovery.DnsDiscovery" level="OFF"/>
|
||||
<logger name="org.bitcoinj.core.DownloadListener" level="OFF"/>
|
||||
<logger name="org.bitcoinj.core.TransactionOutput" level="OFF"/>
|
||||
<logger name="org.bitcoinj.core.BitcoinSerializer" level="OFF"/>
|
||||
<logger name="org.bitcoinj.core.Peer" level="OFF"/>
|
||||
<logger name="org.bitcoinj.core.PeerGroup" level="OFF"/>
|
||||
<logger name="org.bitcoinj.core.PeerSocketHandler" level="OFF"/>
|
||||
<logger name="org.bitcoinj.net.NioClientManager" level="OFF"/>
|
||||
<logger name="org.bitcoinj.net.ConnectionHandler" level="OFF"/>
|
||||
-->
|
||||
</configuration>
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.gui.common.model;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class ActivatableDataModel implements Activatable, DataModel {
|
||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public final void _activate() {
|
||||
this.activate();
|
||||
}
|
||||
|
||||
protected void activate() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void _deactivate() {
|
||||
this.deactivate();
|
||||
}
|
||||
|
||||
protected void deactivate() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.gui.common.model;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class ActivatableViewModel implements Activatable, ViewModel {
|
||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public final void _activate() {
|
||||
this.activate();
|
||||
}
|
||||
|
||||
protected void activate() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void _deactivate() {
|
||||
this.deactivate();
|
||||
}
|
||||
|
||||
protected void deactivate() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* 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.gui.components;
|
||||
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.effect.BlurType;
|
||||
import javafx.scene.effect.DropShadow;
|
||||
import javafx.scene.effect.Effect;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.stage.Window;
|
||||
import org.controlsfx.control.PopOver;
|
||||
|
||||
public class PasswordTextField extends PasswordField {
|
||||
|
||||
private final Effect invalidEffect = new DropShadow(BlurType.THREE_PASS_BOX, Color.RED, 4, 0.0, 0, 0);
|
||||
|
||||
private final ObjectProperty<InputValidator.ValidationResult> validationResult = new SimpleObjectProperty<>
|
||||
(new InputValidator.ValidationResult(true));
|
||||
|
||||
private static PopOver errorMessageDisplay;
|
||||
private Region layoutReference = this;
|
||||
|
||||
public InputValidator getValidator() {
|
||||
return validator;
|
||||
}
|
||||
|
||||
public void setValidator(InputValidator validator) {
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
private InputValidator validator;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Static
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private static void hideErrorMessageDisplay() {
|
||||
if (errorMessageDisplay != null)
|
||||
errorMessageDisplay.hide();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public PasswordTextField() {
|
||||
super();
|
||||
|
||||
validationResult.addListener((ov, oldValue, newValue) -> {
|
||||
if (newValue != null) {
|
||||
setEffect(newValue.isValid ? null : invalidEffect);
|
||||
|
||||
if (newValue.isValid)
|
||||
hideErrorMessageDisplay();
|
||||
else
|
||||
applyErrorMessage(newValue);
|
||||
}
|
||||
});
|
||||
|
||||
sceneProperty().addListener((ov, oldValue, newValue) -> {
|
||||
// we got removed from the scene so hide the popup (if open)
|
||||
if (newValue == null)
|
||||
hideErrorMessageDisplay();
|
||||
});
|
||||
|
||||
focusedProperty().addListener((o, oldValue, newValue) -> {
|
||||
if (oldValue && !newValue && validator != null)
|
||||
validationResult.set(validator.validate(getText()));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void resetValidation() {
|
||||
setEffect(null);
|
||||
hideErrorMessageDisplay();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @param layoutReference The node used as reference for positioning. If not set explicitly the
|
||||
* ValidatingTextField instance is used.
|
||||
*/
|
||||
public void setLayoutReference(Region layoutReference) {
|
||||
this.layoutReference = layoutReference;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public ObjectProperty<InputValidator.ValidationResult> validationResultProperty() {
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void applyErrorMessage(InputValidator.ValidationResult validationResult) {
|
||||
if (errorMessageDisplay != null)
|
||||
errorMessageDisplay.hide();
|
||||
|
||||
if (!validationResult.isValid) {
|
||||
createErrorPopOver(validationResult.errorMessage);
|
||||
if (getScene() != null)
|
||||
errorMessageDisplay.show(getScene().getWindow(), getErrorPopupPosition().getX(),
|
||||
getErrorPopupPosition().getY());
|
||||
|
||||
if (errorMessageDisplay != null)
|
||||
errorMessageDisplay.setDetached(false);
|
||||
}
|
||||
}
|
||||
|
||||
private Point2D getErrorPopupPosition() {
|
||||
Window window = getScene().getWindow();
|
||||
Point2D point;
|
||||
point = layoutReference.localToScene(0, 0);
|
||||
double x = Math.floor(point.getX() + window.getX() + layoutReference.getWidth() + 20 - getPadding().getLeft() -
|
||||
getPadding().getRight());
|
||||
double y = Math.floor(point.getY() + window.getY() + getHeight() / 2 - getPadding().getTop() - getPadding()
|
||||
.getBottom());
|
||||
return new Point2D(x, y);
|
||||
}
|
||||
|
||||
|
||||
private static void createErrorPopOver(String errorMessage) {
|
||||
Label errorLabel = new Label(errorMessage);
|
||||
errorLabel.setId("validation-error");
|
||||
errorLabel.setPadding(new Insets(0, 10, 0, 10));
|
||||
errorLabel.setOnMouseClicked(e -> hideErrorMessageDisplay());
|
||||
|
||||
errorMessageDisplay = new PopOver(errorLabel);
|
||||
errorMessageDisplay.setDetachable(true);
|
||||
errorMessageDisplay.setDetachedTitle("Close");
|
||||
errorMessageDisplay.setArrowIndent(5);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.gui.components;
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.StackPane;
|
||||
|
||||
public class TableGroupHeadline extends Pane {
|
||||
|
||||
private final Label label;
|
||||
private final StringProperty text = new SimpleStringProperty();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public TableGroupHeadline() {
|
||||
this("");
|
||||
}
|
||||
|
||||
public TableGroupHeadline(String title) {
|
||||
text.set(title);
|
||||
|
||||
GridPane.setMargin(this, new Insets(-10, -10, -10, -10));
|
||||
GridPane.setColumnSpan(this, 2);
|
||||
|
||||
Pane bg = new StackPane();
|
||||
bg.setId("table-group-headline");
|
||||
bg.prefWidthProperty().bind(widthProperty());
|
||||
bg.prefHeightProperty().bind(heightProperty());
|
||||
|
||||
label = new Label();
|
||||
label.textProperty().bind(text);
|
||||
label.setLayoutX(8);
|
||||
label.setLayoutY(-8);
|
||||
label.setPadding(new Insets(0, 7, 0, 5));
|
||||
setActive();
|
||||
getChildren().addAll(bg, label);
|
||||
}
|
||||
|
||||
public void setInactive() {
|
||||
setId("titled-group-bg");
|
||||
label.setId("titled-group-bg-label");
|
||||
}
|
||||
|
||||
private void setActive() {
|
||||
setId("titled-group-bg-active");
|
||||
label.setId("titled-group-bg-label-active");
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text.get();
|
||||
}
|
||||
|
||||
public StringProperty textProperty() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text.set(text);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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.gui.components.paymentmethods;
|
||||
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.gui.util.validation.AliPayValidator;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.payment.AliPayAccount;
|
||||
import io.bitsquare.payment.AliPayAccountContractData;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public class AliPayForm extends PaymentMethodForm {
|
||||
private static final Logger log = LoggerFactory.getLogger(AliPayForm.class);
|
||||
|
||||
private final AliPayAccount aliPayAccount;
|
||||
private final AliPayValidator aliPayValidator;
|
||||
private InputTextField accountNrInputTextField;
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account nr.:", ((AliPayAccountContractData) paymentAccountContractData).getAccountNr());
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
public AliPayForm(PaymentAccount paymentAccount, AliPayValidator aliPayValidator, InputValidator inputValidator, GridPane gridPane, int gridRow) {
|
||||
super(paymentAccount, inputValidator, gridPane, gridRow);
|
||||
this.aliPayAccount = (AliPayAccount) paymentAccount;
|
||||
this.aliPayValidator = aliPayValidator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForAddAccount() {
|
||||
gridRowFrom = gridRow + 1;
|
||||
|
||||
accountNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Account nr.:").second;
|
||||
accountNrInputTextField.setValidator(aliPayValidator);
|
||||
accountNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
aliPayAccount.setAccountNr(newValue);
|
||||
updateFromInputs();
|
||||
});
|
||||
|
||||
addLabelTextField(gridPane, ++gridRow, "Currency:", aliPayAccount.getSingleTradeCurrency().getCodeAndName());
|
||||
addAllowedPeriod();
|
||||
addAccountNameTextFieldWithAutoFillCheckBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
String accountNr = accountNrInputTextField.getText();
|
||||
accountNr = accountNr.substring(0, Math.min(5, accountNr.length())) + "...";
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
accountNameTextField.setText(method.concat(", ").concat(accountNr));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForDisplayAccount() {
|
||||
gridRowFrom = gridRow;
|
||||
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, "Account nr.:", aliPayAccount.getAccountNr());
|
||||
addLabelTextField(gridPane, ++gridRow, "Currency:", aliPayAccount.getSingleTradeCurrency().getCodeAndName());
|
||||
addAllowedPeriod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAllInputsValid() {
|
||||
allInputsValid.set(isAccountNameValid()
|
||||
&& aliPayValidator.validate(aliPayAccount.getAccountNr()).isValid
|
||||
&& aliPayAccount.getTradeCurrencies().size() > 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* 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.gui.components.paymentmethods;
|
||||
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.gui.util.validation.AltCoinAddressValidator;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.payment.BlockChainAccount;
|
||||
import io.bitsquare.payment.BlockChainAccountContractData;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.util.StringConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public class BlockChainForm extends PaymentMethodForm {
|
||||
private static final Logger log = LoggerFactory.getLogger(BlockChainForm.class);
|
||||
|
||||
private final BlockChainAccount blockChainAccount;
|
||||
private final AltCoinAddressValidator altCoinAddressValidator;
|
||||
private InputTextField addressInputTextField;
|
||||
|
||||
private ComboBox<TradeCurrency> currencyComboBox;
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Address:", ((BlockChainAccountContractData) paymentAccountContractData).getAddress());
|
||||
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
|
||||
((BlockChainAccountContractData) paymentAccountContractData).getPaymentId() != null)
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Payment ID:", ((BlockChainAccountContractData) paymentAccountContractData).getPaymentId());
|
||||
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
public BlockChainForm(PaymentAccount paymentAccount, AltCoinAddressValidator altCoinAddressValidator, InputValidator inputValidator, GridPane gridPane,
|
||||
int gridRow) {
|
||||
super(paymentAccount, inputValidator, gridPane, gridRow);
|
||||
this.blockChainAccount = (BlockChainAccount) paymentAccount;
|
||||
this.altCoinAddressValidator = altCoinAddressValidator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForAddAccount() {
|
||||
gridRowFrom = gridRow + 1;
|
||||
|
||||
addTradeCurrencyComboBox();
|
||||
currencyComboBox.setPrefWidth(250);
|
||||
addressInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Address:").second;
|
||||
addressInputTextField.setValidator(altCoinAddressValidator);
|
||||
|
||||
addressInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
blockChainAccount.setAddress(newValue);
|
||||
updateFromInputs();
|
||||
});
|
||||
|
||||
addAllowedPeriod();
|
||||
addAccountNameTextFieldWithAutoFillCheckBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
String address = addressInputTextField.getText();
|
||||
address = address.substring(0, Math.min(9, address.length())) + "...";
|
||||
String currency = paymentAccount.getSingleTradeCurrency() != null ? paymentAccount.getSingleTradeCurrency().getCode() : "?";
|
||||
accountNameTextField.setText(method.concat(", ").concat(currency).concat(", ").concat(address));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForDisplayAccount() {
|
||||
gridRowFrom = gridRow;
|
||||
addLabelTextField(gridPane, gridRow, "Account name:", blockChainAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(blockChainAccount.getPaymentMethod().getId()));
|
||||
addLabelTextField(gridPane, ++gridRow, "Address:", blockChainAccount.getAddress());
|
||||
addLabelTextField(gridPane, ++gridRow, "Crypto currency:", blockChainAccount.getSingleTradeCurrency().getCodeAndName());
|
||||
addAllowedPeriod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAllInputsValid() {
|
||||
allInputsValid.set(isAccountNameValid()
|
||||
&& altCoinAddressValidator.validate(blockChainAccount.getAddress()).isValid
|
||||
&& blockChainAccount.getSingleTradeCurrency() != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addTradeCurrencyComboBox() {
|
||||
currencyComboBox = addLabelComboBox(gridPane, ++gridRow, "Crypto currency:").second;
|
||||
currencyComboBox.setPromptText("Select crypto currency");
|
||||
currencyComboBox.setItems(FXCollections.observableArrayList(CurrencyUtil.getSortedCryptoCurrencies()));
|
||||
currencyComboBox.setVisibleRowCount(Math.min(currencyComboBox.getItems().size(), 20));
|
||||
currencyComboBox.setConverter(new StringConverter<TradeCurrency>() {
|
||||
@Override
|
||||
public String toString(TradeCurrency tradeCurrency) {
|
||||
return tradeCurrency.getCodeAndName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeCurrency fromString(String s) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
currencyComboBox.setOnAction(e -> {
|
||||
paymentAccount.setSingleTradeCurrency(currencyComboBox.getSelectionModel().getSelectedItem());
|
||||
updateFromInputs();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* 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.gui.components.paymentmethods;
|
||||
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import io.bitsquare.gui.util.validation.OKPayValidator;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.payment.OKPayAccount;
|
||||
import io.bitsquare.payment.OKPayAccountContractData;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.VPos;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.FlowPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public class OKPayForm extends PaymentMethodForm {
|
||||
private static final Logger log = LoggerFactory.getLogger(OKPayForm.class);
|
||||
|
||||
private final OKPayAccount okPayAccount;
|
||||
private final OKPayValidator okPayValidator;
|
||||
private InputTextField accountNrInputTextField;
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account nr.:", ((OKPayAccountContractData) paymentAccountContractData).getAccountNr());
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
public OKPayForm(PaymentAccount paymentAccount, OKPayValidator okPayValidator, InputValidator inputValidator, GridPane gridPane, int gridRow) {
|
||||
super(paymentAccount, inputValidator, gridPane, gridRow);
|
||||
this.okPayAccount = (OKPayAccount) paymentAccount;
|
||||
this.okPayValidator = okPayValidator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForAddAccount() {
|
||||
gridRowFrom = gridRow + 1;
|
||||
|
||||
accountNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Account nr.:").second;
|
||||
accountNrInputTextField.setValidator(okPayValidator);
|
||||
accountNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
okPayAccount.setAccountNr(newValue);
|
||||
updateFromInputs();
|
||||
});
|
||||
|
||||
addCurrenciesGrid(true);
|
||||
addAllowedPeriod();
|
||||
addAccountNameTextFieldWithAutoFillCheckBox();
|
||||
}
|
||||
|
||||
private void addCurrenciesGrid(boolean isEditable) {
|
||||
Label label = addLabel(gridPane, ++gridRow, "Supported OKPay currencies:", 0);
|
||||
GridPane.setValignment(label, VPos.TOP);
|
||||
FlowPane flowPane = new FlowPane();
|
||||
flowPane.setPadding(new Insets(10, 10, 10, 10));
|
||||
flowPane.setVgap(10);
|
||||
flowPane.setHgap(10);
|
||||
|
||||
if (isEditable)
|
||||
flowPane.setId("flowpane-checkboxes-bg");
|
||||
else
|
||||
flowPane.setId("flowpane-checkboxes-non-editable-bg");
|
||||
|
||||
CurrencyUtil.getAllOKPayCurrencies().stream().forEach(e ->
|
||||
{
|
||||
CheckBox checkBox = new CheckBox(e.getCode());
|
||||
checkBox.setMouseTransparent(!isEditable);
|
||||
checkBox.setSelected(okPayAccount.getTradeCurrencies().contains(e));
|
||||
checkBox.setMinWidth(60);
|
||||
checkBox.setMaxWidth(checkBox.getMinWidth());
|
||||
checkBox.setOnAction(event -> {
|
||||
if (checkBox.isSelected())
|
||||
okPayAccount.addCurrency(e);
|
||||
else
|
||||
okPayAccount.removeCurrency(e);
|
||||
|
||||
updateAllInputsValid();
|
||||
});
|
||||
flowPane.getChildren().add(checkBox);
|
||||
});
|
||||
|
||||
GridPane.setRowIndex(flowPane, gridRow);
|
||||
GridPane.setColumnIndex(flowPane, 1);
|
||||
gridPane.getChildren().add(flowPane);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
String accountNr = accountNrInputTextField.getText();
|
||||
accountNr = accountNr.substring(0, Math.min(5, accountNr.length())) + "...";
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
accountNameTextField.setText(method.concat(", ").concat(accountNr));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForDisplayAccount() {
|
||||
gridRowFrom = gridRow;
|
||||
addLabelTextField(gridPane, gridRow, "Account name:", okPayAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(okPayAccount.getPaymentMethod().getId()));
|
||||
addLabelTextField(gridPane, ++gridRow, "Account nr.:", okPayAccount.getAccountNr());
|
||||
addAllowedPeriod();
|
||||
addCurrenciesGrid(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAllInputsValid() {
|
||||
allInputsValid.set(isAccountNameValid()
|
||||
&& okPayValidator.validate(okPayAccount.getAccountNr()).isValid
|
||||
&& okPayAccount.getTradeCurrencies().size() > 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* 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.gui.components.paymentmethods;
|
||||
|
||||
import io.bitsquare.common.util.Tuple3;
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.util.StringConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public abstract class PaymentMethodForm {
|
||||
private static final Logger log = LoggerFactory.getLogger(PaymentMethodForm.class);
|
||||
|
||||
protected final PaymentAccount paymentAccount;
|
||||
protected final InputValidator inputValidator;
|
||||
protected final GridPane gridPane;
|
||||
protected int gridRow;
|
||||
protected final BooleanProperty allInputsValid = new SimpleBooleanProperty();
|
||||
|
||||
protected int gridRowFrom;
|
||||
protected InputTextField accountNameTextField;
|
||||
protected CheckBox autoFillCheckBox;
|
||||
private ComboBox<TradeCurrency> currencyComboBox;
|
||||
|
||||
public PaymentMethodForm(PaymentAccount paymentAccount, InputValidator inputValidator, GridPane gridPane, int gridRow) {
|
||||
this.paymentAccount = paymentAccount;
|
||||
this.inputValidator = inputValidator;
|
||||
this.gridPane = gridPane;
|
||||
this.gridRow = gridRow;
|
||||
}
|
||||
|
||||
protected void addTradeCurrencyComboBox() {
|
||||
currencyComboBox = addLabelComboBox(gridPane, ++gridRow, "Currency:").second;
|
||||
currencyComboBox.setPromptText("Select currency");
|
||||
currencyComboBox.setItems(FXCollections.observableArrayList(CurrencyUtil.getAllSortedCurrencies()));
|
||||
currencyComboBox.setConverter(new StringConverter<TradeCurrency>() {
|
||||
@Override
|
||||
public String toString(TradeCurrency tradeCurrency) {
|
||||
return tradeCurrency.getCodeAndName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeCurrency fromString(String s) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
currencyComboBox.setOnAction(e -> {
|
||||
paymentAccount.setSingleTradeCurrency(currencyComboBox.getSelectionModel().getSelectedItem());
|
||||
updateFromInputs();
|
||||
});
|
||||
}
|
||||
|
||||
protected void addAccountNameTextFieldWithAutoFillCheckBox() {
|
||||
Tuple3<Label, InputTextField, CheckBox> tuple = addLabelInputTextFieldCheckBox(gridPane, ++gridRow, "Account name:", "Auto-fill");
|
||||
accountNameTextField = tuple.second;
|
||||
accountNameTextField.setPrefWidth(250);
|
||||
accountNameTextField.setEditable(false);
|
||||
accountNameTextField.setValidator(inputValidator);
|
||||
accountNameTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
paymentAccount.setAccountName(newValue);
|
||||
updateAllInputsValid();
|
||||
});
|
||||
autoFillCheckBox = tuple.third;
|
||||
autoFillCheckBox.setSelected(true);
|
||||
autoFillCheckBox.setOnAction(e -> {
|
||||
accountNameTextField.setEditable(!autoFillCheckBox.isSelected());
|
||||
autoFillNameTextField();
|
||||
});
|
||||
}
|
||||
|
||||
static void addAllowedPeriod(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
long hours = paymentAccountContractData.getMaxTradePeriod() / 6;
|
||||
String displayText = hours + " hours";
|
||||
if (hours == 24)
|
||||
displayText = "1 day";
|
||||
if (hours > 24)
|
||||
displayText = hours / 24 + " days";
|
||||
|
||||
addLabelTextField(gridPane, gridRow, "Max. allowed trade period:", displayText);
|
||||
}
|
||||
|
||||
protected void addAllowedPeriod() {
|
||||
long hours = paymentAccount.getPaymentMethod().getMaxTradePeriod() / 6;
|
||||
String displayText = hours + " hours";
|
||||
if (hours == 24)
|
||||
displayText = "1 day";
|
||||
if (hours > 24)
|
||||
displayText = hours / 24 + " days";
|
||||
|
||||
addLabelTextField(gridPane, ++gridRow, "Max. allowed trade period:", displayText);
|
||||
}
|
||||
|
||||
abstract protected void autoFillNameTextField();
|
||||
|
||||
abstract public void addFormForAddAccount();
|
||||
|
||||
abstract public void addFormForDisplayAccount();
|
||||
|
||||
protected abstract void updateAllInputsValid();
|
||||
|
||||
public void updateFromInputs() {
|
||||
autoFillNameTextField();
|
||||
updateAllInputsValid();
|
||||
}
|
||||
|
||||
public boolean isAccountNameValid() {
|
||||
return inputValidator.validate(paymentAccount.getAccountName()).isValid;
|
||||
}
|
||||
|
||||
public int getGridRow() {
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
public int getRowSpan() {
|
||||
return gridRow - gridRowFrom + 1;
|
||||
}
|
||||
|
||||
public PaymentAccount getPaymentAccount() {
|
||||
return paymentAccount;
|
||||
}
|
||||
|
||||
public BooleanProperty allInputsValidProperty() {
|
||||
return allInputsValid;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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.gui.components.paymentmethods;
|
||||
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import io.bitsquare.gui.util.validation.PerfectMoneyValidator;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import io.bitsquare.payment.PerfectMoneyAccount;
|
||||
import io.bitsquare.payment.PerfectMoneyAccountContractData;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public class PerfectMoneyForm extends PaymentMethodForm {
|
||||
private static final Logger log = LoggerFactory.getLogger(PerfectMoneyForm.class);
|
||||
|
||||
private final PerfectMoneyAccount perfectMoneyAccount;
|
||||
private final PerfectMoneyValidator perfectMoneyValidator;
|
||||
private InputTextField accountNrInputTextField;
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name:", ((PerfectMoneyAccountContractData) paymentAccountContractData)
|
||||
.getHolderName());
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account nr.:", ((PerfectMoneyAccountContractData) paymentAccountContractData).getAccountNr());
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
public PerfectMoneyForm(PaymentAccount paymentAccount, PerfectMoneyValidator perfectMoneyValidator, InputValidator inputValidator, GridPane gridPane, int
|
||||
gridRow) {
|
||||
super(paymentAccount, inputValidator, gridPane, gridRow);
|
||||
this.perfectMoneyAccount = (PerfectMoneyAccount) paymentAccount;
|
||||
this.perfectMoneyValidator = perfectMoneyValidator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForAddAccount() {
|
||||
gridRowFrom = gridRow + 1;
|
||||
|
||||
InputTextField holderNameInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Account holder name:").second;
|
||||
holderNameInputTextField.setValidator(inputValidator);
|
||||
holderNameInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
perfectMoneyAccount.setHolderName(newValue);
|
||||
updateFromInputs();
|
||||
});
|
||||
|
||||
accountNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Account nr.:").second;
|
||||
accountNrInputTextField.setValidator(perfectMoneyValidator);
|
||||
accountNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
perfectMoneyAccount.setAccountNr(newValue);
|
||||
updateFromInputs();
|
||||
});
|
||||
|
||||
addLabelTextField(gridPane, ++gridRow, "Currency:", perfectMoneyAccount.getSingleTradeCurrency().getCodeAndName());
|
||||
addAllowedPeriod();
|
||||
addAccountNameTextFieldWithAutoFillCheckBox();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
String accountNr = accountNrInputTextField.getText();
|
||||
accountNr = accountNr.substring(0, Math.min(5, accountNr.length())) + "...";
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
accountNameTextField.setText(method.concat(", ").concat(accountNr));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForDisplayAccount() {
|
||||
gridRowFrom = gridRow;
|
||||
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, "Account holder name:", perfectMoneyAccount.getHolderName());
|
||||
addLabelTextField(gridPane, ++gridRow, "Account nr.:", perfectMoneyAccount.getAccountNr());
|
||||
addLabelTextField(gridPane, ++gridRow, "Currency:", perfectMoneyAccount.getSingleTradeCurrency().getCodeAndName());
|
||||
addAllowedPeriod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAllInputsValid() {
|
||||
allInputsValid.set(isAccountNameValid()
|
||||
&& perfectMoneyValidator.validate(perfectMoneyAccount.getAccountNr()).isValid
|
||||
&& perfectMoneyAccount.getTradeCurrencies().size() > 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* 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.gui.components.paymentmethods;
|
||||
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.gui.util.validation.BICValidator;
|
||||
import io.bitsquare.gui.util.validation.IBANValidator;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import io.bitsquare.locale.*;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import io.bitsquare.payment.SepaAccount;
|
||||
import io.bitsquare.payment.SepaAccountContractData;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.VPos;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.FlowPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.util.StringConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public class SepaForm extends PaymentMethodForm {
|
||||
private static final Logger log = LoggerFactory.getLogger(SepaForm.class);
|
||||
|
||||
private final SepaAccount sepaAccount;
|
||||
private final IBANValidator ibanValidator;
|
||||
private final BICValidator bicValidator;
|
||||
private InputTextField ibanInputTextField;
|
||||
private InputTextField bicInputTextField;
|
||||
private TextField currencyTextField;
|
||||
private List<CheckBox> euroCountryCheckBoxes = new ArrayList<>();
|
||||
private List<CheckBox> nonEuroCountryCheckBoxes = new ArrayList<>();
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name:", ((SepaAccountContractData) paymentAccountContractData).getHolderName());
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "IBAN:", ((SepaAccountContractData) paymentAccountContractData).getIban());
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "BIC/SWIFT:", ((SepaAccountContractData) paymentAccountContractData).getBic());
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
public SepaForm(PaymentAccount paymentAccount, IBANValidator ibanValidator, BICValidator bicValidator, InputValidator inputValidator,
|
||||
GridPane gridPane, int gridRow) {
|
||||
super(paymentAccount, inputValidator, gridPane, gridRow);
|
||||
this.sepaAccount = (SepaAccount) paymentAccount;
|
||||
this.ibanValidator = ibanValidator;
|
||||
this.bicValidator = bicValidator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForAddAccount() {
|
||||
gridRowFrom = gridRow + 1;
|
||||
|
||||
InputTextField holderNameInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Account holder name:").second;
|
||||
holderNameInputTextField.setValidator(inputValidator);
|
||||
holderNameInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
sepaAccount.setHolderName(newValue);
|
||||
updateFromInputs();
|
||||
});
|
||||
|
||||
ibanInputTextField = addLabelInputTextField(gridPane, ++gridRow, "IBAN:").second;
|
||||
ibanInputTextField.setValidator(ibanValidator);
|
||||
ibanInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
sepaAccount.setIban(newValue);
|
||||
updateFromInputs();
|
||||
|
||||
});
|
||||
bicInputTextField = addLabelInputTextField(gridPane, ++gridRow, "BIC/SWIFT:").second;
|
||||
bicInputTextField.setValidator(bicValidator);
|
||||
bicInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
sepaAccount.setBic(newValue);
|
||||
updateFromInputs();
|
||||
|
||||
});
|
||||
|
||||
Tuple2<Label, ComboBox> tuple2 = addLabelComboBox(gridPane, ++gridRow, "Country of Bank:");
|
||||
ComboBox<Country> countryComboBox = tuple2.second;
|
||||
countryComboBox.setPromptText("Select country of Bank");
|
||||
countryComboBox.setConverter(new StringConverter<Country>() {
|
||||
@Override
|
||||
public String toString(Country country) {
|
||||
return country.code + " (" + country.name + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Country fromString(String s) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
countryComboBox.setOnAction(e -> {
|
||||
Country selectedItem = countryComboBox.getSelectionModel().getSelectedItem();
|
||||
sepaAccount.setCountry(selectedItem);
|
||||
TradeCurrency currency = CurrencyUtil.getCurrencyByCountryCode(selectedItem.code);
|
||||
sepaAccount.setSingleTradeCurrency(currency);
|
||||
currencyTextField.setText(currency.getCodeAndName());
|
||||
updateCountriesSelection(true, euroCountryCheckBoxes);
|
||||
updateCountriesSelection(true, nonEuroCountryCheckBoxes);
|
||||
updateFromInputs();
|
||||
});
|
||||
|
||||
currencyTextField = addLabelTextField(gridPane, ++gridRow, "Currency:").second;
|
||||
|
||||
addEuroCountriesGrid(true);
|
||||
addNonEuroCountriesGrid(true);
|
||||
addAllowedPeriod();
|
||||
addAccountNameTextFieldWithAutoFillCheckBox();
|
||||
|
||||
countryComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllSepaCountries()));
|
||||
Country country = CountryUtil.getDefaultCountry();
|
||||
countryComboBox.getSelectionModel().select(country);
|
||||
sepaAccount.setCountry(country);
|
||||
TradeCurrency currency = CurrencyUtil.getCurrencyByCountryCode(country.code);
|
||||
sepaAccount.setSingleTradeCurrency(currency);
|
||||
currencyTextField.setText(currency.getCodeAndName());
|
||||
updateFromInputs();
|
||||
}
|
||||
|
||||
private void addEuroCountriesGrid(boolean isEditable) {
|
||||
addCountriesGrid(isEditable, "Accept taker countries (Euro):", euroCountryCheckBoxes, CountryUtil.getAllSepaEuroCountries());
|
||||
}
|
||||
|
||||
private void addNonEuroCountriesGrid(boolean isEditable) {
|
||||
addCountriesGrid(isEditable, "Accepted taker countries (non-Euro):", nonEuroCountryCheckBoxes, CountryUtil.getAllSepaNonEuroCountries());
|
||||
}
|
||||
|
||||
private void addCountriesGrid(boolean isEditable, String title, List<CheckBox> checkBoxList, List<Country> dataProvider) {
|
||||
Label label = addLabel(gridPane, ++gridRow, title, 0);
|
||||
GridPane.setValignment(label, VPos.TOP);
|
||||
FlowPane flowPane = new FlowPane();
|
||||
flowPane.setPadding(new Insets(10, 10, 10, 10));
|
||||
flowPane.setVgap(10);
|
||||
flowPane.setHgap(10);
|
||||
|
||||
if (isEditable)
|
||||
flowPane.setId("flowpane-checkboxes-bg");
|
||||
else
|
||||
flowPane.setId("flowpane-checkboxes-non-editable-bg");
|
||||
|
||||
dataProvider.stream().forEach(country ->
|
||||
{
|
||||
final String countryCode = country.code;
|
||||
CheckBox checkBox = new CheckBox(countryCode);
|
||||
checkBox.setUserData(countryCode);
|
||||
checkBoxList.add(checkBox);
|
||||
checkBox.setMouseTransparent(!isEditable);
|
||||
checkBox.setMinWidth(45);
|
||||
checkBox.setMaxWidth(checkBox.getMinWidth());
|
||||
checkBox.setTooltip(new Tooltip(country.name));
|
||||
checkBox.setOnAction(event -> {
|
||||
if (checkBox.isSelected())
|
||||
sepaAccount.addAcceptedCountry(countryCode);
|
||||
else
|
||||
sepaAccount.removeAcceptedCountry(countryCode);
|
||||
|
||||
updateAllInputsValid();
|
||||
});
|
||||
flowPane.getChildren().add(checkBox);
|
||||
});
|
||||
updateCountriesSelection(isEditable, checkBoxList);
|
||||
|
||||
GridPane.setRowIndex(flowPane, gridRow);
|
||||
GridPane.setColumnIndex(flowPane, 1);
|
||||
gridPane.getChildren().add(flowPane);
|
||||
}
|
||||
|
||||
private void updateCountriesSelection(boolean isEditable, List<CheckBox> checkBoxList) {
|
||||
checkBoxList.stream().forEach(checkBox -> {
|
||||
String countryCode = (String) checkBox.getUserData();
|
||||
TradeCurrency selectedCurrency = sepaAccount.getSelectedTradeCurrency();
|
||||
if (selectedCurrency == null)
|
||||
selectedCurrency = CurrencyUtil.getCurrencyByCountryCode(CountryUtil.getDefaultCountry().code);
|
||||
|
||||
boolean selected;
|
||||
|
||||
if (isEditable) {
|
||||
selected = CurrencyUtil.getCurrencyByCountryCode(countryCode).getCode().equals(selectedCurrency.getCode());
|
||||
|
||||
if (selected)
|
||||
sepaAccount.addAcceptedCountry(countryCode);
|
||||
else
|
||||
sepaAccount.removeAcceptedCountry(countryCode);
|
||||
} else {
|
||||
selected = sepaAccount.getAcceptedCountryCodes().contains(countryCode);
|
||||
}
|
||||
checkBox.setSelected(selected);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
String iban = ibanInputTextField.getText();
|
||||
if (iban.length() > 5)
|
||||
iban = "..." + iban.substring(iban.length() - 5, iban.length());
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
String country = paymentAccount.getCountry() != null ? paymentAccount.getCountry().code : "?";
|
||||
String currency = paymentAccount.getSingleTradeCurrency() != null ? paymentAccount.getSingleTradeCurrency().getCode() : "?";
|
||||
accountNameTextField.setText(method.concat(", ").concat(currency).concat(", ").concat(country).concat(", ").concat(iban));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAllInputsValid() {
|
||||
allInputsValid.set(isAccountNameValid()
|
||||
&& bicValidator.validate(sepaAccount.getBic()).isValid
|
||||
&& ibanValidator.validate(sepaAccount.getIban()).isValid
|
||||
&& inputValidator.validate(sepaAccount.getHolderName()).isValid
|
||||
&& sepaAccount.getAcceptedCountryCodes().size() > 0
|
||||
&& sepaAccount.getSingleTradeCurrency() != null
|
||||
&& sepaAccount.getCountry() != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForDisplayAccount() {
|
||||
gridRowFrom = gridRow;
|
||||
addLabelTextField(gridPane, gridRow, "Account name:", sepaAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(sepaAccount.getPaymentMethod().getId()));
|
||||
addLabelTextField(gridPane, ++gridRow, "Account holder name:", sepaAccount.getHolderName());
|
||||
addLabelTextField(gridPane, ++gridRow, "IBAN:", sepaAccount.getIban());
|
||||
addLabelTextField(gridPane, ++gridRow, "BIC/SWIFT:", sepaAccount.getBic());
|
||||
addLabelTextField(gridPane, ++gridRow, "Location of Bank:", sepaAccount.getCountry().name);
|
||||
addLabelTextField(gridPane, ++gridRow, "Currency:", sepaAccount.getSingleTradeCurrency().getCodeAndName());
|
||||
addAllowedPeriod();
|
||||
addEuroCountriesGrid(false);
|
||||
addNonEuroCountriesGrid(false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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.gui.components.paymentmethods;
|
||||
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import io.bitsquare.gui.util.validation.SwishValidator;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import io.bitsquare.payment.SwishAccount;
|
||||
import io.bitsquare.payment.SwishAccountContractData;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.addLabelInputTextField;
|
||||
import static io.bitsquare.gui.util.FormBuilder.addLabelTextField;
|
||||
|
||||
public class SwishForm extends PaymentMethodForm {
|
||||
private static final Logger log = LoggerFactory.getLogger(SwishForm.class);
|
||||
|
||||
private final SwishAccount swishAccount;
|
||||
private final SwishValidator swishValidator;
|
||||
private InputTextField mobileNrInputTextField;
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextField(gridPane, ++gridRow, "Account holder name:", ((SwishAccountContractData) paymentAccountContractData).getHolderName());
|
||||
addLabelTextField(gridPane, ++gridRow, "Mobile nr.:", ((SwishAccountContractData) paymentAccountContractData).getMobileNr());
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
public SwishForm(PaymentAccount paymentAccount, SwishValidator swishValidator, InputValidator inputValidator, GridPane gridPane, int gridRow) {
|
||||
super(paymentAccount, inputValidator, gridPane, gridRow);
|
||||
this.swishAccount = (SwishAccount) paymentAccount;
|
||||
this.swishValidator = swishValidator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForAddAccount() {
|
||||
gridRowFrom = gridRow + 1;
|
||||
|
||||
InputTextField holderNameInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Account holder name:").second;
|
||||
holderNameInputTextField.setValidator(inputValidator);
|
||||
holderNameInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
swishAccount.setHolderName(newValue);
|
||||
updateFromInputs();
|
||||
});
|
||||
|
||||
mobileNrInputTextField = addLabelInputTextField(gridPane, ++gridRow, "Mobile nr.:").second;
|
||||
mobileNrInputTextField.setValidator(swishValidator);
|
||||
mobileNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
swishAccount.setMobileNr(newValue);
|
||||
updateFromInputs();
|
||||
});
|
||||
|
||||
addLabelTextField(gridPane, ++gridRow, "Currency:", swishAccount.getSingleTradeCurrency().getCodeAndName());
|
||||
addAllowedPeriod();
|
||||
addAccountNameTextFieldWithAutoFillCheckBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
String mobileNr = mobileNrInputTextField.getText();
|
||||
mobileNr = mobileNr.substring(0, Math.min(5, mobileNr.length())) + "...";
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
accountNameTextField.setText(method.concat(", ").concat(mobileNr));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormForDisplayAccount() {
|
||||
gridRowFrom = gridRow;
|
||||
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, "Account holder name:", swishAccount.getHolderName());
|
||||
addLabelTextField(gridPane, ++gridRow, "Mobile nr.:", swishAccount.getMobileNr());
|
||||
addLabelTextField(gridPane, ++gridRow, "Currency:", swishAccount.getSingleTradeCurrency().getCodeAndName());
|
||||
addAllowedPeriod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAllInputsValid() {
|
||||
allInputsValid.set(isAccountNameValid()
|
||||
&& swishValidator.validate(swishAccount.getMobileNr()).isValid
|
||||
&& inputValidator.validate(swishAccount.getHolderName()).isValid
|
||||
&& swishAccount.getTradeCurrencies().size() > 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.account.arbitratorregistration.ArbitratorRegistrationView"
|
||||
spacing="10"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
||||
<padding>
|
||||
<Insets bottom="0.0" left="10.0" right="10.0" top="0.0"/>
|
||||
</padding>
|
||||
</VBox>
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* 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.gui.main.account.arbitratorregistration;
|
||||
|
||||
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.arbitration.Arbitrator;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||
import io.bitsquare.gui.common.view.FxmlView;
|
||||
import io.bitsquare.gui.popups.Popup;
|
||||
import io.bitsquare.gui.util.FormBuilder;
|
||||
import io.bitsquare.gui.util.ImageUtil;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.locale.LanguageUtil;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.VPos;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.util.Callback;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
@FxmlView
|
||||
public class ArbitratorRegistrationView extends ActivatableViewAndModel<VBox, ArbitratorRegistrationViewModel> {
|
||||
|
||||
private TextField pubKeyTextField;
|
||||
private ListView<String> languagesListView;
|
||||
private ComboBox<String> languageComboBox;
|
||||
|
||||
private int gridRow = 0;
|
||||
private Button registerButton;
|
||||
private Button revokeButton;
|
||||
|
||||
private ChangeListener<Arbitrator> arbitratorChangeListener;
|
||||
private EnterPrivKeyPopup enterPrivKeyPopup;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private ArbitratorRegistrationView(ArbitratorRegistrationViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
buildUI();
|
||||
|
||||
languageComboBox.setItems(model.allLanguageCodes);
|
||||
|
||||
arbitratorChangeListener = (observable, oldValue, arbitrator) -> updateLanguageList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
}
|
||||
|
||||
public void onTabSelection(boolean isSelectedTab) {
|
||||
if (isSelectedTab) {
|
||||
model.myArbitratorProperty.addListener(arbitratorChangeListener);
|
||||
updateLanguageList();
|
||||
|
||||
if (model.registrationPubKeyAsHex.get() == null && enterPrivKeyPopup == null) {
|
||||
enterPrivKeyPopup = new EnterPrivKeyPopup();
|
||||
enterPrivKeyPopup.onClose(() -> enterPrivKeyPopup = null)
|
||||
.onKey(privKey -> model.setPrivKeyAndCheckPubKey(privKey))
|
||||
.width(700)
|
||||
.show();
|
||||
}
|
||||
} else {
|
||||
model.myArbitratorProperty.removeListener(arbitratorChangeListener);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLanguageList() {
|
||||
languagesListView.setItems(model.languageCodes);
|
||||
languagesListView.setPrefHeight(languagesListView.getItems().size() * Layout.LIST_ROW_HEIGHT + 2);
|
||||
languagesListView.getItems().addListener((ListChangeListener<String>)
|
||||
c -> languagesListView.setPrefHeight(languagesListView.getItems().size() * Layout.LIST_ROW_HEIGHT + 2));
|
||||
}
|
||||
|
||||
private void buildUI() {
|
||||
GridPane gridPane = new GridPane();
|
||||
gridPane.setPadding(new Insets(30, 25, -1, 25));
|
||||
gridPane.setHgap(5);
|
||||
gridPane.setVgap(5);
|
||||
ColumnConstraints columnConstraints1 = new ColumnConstraints();
|
||||
columnConstraints1.setHalignment(HPos.RIGHT);
|
||||
columnConstraints1.setHgrow(Priority.SOMETIMES);
|
||||
columnConstraints1.setMinWidth(200);
|
||||
ColumnConstraints columnConstraints2 = new ColumnConstraints();
|
||||
columnConstraints2.setHgrow(Priority.ALWAYS);
|
||||
gridPane.getColumnConstraints().addAll(columnConstraints1, columnConstraints2);
|
||||
root.getChildren().add(gridPane);
|
||||
|
||||
addTitledGroupBg(gridPane, gridRow, 3, "Arbitrator registration");
|
||||
pubKeyTextField = FormBuilder.addLabelTextField(gridPane, gridRow, "Public key:",
|
||||
model.registrationPubKeyAsHex.get(), Layout.FIRST_ROW_DISTANCE).second;
|
||||
|
||||
if (BitsquareApp.DEV_MODE)
|
||||
pubKeyTextField.setText("6ac43ea1df2a290c1c8391736aa42e4339c5cb4f110ff0257a13b63211977b7a");
|
||||
|
||||
pubKeyTextField.textProperty().bind(model.registrationPubKeyAsHex);
|
||||
|
||||
Tuple2<Label, ListView> tuple = addLabelListView(gridPane, ++gridRow, "Your languages:");
|
||||
GridPane.setValignment(tuple.first, VPos.TOP);
|
||||
languagesListView = tuple.second;
|
||||
languagesListView.disableProperty().bind(model.registrationEditDisabled);
|
||||
languagesListView.setMinHeight(3 * Layout.LIST_ROW_HEIGHT + 2);
|
||||
languagesListView.setMaxHeight(6 * Layout.LIST_ROW_HEIGHT + 2);
|
||||
languagesListView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
|
||||
@Override
|
||||
public ListCell<String> call(ListView<String> list) {
|
||||
return new ListCell<String>() {
|
||||
final Label label = new Label();
|
||||
final ImageView icon = ImageUtil.getImageViewById(ImageUtil.REMOVE_ICON);
|
||||
final Button removeButton = new Button("", icon);
|
||||
final AnchorPane pane = new AnchorPane(label, removeButton);
|
||||
|
||||
{
|
||||
label.setLayoutY(5);
|
||||
removeButton.setId("icon-button");
|
||||
AnchorPane.setRightAnchor(removeButton, 0d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateItem(final String item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
label.setText(LanguageUtil.getDisplayName(item));
|
||||
removeButton.setOnAction(e -> onRemoveLanguage(item));
|
||||
setGraphic(pane);
|
||||
} else {
|
||||
setGraphic(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
languageComboBox = addLabelComboBox(gridPane, ++gridRow).second;
|
||||
languageComboBox.disableProperty().bind(model.registrationEditDisabled);
|
||||
languageComboBox.setPromptText("Add language");
|
||||
languageComboBox.setConverter(new StringConverter<String>() {
|
||||
@Override
|
||||
public String toString(String code) {
|
||||
return LanguageUtil.getDisplayName(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fromString(String s) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
languageComboBox.setOnAction(e -> onAddLanguage());
|
||||
|
||||
registerButton = addButtonAfterGroup(gridPane, ++gridRow, "Register arbitrator");
|
||||
registerButton.disableProperty().bind(model.registrationEditDisabled);
|
||||
registerButton.setOnAction(e -> onRegister());
|
||||
|
||||
revokeButton = addButton(gridPane, ++gridRow, "Revoke registration");
|
||||
revokeButton.setDefaultButton(false);
|
||||
revokeButton.disableProperty().bind(model.revokeButtonDisabled);
|
||||
revokeButton.setOnAction(e -> onRevoke());
|
||||
|
||||
addTitledGroupBg(gridPane, ++gridRow, 2, "Information", Layout.GROUP_DISTANCE);
|
||||
Label infoLabel = addMultilineLabel(gridPane, gridRow);
|
||||
GridPane.setMargin(infoLabel, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 0, 0, 0));
|
||||
infoLabel.setText("Please not that you need to stay available for 15 days after revoking as there might be trades which are using you as " +
|
||||
"arbitrator. The max. allowed trader period is 8 days and the dispute process might take up to 7 days.");
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI actions
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void onAddLanguage() {
|
||||
model.onAddLanguage(languageComboBox.getSelectionModel().getSelectedItem());
|
||||
UserThread.execute(() -> languageComboBox.getSelectionModel().clearSelection());
|
||||
}
|
||||
|
||||
private void onRemoveLanguage(String locale) {
|
||||
model.onRemoveLanguage(locale);
|
||||
|
||||
if (languagesListView.getItems().size() == 0) {
|
||||
new Popup().warning("You need to set at least 1 language.\nWe added the default language for you.").show();
|
||||
model.onAddLanguage(LanguageUtil.getDefaultLanguageLocaleAsCode());
|
||||
}
|
||||
}
|
||||
|
||||
private void onRevoke() {
|
||||
model.onRevoke(
|
||||
() -> new Popup().information("You have successfully removed your arbitrator from the P2P network.").show(),
|
||||
(errorMessage) -> new Popup().error("Could not remove arbitrator.\nError message: " + errorMessage).show());
|
||||
}
|
||||
|
||||
private void onRegister() {
|
||||
model.onRegister(
|
||||
() -> new Popup().information("You have successfully registered your arbitrator to the P2P network.").show(),
|
||||
(errorMessage) -> new Popup().error("Could not register arbitrator.\nError message: " + errorMessage).show());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* 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.gui.main.account.arbitratorregistration;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.arbitration.Arbitrator;
|
||||
import io.bitsquare.arbitration.ArbitratorManager;
|
||||
import io.bitsquare.btc.AddressEntry;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.common.crypto.KeyRing;
|
||||
import io.bitsquare.common.handlers.ErrorMessageHandler;
|
||||
import io.bitsquare.common.handlers.ResultHandler;
|
||||
import io.bitsquare.gui.common.model.ActivatableViewModel;
|
||||
import io.bitsquare.locale.LanguageUtil;
|
||||
import io.bitsquare.p2p.Address;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.user.User;
|
||||
import javafx.beans.property.*;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.MapChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.core.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
class ArbitratorRegistrationViewModel extends ActivatableViewModel {
|
||||
private final ArbitratorManager arbitratorManager;
|
||||
private P2PService p2PService;
|
||||
private final WalletService walletService;
|
||||
private final KeyRing keyRing;
|
||||
|
||||
final BooleanProperty registrationEditDisabled = new SimpleBooleanProperty(true);
|
||||
final BooleanProperty revokeButtonDisabled = new SimpleBooleanProperty(true);
|
||||
final ObjectProperty<Arbitrator> myArbitratorProperty = new SimpleObjectProperty<>();
|
||||
|
||||
final ObservableList<String> languageCodes = FXCollections.observableArrayList(LanguageUtil.getDefaultLanguageLocaleAsCode());
|
||||
final ObservableList<String> allLanguageCodes = FXCollections.observableArrayList(LanguageUtil.getAllLanguageCodes());
|
||||
private boolean allDataValid;
|
||||
private final MapChangeListener<Address, Arbitrator> arbitratorMapChangeListener;
|
||||
private ECKey registrationKey;
|
||||
StringProperty registrationPubKeyAsHex = new SimpleStringProperty();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public ArbitratorRegistrationViewModel(ArbitratorManager arbitratorManager,
|
||||
User user,
|
||||
P2PService p2PService,
|
||||
WalletService walletService,
|
||||
KeyRing keyRing) {
|
||||
this.arbitratorManager = arbitratorManager;
|
||||
this.p2PService = p2PService;
|
||||
this.walletService = walletService;
|
||||
this.keyRing = keyRing;
|
||||
|
||||
arbitratorMapChangeListener = new MapChangeListener<Address, Arbitrator>() {
|
||||
@Override
|
||||
public void onChanged(Change<? extends Address, ? extends Arbitrator> change) {
|
||||
Arbitrator myRegisteredArbitrator = user.getRegisteredArbitrator();
|
||||
myArbitratorProperty.set(myRegisteredArbitrator);
|
||||
|
||||
// We don't reset the languages in case of revokation, as its likely that the arbitrator will use the same again when he re-activate
|
||||
// registration later
|
||||
if (myRegisteredArbitrator != null)
|
||||
languageCodes.setAll(myRegisteredArbitrator.getLanguageCodes());
|
||||
|
||||
updateDisableStates();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
arbitratorManager.getArbitratorsObservableMap().addListener(arbitratorMapChangeListener);
|
||||
updateDisableStates();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
arbitratorManager.getArbitratorsObservableMap().removeListener(arbitratorMapChangeListener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI actions
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void onAddLanguage(String code) {
|
||||
if (code != null && !languageCodes.contains(code))
|
||||
languageCodes.add(code);
|
||||
|
||||
updateDisableStates();
|
||||
}
|
||||
|
||||
void onRemoveLanguage(String code) {
|
||||
if (code != null && languageCodes.contains(code))
|
||||
languageCodes.remove(code);
|
||||
|
||||
updateDisableStates();
|
||||
}
|
||||
|
||||
boolean setPrivKeyAndCheckPubKey(String privKeyString) {
|
||||
ECKey _registrationKey = arbitratorManager.getRegistrationKey(privKeyString);
|
||||
if (_registrationKey != null) {
|
||||
String _registrationPubKeyAsHex = Utils.HEX.encode(_registrationKey.getPubKey());
|
||||
boolean isKeyValid = arbitratorManager.isPublicKeyInList(_registrationPubKeyAsHex);
|
||||
if (isKeyValid) {
|
||||
registrationKey = _registrationKey;
|
||||
registrationPubKeyAsHex.set(_registrationPubKeyAsHex);
|
||||
}
|
||||
updateDisableStates();
|
||||
return isKeyValid;
|
||||
} else {
|
||||
updateDisableStates();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void onRegister(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
updateDisableStates();
|
||||
if (allDataValid) {
|
||||
AddressEntry arbitratorDepositAddressEntry = walletService.getArbitratorAddressEntry();
|
||||
String registrationSignature = arbitratorManager.signStorageSignaturePubKey(registrationKey);
|
||||
Arbitrator arbitrator = new Arbitrator(
|
||||
p2PService.getAddress(),
|
||||
arbitratorDepositAddressEntry.getPubKey(),
|
||||
arbitratorDepositAddressEntry.getAddressString(),
|
||||
keyRing.getPubKeyRing(),
|
||||
new ArrayList<>(languageCodes),
|
||||
new Date(),
|
||||
registrationKey.getPubKey(),
|
||||
registrationSignature
|
||||
);
|
||||
if (arbitrator != null) {
|
||||
arbitratorManager.addArbitrator(arbitrator,
|
||||
() -> {
|
||||
updateDisableStates();
|
||||
resultHandler.handleResult();
|
||||
},
|
||||
(errorMessage) -> {
|
||||
updateDisableStates();
|
||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void onRevoke(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
arbitratorManager.removeArbitrator(
|
||||
() -> {
|
||||
updateDisableStates();
|
||||
resultHandler.handleResult();
|
||||
},
|
||||
(errorMessage) -> {
|
||||
updateDisableStates();
|
||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
private void updateDisableStates() {
|
||||
allDataValid = languageCodes != null && languageCodes.size() > 0 && registrationKey != null && registrationPubKeyAsHex.get() != null;
|
||||
registrationEditDisabled.set(!allDataValid || myArbitratorProperty.get() != null);
|
||||
revokeButtonDisabled.set(!allDataValid || myArbitratorProperty.get() == null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* 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.gui.main.account.arbitratorregistration;
|
||||
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.popups.Popup;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class EnterPrivKeyPopup extends Popup {
|
||||
private Button unlockButton;
|
||||
private InputTextField keyInputTextField;
|
||||
private PrivKeyHandler privKeyHandler;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public interface PrivKeyHandler {
|
||||
boolean checkKey(String privKey);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public EnterPrivKeyPopup() {
|
||||
}
|
||||
|
||||
public EnterPrivKeyPopup show() {
|
||||
if (gridPane != null) {
|
||||
rowIndex = -1;
|
||||
gridPane.getChildren().clear();
|
||||
}
|
||||
|
||||
if (headLine == null)
|
||||
headLine = "Registration open for invited arbitrators only";
|
||||
|
||||
createGridPane();
|
||||
addHeadLine();
|
||||
addInputFields();
|
||||
addButtons();
|
||||
createPopup();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public EnterPrivKeyPopup onClose(Runnable closeHandler) {
|
||||
this.closeHandlerOptional = Optional.of(closeHandler);
|
||||
return this;
|
||||
}
|
||||
|
||||
public EnterPrivKeyPopup onKey(PrivKeyHandler privKeyHandler) {
|
||||
this.privKeyHandler = privKeyHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void addInputFields() {
|
||||
Label label = new Label("Enter private key:");
|
||||
label.setWrapText(true);
|
||||
GridPane.setMargin(label, new Insets(3, 0, 0, 0));
|
||||
GridPane.setRowIndex(label, ++rowIndex);
|
||||
|
||||
keyInputTextField = new InputTextField();
|
||||
//TODO change when testing is done
|
||||
if (BitsquareApp.DEV_MODE)
|
||||
keyInputTextField.setText("6ac43ea1df2a290c1c8391736aa42e4339c5cb4f110ff0257a13b63211977b7a");
|
||||
GridPane.setMargin(keyInputTextField, new Insets(3, 0, 0, 0));
|
||||
GridPane.setRowIndex(keyInputTextField, rowIndex);
|
||||
GridPane.setColumnIndex(keyInputTextField, 1);
|
||||
keyInputTextField.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
unlockButton.setDisable(newValue.length() == 0);
|
||||
});
|
||||
gridPane.getChildren().addAll(label, keyInputTextField);
|
||||
}
|
||||
|
||||
private void addButtons() {
|
||||
unlockButton = new Button("Unlock");
|
||||
unlockButton.setDefaultButton(true);
|
||||
unlockButton.setDisable(keyInputTextField.getText().length() == 0);
|
||||
unlockButton.setOnAction(e -> {
|
||||
if (privKeyHandler.checkKey(keyInputTextField.getText()))
|
||||
hide();
|
||||
else
|
||||
new Popup().warning("The key you entered was not correct.").width(300).onClose(() -> blurAgain()).show();
|
||||
});
|
||||
|
||||
Button cancelButton = new Button("Close");
|
||||
cancelButton.setOnAction(event -> {
|
||||
hide();
|
||||
closeHandlerOptional.ifPresent(closeHandler -> closeHandler.run());
|
||||
});
|
||||
|
||||
HBox hBox = new HBox();
|
||||
hBox.setSpacing(10);
|
||||
GridPane.setRowIndex(hBox, ++rowIndex);
|
||||
GridPane.setColumnIndex(hBox, 1);
|
||||
hBox.getChildren().addAll(unlockButton, cancelButton);
|
||||
gridPane.getChildren().add(hBox);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue