diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000000..8a67891ccde
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,25 @@
+.git
+.gitignore
+.gitmodules
+.dockerignore
+.travis.yml
+docker-compose.yml
+docker-compose-base.yml
+Dockerfile
+.idea
+*.iml
+target
+support
+.gradle
+build
+out
+doc
+
+http-api/docker/dev/Dockerfile
+http-api/docker/prod/Dockerfile
+http-api/.dockerignore
+http-api/.editorconfig
+http-api/.git
+http-api/.gitignore
+http-api/.travis.yml
+http-api/support
diff --git a/.travis.yml b/.travis.yml
index 9a389a5e411..1b5eaee1152 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,29 @@
language: java
jdk: openjdk10
-before_install:
- grep -v '^#' assets/src/main/resources/META-INF/services/bisq.asset.Asset | sort --check --dictionary-order --ignore-case
+sudo: required
+services:
+- docker
+jobs:
+ include:
+ - stage: asset ordering
+ install:
+ script: grep -v '^#' assets/src/main/resources/META-INF/services/bisq.asset.Asset | sort --check --dictionary-order --ignore-case
+ - stage: build
+ - stage: integration
+ env:
+ - CUBE_LOGGER_ENABLE=true
+ install: cd http-api; docker-compose build;
+ script: ../gradlew testIntegration;
+before_cache:
+- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
+- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
+cache:
+ directories:
+ - $HOME/.gradle/caches/
+ - $HOME/.gradle/wrapper/
notifications:
- slack:
- on_success: change
- on_failure: always
- rooms:
- - secure: EzlqWTBuhb3FCfApjUXaShWgsWOVDwMXI7ISMiVBkcl2VFISYs/lc/7Qjr7rdy4iqQOQXMcUPHdwMUp0diX+GxiSjLARjUpKIvNOPswZWBL+3Z1h28jyOwtHRviZbM1EU0BZROrr+ODyTNz2lf+L1iXTkpSvk50o5JAnAkumsPw=
+ slack:
+ on_success: change
+ on_failure: always
+ rooms:
+ - secure: EzlqWTBuhb3FCfApjUXaShWgsWOVDwMXI7ISMiVBkcl2VFISYs/lc/7Qjr7rdy4iqQOQXMcUPHdwMUp0diX+GxiSjLARjUpKIvNOPswZWBL+3Z1h28jyOwtHRviZbM1EU0BZROrr+ODyTNz2lf+L1iXTkpSvk50o5JAnAkumsPw=
diff --git a/build.gradle b/build.gradle
index ddf8b497bca..50f6a690a53 100644
--- a/build.gradle
+++ b/build.gradle
@@ -271,6 +271,85 @@ configure(project(':core')) {
}
+configure(project(':http-api')) {
+
+ apply plugin: 'application'
+
+ mainClassName = 'bisq.httpapi.app.HttpApiMain'
+
+ dependencies {
+ compile project(':common')
+ compile project(':assets')
+ compile project(':core')
+ compile project(':p2p')
+
+ compile 'org.eclipse.jetty:jetty-servlet:9.4.14.v20181114'
+ compile 'javax.activation:activation:1.1.1'
+ compile 'javax.ws.rs:javax.ws.rs-api:2.1'
+ compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.27'
+ compile 'org.glassfish.jersey.inject:jersey-hk2:2.27'
+ compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.27'
+ compile 'org.glassfish.jersey.media:jersey-media-multipart:2.27'
+ compile 'org.glassfish.jersey.ext:jersey-bean-validation:2.27'
+
+ compile 'io.swagger.core.v3:swagger-jaxrs2:2.0.6'
+ compile 'org.webjars:swagger-ui:3.20.1'
+
+ compileOnly 'org.projectlombok:lombok:1.18.2'
+ annotationProcessor 'org.projectlombok:lombok:1.18.2'
+
+ testCompile 'junit:junit:4.12'
+ testCompile('org.mockito:mockito-core:2.8.9') {
+ exclude(module: 'objenesis')
+ }
+ testCompileOnly 'org.projectlombok:lombok:1.18.2'
+ testAnnotationProcessor 'org.projectlombok:lombok:1.18.2'
+ testCompile "junit:junit:4.12"
+ testCompile "org.mockito:mockito-core:2.7.5"
+ testCompile "com.github.javafaker:javafaker:0.14"
+ testCompile "org.arquillian.universe:arquillian-junit:1.2.0.1"
+ testCompile "org.arquillian.universe:arquillian-cube-docker:1.2.0.1"
+ testCompile "org.arquillian.cube:arquillian-cube-docker:1.15.3"
+ testCompile "io.rest-assured:rest-assured:3.0.2"
+ }
+
+ sourceSets {
+ testIntegration {
+ java.srcDir 'src/testIntegration/java'
+ resources.srcDir 'src/testIntegration/resources'
+ compileClasspath += sourceSets.main.output + configurations.testRuntimeClasspath
+ runtimeClasspath += output + compileClasspath
+ }
+ }
+
+ task testIntegration(type: Test) {
+ group = LifecycleBasePlugin.VERIFICATION_GROUP
+ description = 'Runs the integration tests.'
+
+ maxHeapSize = '1024m'
+
+ testClassesDir = sourceSets.testIntegration.output.classesDir
+ classpath = sourceSets.testIntegration.runtimeClasspath
+
+ binResultsDir = file("$buildDir/http-api/integration-test-results/binary/testIntegration")
+
+ reports {
+ html.destination = "$buildDir/http-api/reports/integration-test"
+ junitXml.destination = "$buildDir/http-api/integration-test-results"
+ }
+
+ systemProperties = [
+ CUBE_LOGGER_ENABLE: System.getenv('CUBE_LOGGER_ENABLE')
+ ]
+
+ testLogging.showStandardStreams = true
+ testLogging.exceptionFormat = 'full'
+
+ mustRunAfter tasks.test
+ }
+}
+
+
configure(project(':desktop')) {
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'witness'
@@ -291,6 +370,7 @@ configure(project(':desktop')) {
compile project(':p2p')
compile project(':core')
compile project(':common')
+ compile project(':http-api')
compile 'org.controlsfx:controlsfx:8.0.6_20'
compile 'org.reactfx:reactfx:2.0-M3'
compile 'net.glxn:qrgen:1.3'
diff --git a/core/src/main/java/bisq/core/app/AppOptionKeys.java b/core/src/main/java/bisq/core/app/AppOptionKeys.java
index 6c44f7d4f81..ead7aea8c18 100644
--- a/core/src/main/java/bisq/core/app/AppOptionKeys.java
+++ b/core/src/main/java/bisq/core/app/AppOptionKeys.java
@@ -29,4 +29,7 @@ public class AppOptionKeys {
public static final String IGNORE_DEV_MSG_KEY = "ignoreDevMsg";
public static final String USE_DEV_PRIVILEGE_KEYS = "useDevPrivilegeKeys";
public static final String REFERRAL_ID = "referralId";
+ public static final String HTTP_API_EXPERIMENTAL_FEATURES_ENABLED = "enableHttpApiExperimentalFeatures";
+ public static final String HTTP_API_HOST = "httpApiHost";
+ public static final String HTTP_API_PORT = "httpApiPort";
}
diff --git a/core/src/main/java/bisq/core/app/BisqEnvironment.java b/core/src/main/java/bisq/core/app/BisqEnvironment.java
index d40e3bcc232..59456278371 100644
--- a/core/src/main/java/bisq/core/app/BisqEnvironment.java
+++ b/core/src/main/java/bisq/core/app/BisqEnvironment.java
@@ -208,6 +208,13 @@ public static boolean isDaoActivated(Environment environment) {
protected final boolean externalTorUseSafeCookieAuthentication, torStreamIsolation;
+ @Getter
+ protected final String httpApiHost;
+ @Getter
+ protected final Integer httpApiPort;
+ @Getter
+ protected boolean httpApiExperimentalFeaturesEnabled;
+
public BisqEnvironment(OptionSet options) {
this(new JOptCommandLinePropertySource(BISQ_COMMANDLINE_PROPERTY_SOURCE_NAME, checkNotNull(
options)));
@@ -249,6 +256,13 @@ public BisqEnvironment(PropertySource commandLineProperties) {
referralId = commandLineProperties.containsProperty(AppOptionKeys.REFERRAL_ID) ?
(String) commandLineProperties.getProperty(AppOptionKeys.REFERRAL_ID) :
"";
+ httpApiExperimentalFeaturesEnabled = commandLineProperties.containsProperty(AppOptionKeys.HTTP_API_EXPERIMENTAL_FEATURES_ENABLED);
+ httpApiHost = commandLineProperties.containsProperty(AppOptionKeys.HTTP_API_HOST) ?
+ (String) commandLineProperties.getProperty(AppOptionKeys.HTTP_API_HOST) :
+ "127.0.0.1";
+ httpApiPort = Integer.parseInt(commandLineProperties.containsProperty(AppOptionKeys.HTTP_API_PORT) ?
+ (String) commandLineProperties.getProperty(AppOptionKeys.HTTP_API_PORT) :
+ "8080");
useDevMode = commandLineProperties.containsProperty(CommonOptionKeys.USE_DEV_MODE) ?
(String) commandLineProperties.getProperty(CommonOptionKeys.USE_DEV_MODE) :
"";
diff --git a/core/src/main/java/bisq/core/app/BisqExecutable.java b/core/src/main/java/bisq/core/app/BisqExecutable.java
index 91b6b1e7307..9ccaf0b7ae6 100644
--- a/core/src/main/java/bisq/core/app/BisqExecutable.java
+++ b/core/src/main/java/bisq/core/app/BisqExecutable.java
@@ -458,6 +458,15 @@ protected void customizeOptionParsing(OptionParser parser) {
"Optional Referral ID (e.g. for API users or pro market makers)")
.withRequiredArg();
+ parser.accepts(AppOptionKeys.HTTP_API_EXPERIMENTAL_FEATURES_ENABLED, "Enable experimental features of HTTP API (disabled by default)");
+ parser.accepts(AppOptionKeys.HTTP_API_HOST, "Optional HTTP API host")
+ .withRequiredArg()
+ .defaultsTo("127.0.0.1");
+ parser.accepts(AppOptionKeys.HTTP_API_PORT, "Optional HTTP API port")
+ .withRequiredArg()
+ .ofType(int.class)
+ .defaultsTo(8080);
+
parser.accepts(CommonOptionKeys.USE_DEV_MODE,
format("Enables dev mode which is used for convenience for developer testing (default: %s)", "false"))
.withRequiredArg()
diff --git a/desktop/src/main/java/bisq/desktop/app/BisqAppMain.java b/desktop/src/main/java/bisq/desktop/app/BisqAppMain.java
index a2494dfbdb1..fc34fbe8a7d 100644
--- a/desktop/src/main/java/bisq/desktop/app/BisqAppMain.java
+++ b/desktop/src/main/java/bisq/desktop/app/BisqAppMain.java
@@ -36,6 +36,10 @@
import lombok.extern.slf4j.Slf4j;
+
+
+import bisq.httpapi.service.HttpApiServer;
+
@Slf4j
public class BisqAppMain extends BisqExecutable {
private BisqApp application;
@@ -44,8 +48,6 @@ public BisqAppMain() {
super("Bisq Desktop", "bisq-desktop", Version.VERSION);
}
- /* @Nullable
- private BisqHttpApiServer bisqHttpApiServer;*/
/* @Nullable
private BisqGrpcServer bisqGrpcServer;
*/
@@ -64,7 +66,6 @@ public void onSetupComplete() {
log.debug("onSetupComplete");
}
-
///////////////////////////////////////////////////////////////////////////////////////////
// First synchronous execution tasks
///////////////////////////////////////////////////////////////////////////////////////////
@@ -135,9 +136,9 @@ protected void startApplication() {
protected void onApplicationStarted() {
super.onApplicationStarted();
- /* if (runWithHttpApi()) {
- bisqHttpApiServer = new BisqHttpApiServer();
- }*/
+ if (runWithHttpApi()) {
+ injector.getInstance(HttpApiServer.class).startServer();
+ }
/*
if (runWithGrpcApi()) {
bisqGrpcServer = new BisqGrpcServer();
diff --git a/gradle/witness/gradle-witness.gradle b/gradle/witness/gradle-witness.gradle
index 75c8d891cc8..eec31615612 100644
--- a/gradle/witness/gradle-witness.gradle
+++ b/gradle/witness/gradle-witness.gradle
@@ -29,9 +29,18 @@ dependencyVerification {
'org.fxmisc.easybind:easybind:666af296dda6de68751668a62661571b5238ac6f1c07c8a204fc6f902b222aaf',
'network.bisq.btcd-cli4j:btcd-cli4j-daemon:c007116da1b0145ddee64bb3a54fef60d58ce5c3dcf27773f39471117be8f132',
'network.bisq.btcd-cli4j:btcd-cli4j-core:b1d0525f3629bad358ad4a40ea3be998220110331d4b9d24e76d7894e563a595',
- 'com.fasterxml.jackson.core:jackson-databind:fcf3c2b0c332f5f54604f7e27fa7ee502378a2cc5df6a944bbfae391872c32ff',
- 'com.fasterxml.jackson.core:jackson-core:39a74610521d7fb9eb3f437bb8739bbf47f6435be12d17bf954c731a0c6352bb',
- 'com.fasterxml.jackson.core:jackson-annotations:2566b3a6662afa3c6af4f5b25006cb46be2efc68f1b5116291d6998a8cdf7ed3',
+ 'org.glassfish.jersey.media:jersey-media-json-jackson:815a783428d87e3f74591c6a9e4fd9c4bf37f5492e4c574b0a3e26a731dabc86',
+ 'io.swagger.core.v3:swagger-jaxrs2:f4de63695032f11df9664e92ca05284a5c2f484cf02cd53222513fd2ab4c8d32',
+ 'io.swagger.core.v3:swagger-integration:470dd943148b0ce90747af0583fb1a9c6db5979f845970353995c634bb124172',
+ 'io.swagger.core.v3:swagger-core:ef8bbaa4bc5643e17dafaaab137c43fb55c47e34287c909546f30f44ed332be0',
+ 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:26af65ee8a17c6751d51f90e241dd3974df0ba85bc6ba48709e58b509c3219e6',
+ 'com.fasterxml.jackson.module:jackson-module-jaxb-annotations:eed08585b2a9b6d64f8dba5ab813813dde1a8df5e7f7e744a3a70d83925bcfc2',
+ 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:d81b4b71778bdca92f4c8b66db08d3e1e3b3fa5b0e4fe349d2f8b59a310cbdd2',
+ 'com.fasterxml.jackson.core:jackson-databind:0fb4e079c118e752cc94c15ad22e6782b0dfc5dc09145f4813fb39d82e686047',
+ 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:adc1c495e9c7286bfa1d861ca07e06c8d0980057ad981b48b04f68eb8dcade2c',
+ 'com.fasterxml.jackson.core:jackson-core:a2bebaa325ad25455b02149c67e6052367a7d7fc1ce77de000eed284a5214eac',
+ 'io.swagger.core.v3:swagger-models:01453452b0715f6ddd5ff52f82b7a2646d0753360f600fd14bb734853c3765a2',
+ 'com.fasterxml.jackson.core:jackson-annotations:38a0e450049f643570adac99888aa3480ec2de385790a7096908bf43bfc085d6',
'com.google.protobuf:protobuf-java:b5e2d91812d183c9f053ffeebcbcda034d4de6679521940a19064714966c2cd4',
'com.google.code.gson:gson:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
'com.googlecode.json-simple:json-simple:4e69696892b88b41c55d49ab2fdcc21eead92bf54acc588c0050596c3b75199c',
@@ -39,9 +48,10 @@ dependencyVerification {
'ch.qos.logback:logback-classic:e66efc674e94837344bc5b748ff510c37a44eeff86cbfdbf9e714ef2eb374013',
'network.bisq.libdohj:libdohj-core:b89d2a6ad6a5aff1fccf2d4e5f7cc8c31991746e61913bcec3e999c2b0d7c954',
'com.github.bisq-network.bitcoinj:bitcoinj-core:d148d9577cf96540f7f5367011f7626ff9c9f148f0bf903b541740d480652969',
- 'org.slf4j:slf4j-api:3a4cd4969015f3beb4b5b4d81dbafc01765fb60b8a439955ca64d8476fef553e',
+ 'org.slf4j:slf4j-api:18c4a0095d5c1da6b817592e767bb23d29dd2f560ad74df75ff3961dbde25b79',
'ch.qos.logback:logback-core:4cd46fa17d77057b39160058df2f21ebbc2aded51d0edcc25d2c1cecc042a005',
'com.google.code.findbugs:jsr305:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
+ 'org.reflections:reflections:cca88428f8a8919df885105833d45ff07bd26f985f96ee55690551216b58b4a1',
'com.google.guava:guava:36a666e3b71ae7f0f0dca23654b67e086e6c93d192f60ba5dfd5519db6c288c8',
'com.google.inject:guice:9b9df27a5b8c7864112b4137fd92b36c3f1395bfe57be42fedf2f520ead1a93e',
'com.github.JesusMcCloud.netlayer:tor:75ca62a08621ea532b42ae6b014d9604a856ed572ffc8d2c15c281df817702ba',
@@ -52,8 +62,22 @@ dependencyVerification {
'org.jetbrains:annotations:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.bouncycastle:bcpg-jdk15on:de3355b821fc81dd32e1f3f560d5b3eca1c678fd2400011d0bfc69fb91bcde85',
'commons-io:commons-io:cc6a41dc3eaacc9e440a6bd0d2890b20d36b4ee408fe2d67122f328bb6e01581',
- 'org.apache.commons:commons-lang3:734c8356420cc8e30c795d64fd1fcd5d44ea9d90342a2cc3262c5158fbc6d98b',
+ 'org.apache.commons:commons-lang3:6e8dc31e046508d9953c96534edf0c2e0bfe6f468966b5b842b3f87e43b6a847',
'org.bouncycastle:bcprov-jdk15on:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
+ 'org.eclipse.jetty:jetty-servlet:fbcd7cc44b91a7f318930b237ad4fdeae79fe84ebeee6007baef01724a39e735',
+ 'javax.activation:activation:ae475120e9fcd99b4b00b38329bd61cdc5eb754eee03fe66c01f50e137724f99',
+ 'org.glassfish.jersey.containers:jersey-container-servlet:40349db8dabf6327a01ad59eaff172bd9a5f8927b2411bcdc59ceb05ce7731c1',
+ 'org.glassfish.jersey.ext:jersey-bean-validation:9dc23bd60a6ff1b8ce3f436b1dec959f82a1a643b7a981f4462700aae432c16d',
+ 'org.glassfish.jersey.containers:jersey-container-servlet-core:39e9fee46f5c6b5d4e49dc03f54741671bd4261090c5f7b5c72541a232873946',
+ 'org.glassfish.jersey.inject:jersey-hk2:634a2790f08c2f33feb78586b22a23005a2f8aa483c316ae2435729be0943968',
+ 'org.glassfish.jersey.media:jersey-media-multipart:08b303988e99546364283c63da5aa2d79c7c823f7b0d1ca5deabe66fbbb6374e',
+ 'org.glassfish.jersey.core:jersey-server:45a2e1e87566cb9808953d1f5ce0b4d99ede51be4a0f22ed92a7ceda7ba9417e',
+ 'org.glassfish.jersey.core:jersey-client:aba407bda94df54f590041b4cde5f2fa31db45bd8b4cf7575af48c1f8f81bb04',
+ 'org.glassfish.jersey.media:jersey-media-jaxb:b295e0d7ca93dbb084abd22a01ae7f54d5ffa244dd4b3ce1a6792eda148e76b2',
+ 'org.glassfish.jersey.core:jersey-common:9a9578c6dac52b96195a614150f696d455db6b6d267a645c3120a4d0ee495789',
+ 'org.glassfish.jersey.ext:jersey-entity-filtering:529b7ee7830441cffe98851b1e6edc0edd30e8b066052999daa5de63c56302b2',
+ 'javax.ws.rs:javax.ws.rs-api:1a4295889416c6972addcd425dfeeee6e6ede110e8b2dc8b49044e9b400ad5db',
+ 'org.webjars:swagger-ui:d6aa5d51493c016e95559452a911ffef739170edc063ff3a3e15ba76d0a40fa5',
'com.google.zxing:javase:0ec23e2ec12664ddd6347c8920ad647bb3b9da290f897a88516014b56cc77eb9',
'com.nativelibs4java:bridj:101bcd9b6637e6bc16e56deb3daefba62b1f5e8e9e37e1b3e56e3b5860d659cf',
'com.github.JesusMcCloud.tor-binary:tor-binary-macos:d143904dee93952576b12afb3c255ffce1b4eb0f8c85b0078c753b5f57fa1d07',
@@ -64,19 +88,43 @@ dependencyVerification {
'org.apache.httpcomponents:httpcore:d7f853dee87680b07293d30855b39b9eb56c1297bd16ff1cd6f19ddb8fa745fb',
'commons-codec:commons-codec:ad19d2601c3abf0b946b5c3a4113e226a8c1e3305e395b90013b78dd94a723ce',
'commons-logging:commons-logging:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
+ 'org.glassfish.hk2:hk2-locator:2a3766079d1cd21e715e4fd75e8189ebd58f9bf852885f1679253f0a27039b72',
+ 'org.glassfish.hk2:hk2-api:4d328e5b1cb5e8dcf3f97e1348d960f439e597009aa9d994dd5325bcef367908',
+ 'org.glassfish.hk2:hk2-utils:5edb176086ad0be1d4abbc0a1d26d519d088a01ee24f9ee064c657895a86e3ee',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'aopalliance:aopalliance:0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08',
'com.lambdaworks:scrypt:9a82d218099fb14c10c0e86e7eefeebd8c104de920acdc47b8b4b7a686fb73b4',
+ 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
+ 'net.jcip:jcip-annotations:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
+ 'org.bitcoinj:orchid:f836325cfa0466a011cb755c9b0fee6368487a2352eb45f4306ad9e4c18de080',
+ 'com.squareup.okhttp:okhttp:b4c943138fcef2bcc9d2006b2250c4aabbedeafc5947ed7c0af7fd103ceb2707',
+ 'org.eclipse.jetty:jetty-security:c4102cdbcbf6becec08b9ab4afbd9979c3f120e8cf45fbdf6be6c3940fe55bf1',
+ 'org.jvnet.mimepull:mimepull:2d1ee56aa89837ba9ea55431542e7939fa9d425552c2e6c8ddfb3b77877721b7',
+ 'org.glassfish.hk2.external:javax.inject:3bcf096beb918c9586be829190903090a21ac40513c1401e1b986e6030addc98',
+ 'org.hibernate:hibernate-validator:7f9300345436349396944fc9347437d862f999abd563ebd212291a44ff66e41b',
+ 'javax.validation:validation-api:f39d7ba7253e35f5ac48081ec1bc28c5df9b32ac4b7db20853e5a8e76bf7b0ed',
+ 'org.glassfish.web:javax.el:787e7e247da8008c699bafd8e086ccae13e6f3cac3c07ca1c698e44f917b42de',
+ 'javax.el:javax.el-api:5fd94735743ed06252c83158a24c290fcbf94b3f599b1bcec3bdc8c80979bed7',
+ 'org.javassist:javassist:59531c00f3e3aa1ff48b3a8cf4ead47d203ab0e2fd9e0ad401f764e05947e252',
+ 'io.swagger.core.v3:swagger-annotations:36ee5908faa140104b4c19f9273b4813f70f7d8486074119a7b83360fd4a4efb',
'com.google.zxing:core:11aae8fd974ab25faa8208be50468eb12349cd239e93e7c797377fa13e381729',
'com.github.JesusMcCloud.tor-binary:tor-binary-geoip:7340d4a0007b822b2f149e7360cd22443a5976676754bfaad0b8c48858475d5f',
'com.github.JesusMcCloud:jtorctl:b8be77613eeba899abff797c3cb9159b96361b2f880a3ebcc2280c027b0758e3',
'org.apache.commons:commons-compress:5f2df1e467825e4cac5996d44890c4201c000b43c0b23cffc0782d28a0beb9b0',
'org.tukaani:xz:a594643d73cc01928cf6ca5ce100e094ea9d73af760a5d4fb6b75fa673ecec96',
- 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
- 'net.jcip:jcip-annotations:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
- 'org.bitcoinj:orchid:f836325cfa0466a011cb755c9b0fee6368487a2352eb45f4306ad9e4c18de080',
- 'com.squareup.okhttp:okhttp:b4c943138fcef2bcc9d2006b2250c4aabbedeafc5947ed7c0af7fd103ceb2707',
- 'org.jetbrains.kotlin:kotlin-stdlib-common:4b161ef619eee0d1a49b1c4f0c4a8e46f4e342573efd8e0106a765f47475fe39',
'com.squareup.okio:okio:114bdc1f47338a68bcbc95abf2f5cdc72beeec91812f2fcd7b521c1937876266',
+ 'org.eclipse.jetty:jetty-server:a922f870f891f6ff4e3503b4e32ac80efb999e9d373ba1f397d055e1f34c8c4a',
+ 'javax.annotation:javax.annotation-api:5909b396ca3a2be10d0eea32c74ef78d816e1b4ead21de1d78de1f890d033e04',
+ 'org.glassfish.hk2:osgi-resource-locator:775003be577e8806f51b6e442be1033d83be2cb2207227b349be0bf16e6c0843',
+ 'org.glassfish.hk2.external:aopalliance-repackaged:669869a9d7e98fcea34580de250db54531550487d03571f26b9592e712897423',
+ 'org.jboss.logging:jboss-logging:6813931fe607469989f76a73a22515d2489dcd8b6be9fc147093a9cec995f822',
+ 'com.fasterxml:classmate:1a381660e2f27912e2c421a70bf816a1739e0475190a8efefbcdd00d89216887',
+ 'org.jetbrains.kotlin:kotlin-stdlib-common:4b161ef619eee0d1a49b1c4f0c4a8e46f4e342573efd8e0106a765f47475fe39',
+ 'javax.servlet:javax.servlet-api:af456b2dd41c4e82cf54f3e743bc678973d9fe35bd4d3071fa05c7e5333b8482',
+ 'org.eclipse.jetty:jetty-http:964795275e9ea340e302845630dd441d0c4977d99c990f28537d6e834260d64f',
+ 'org.eclipse.jetty:jetty-io:3710e8c88f99c8047ad38e4163715c1e63026f3fa586fa7727cf81b54dc420d5',
+ 'javax.xml.bind:jaxb-api:883007989d373d19f352ba9792b25dec21dc7d0e205a710a93a3815101bb3d03',
+ 'org.eclipse.jetty:jetty-util:02469929c448d4a3197dc69c5a6b9296bd37d12bcafd2b576ec8fe47ee42ef8f',
+ 'org.yaml:snakeyaml:81bf4c29d0275dace75fadb5febf5384553422816256023efa83b2b15a9ced60',
]
}
diff --git a/http-api/.dockerignore b/http-api/.dockerignore
new file mode 100644
index 00000000000..686ea619974
--- /dev/null
+++ b/http-api/.dockerignore
@@ -0,0 +1,17 @@
+.git
+.gitignore
+.dockerignore
+docker-compose.yml
+docker-compose-base.yml
+Dockerfile
+docker/dev/Dockerfile
+docker/prod/Dockerfile
+
+.idea
+*.iml
+
+target
+support
+
+build
+out
diff --git a/http-api/docker-compose-base.yml b/http-api/docker-compose-base.yml
new file mode 100644
index 00000000000..07ef4d5e12d
--- /dev/null
+++ b/http-api/docker-compose-base.yml
@@ -0,0 +1,34 @@
+version: '2.1'
+
+services:
+ api:
+ build:
+ context: ..
+ dockerfile: http-api/docker/dev/Dockerfile
+ image: bisq/http-api
+ environment:
+ - LOG_LEVEL=debug
+ - USE_LOCALHOST_FOR_P2P=true
+ - USE_DEV_PRIVILEGE_KEYS=true
+ - SEED_NODES=seed:8000
+ - BTC_NODES=bitcoin:18444
+ - BASE_CURRENCY_NETWORK=BTC_REGTEST
+ - BITCOIN_REGTEST_HOST=NONE
+ - HTTP_API_HOST=0.0.0.0
+ - ENABLE_HTTP_API_EXPERIMENTAL_FEATURES=true
+ seed:
+ image: bisq/seednode
+ environment:
+ - MY_ADDRESS=seed:8000
+ - SEED_NODES=seed:8000
+ - BTC_NODES=bitcoin:18444
+ - USE_LOCALHOST_FOR_P2P=true
+ - BASE_CURRENCY_NETWORK=BTC_REGTEST
+ - BITCOIN_REGTEST_HOST=NONE
+ bitcoin:
+ image: kylemanna/bitcoind:latest
+ command: -logips -rpcallowip=::/0 -regtest -printtoconsole
+ environment:
+ - DISABLEWALLET=0
+ - RPCUSER=user
+ - RPCPASSWORD=password
diff --git a/http-api/docker-compose.yml b/http-api/docker-compose.yml
new file mode 100644
index 00000000000..2305ff48f75
--- /dev/null
+++ b/http-api/docker-compose.yml
@@ -0,0 +1,51 @@
+version: '2.1'
+
+services:
+ alice:
+ extends:
+ file: docker-compose-base.yml
+ service: api
+ ports:
+ - 8080:8080
+ environment:
+ - NODE_PORT=8003
+ links:
+ - seed
+ - bitcoin
+ bob:
+ extends:
+ file: docker-compose-base.yml
+ service: api
+ ports:
+ - 8081:8080
+ environment:
+ - NODE_PORT=8004
+ links:
+ - seed
+ - bitcoin
+ arbitrator:
+ extends:
+ file: docker-compose-base.yml
+ service: api
+ ports:
+ - 8082:8080
+ environment:
+ - NODE_PORT=8005
+ links:
+ - seed
+ - bitcoin
+ seed:
+ extends:
+ file: docker-compose-base.yml
+ service: seed
+ ports:
+ - 8000:8000
+ links:
+ - bitcoin
+ bitcoin:
+ extends:
+ file: docker-compose-base.yml
+ service: bitcoin
+ ports:
+# If it is default regtest port (18444) then bisq ignores btcNodes param and uses localhost
+ - 18445:18444
diff --git a/http-api/docker/dev/Dockerfile b/http-api/docker/dev/Dockerfile
new file mode 100644
index 00000000000..26994090ab0
--- /dev/null
+++ b/http-api/docker/dev/Dockerfile
@@ -0,0 +1,29 @@
+FROM openjdk:10-jdk
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ openjfx && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /bisq/http-api
+
+#ENV HTTP_API_HOST=
+#ENV HTTP_API_PORT=
+ENV LANG=en_US
+
+CMD ./docker/startApi.sh
+
+#Fetch gradle and dependencies
+COPY gradle /bisq/gradle/
+COPY gradlew build.gradle gradle.properties settings.gradle /bisq/
+RUN ../gradlew --no-daemon -v
+
+COPY assets /bisq/assets/
+COPY common /bisq/common/
+COPY core /bisq/core/
+COPY p2p /bisq/p2p/
+COPY pricenode /bisq/pricenode/
+RUN ../gradlew --no-daemon build -x test
+
+COPY http-api /bisq/http-api
+
+#Compile sources to speed up startup
+RUN ../gradlew --no-daemon --offline compileJava -x test
diff --git a/http-api/docker/startApi.sh b/http-api/docker/startApi.sh
new file mode 100755
index 00000000000..969e436f117
--- /dev/null
+++ b/http-api/docker/startApi.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+IP=`ip -4 -o addr show eth0 | sed 's/.*inet \([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/'`
+ARGS="--myAddress $IP:${NODE_PORT:-9999}"
+if [ ! -z "$APP_NAME" ]; then
+ ARGS="$ARGS --appName=$APP_NAME"
+fi
+if [ ! -z "$NODE_PORT" ]; then
+ ARGS="$ARGS --nodePort=$NODE_PORT"
+fi
+if [ ! -z "$USE_LOCALHOST_FOR_P2P" ]; then
+ ARGS="$ARGS --useLocalhostForP2P=$USE_LOCALHOST_FOR_P2P"
+fi
+if [ ! -z "$SEED_NODES" ]; then
+ ARGS="$ARGS --seedNodes=$SEED_NODES"
+fi
+if [ ! -z "$BTC_NODES" ]; then
+ ARGS="$ARGS --btcNodes=$BTC_NODES"
+fi
+if [ ! -z "$BITCOIN_REGTEST_HOST" ]; then
+ ARGS="$ARGS --bitcoinRegtestHost=$BITCOIN_REGTEST_HOST"
+fi
+if [ ! -z "$BASE_CURRENCY_NETWORK" ]; then
+ ARGS="$ARGS --baseCurrencyNetwork=$BASE_CURRENCY_NETWORK"
+fi
+if [ ! -z "$LOG_LEVEL" ]; then
+ ARGS="$ARGS --logLevel=$LOG_LEVEL"
+fi
+if [ ! -z "$USE_DEV_PRIVILEGE_KEYS" ]; then
+ ARGS="$ARGS --useDevPrivilegeKeys=$USE_DEV_PRIVILEGE_KEYS"
+fi
+if [ "$ENABLE_HTTP_API_EXPERIMENTAL_FEATURES" == "true" ]; then
+ ARGS="$ARGS --enableHttpApiExperimentalFeatures"
+fi
+if [ ! -z "$HTTP_API_PORT" ]; then
+ ARGS="$ARGS --httpApiPort=$HTTP_API_PORT"
+fi
+if [ ! -z "$HTTP_API_HOST" ]; then
+ ARGS="$ARGS --httpApiHost=$HTTP_API_HOST"
+fi
+
+echo ../gradlew run --no-daemon --args "foo $ARGS"
+../gradlew run --no-daemon --args "foo $ARGS"
diff --git a/http-api/src/main/java/bisq/httpapi/HttpApiModule.java b/http-api/src/main/java/bisq/httpapi/HttpApiModule.java
new file mode 100644
index 00000000000..a8f591059e1
--- /dev/null
+++ b/http-api/src/main/java/bisq/httpapi/HttpApiModule.java
@@ -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