mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Merge pull request #3888 from cbeams/grpc-poc
Introduce gRPC API proof of concept
This commit is contained in:
commit
92466f96eb
@ -33,7 +33,7 @@
|
||||
<emptyLine />
|
||||
<package name="bisq.asset" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="io.bisq.generated" withSubpackages="true" static="false" />
|
||||
<package name="io.grpc" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="com.google.protobuf" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
|
76
build.gradle
76
build.gradle
@ -38,6 +38,7 @@ configure(subprojects) {
|
||||
fontawesomefxVersion = '8.0.0'
|
||||
fontawesomefxCommonsVersion = '9.1.2'
|
||||
fontawesomefxMaterialdesignfontVersion = '2.0.26-9.1.2'
|
||||
grpcVersion = '1.25.0'
|
||||
guavaVersion = '20.0'
|
||||
guiceVersion = '4.2.2'
|
||||
hamcrestVersion = '1.3'
|
||||
@ -59,7 +60,8 @@ configure(subprojects) {
|
||||
lombokVersion = '1.18.2'
|
||||
mockitoVersion = '3.0.0'
|
||||
netlayerVersion = '0.6.5.2'
|
||||
protobufVersion = '3.9.1'
|
||||
protobufVersion = '3.10.0'
|
||||
protocVersion = protobufVersion
|
||||
pushyVersion = '0.13.2'
|
||||
qrgenVersion = '1.3'
|
||||
sarxosVersion = '0.3.12'
|
||||
@ -86,7 +88,9 @@ configure(subprojects) {
|
||||
}
|
||||
|
||||
|
||||
configure([project(':desktop'),
|
||||
configure([project(':cli'),
|
||||
project(':daemon'),
|
||||
project(':desktop'),
|
||||
project(':monitor'),
|
||||
project(':relay'),
|
||||
project(':seednode'),
|
||||
@ -166,7 +170,7 @@ configure(project(':common')) {
|
||||
|
||||
protobuf {
|
||||
protoc {
|
||||
artifact = "com.google.protobuf:protoc:$protobufVersion"
|
||||
artifact = "com.google.protobuf:protoc:$protocVersion"
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,7 +179,7 @@ configure(project(':common')) {
|
||||
compile "org.openjfx:javafx-base:$javafxVersion:$os"
|
||||
compile "org.openjfx:javafx-graphics:$javafxVersion:$os"
|
||||
compile "com.google.protobuf:protobuf-java:$protobufVersion"
|
||||
compile 'com.google.code.gson:gson:2.7'
|
||||
compile 'com.google.code.gson:gson:2.8.5'
|
||||
compile "org.springframework:spring-core:$springVersion"
|
||||
compile "org.slf4j:slf4j-api:$slf4jVersion"
|
||||
compile "ch.qos.logback:logback-core:$logbackVersion"
|
||||
@ -225,6 +229,8 @@ configure(project(':p2p')) {
|
||||
|
||||
|
||||
configure(project(':core')) {
|
||||
apply plugin: 'com.google.protobuf'
|
||||
|
||||
dependencies {
|
||||
compile project(':assets')
|
||||
compile project(':p2p')
|
||||
@ -250,7 +256,20 @@ configure(project(':core')) {
|
||||
compile("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion") {
|
||||
exclude(module: 'jackson-annotations')
|
||||
}
|
||||
|
||||
implementation "com.google.protobuf:protobuf-java:$protobufVersion"
|
||||
implementation("io.grpc:grpc-protobuf:$grpcVersion") {
|
||||
exclude(module: 'guava')
|
||||
exclude(module: 'animal-sniffer-annotations')
|
||||
}
|
||||
implementation("io.grpc:grpc-stub:$grpcVersion") {
|
||||
exclude(module: 'guava')
|
||||
exclude(module: 'animal-sniffer-annotations')
|
||||
}
|
||||
compileOnly "javax.annotation:javax.annotation-api:1.2"
|
||||
runtimeOnly ("io.grpc:grpc-netty-shaded:$grpcVersion") {
|
||||
exclude(module: 'guava')
|
||||
exclude(module: 'animal-sniffer-annotations')
|
||||
}
|
||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||
|
||||
@ -262,11 +281,47 @@ configure(project(':core')) {
|
||||
testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||
}
|
||||
|
||||
protobuf {
|
||||
protoc {
|
||||
artifact = "com.google.protobuf:protoc:${protocVersion}"
|
||||
}
|
||||
plugins {
|
||||
grpc {
|
||||
artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
|
||||
}
|
||||
}
|
||||
generateProtoTasks {
|
||||
all()*.plugins { grpc {} }
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets.main.java.srcDirs += [
|
||||
'build/generated/source/proto/main/grpc',
|
||||
'build/generated/source/proto/main/java'
|
||||
]
|
||||
|
||||
test {
|
||||
systemProperty 'jdk.attach.allowAttachSelf', true
|
||||
}
|
||||
}
|
||||
|
||||
configure(project(':cli')) {
|
||||
mainClassName = 'bisq.cli.app.BisqCliMain'
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
implementation("io.grpc:grpc-core:$grpcVersion") {
|
||||
exclude(module: 'guava')
|
||||
exclude(module: 'animal-sniffer-annotations')
|
||||
}
|
||||
implementation("io.grpc:grpc-stub:$grpcVersion") {
|
||||
exclude(module: 'guava')
|
||||
exclude(module: 'animal-sniffer-annotations')
|
||||
}
|
||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||
}
|
||||
}
|
||||
|
||||
configure(project(':desktop')) {
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
@ -402,3 +457,14 @@ configure(project(':statsnode')) {
|
||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||
}
|
||||
}
|
||||
|
||||
configure(project(':daemon')) {
|
||||
mainClassName = 'bisq.daemon.app.BisqDaemonMain'
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||
compileOnly "javax.annotation:javax.annotation-api:1.2"
|
||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||
}
|
||||
}
|
||||
|
296
cli/src/main/java/bisq/cli/app/BisqCliMain.java
Normal file
296
cli/src/main/java/bisq/cli/app/BisqCliMain.java
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq 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.
|
||||
*
|
||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.cli.app;
|
||||
|
||||
import bisq.core.grpc.GetBalanceGrpc;
|
||||
import bisq.core.grpc.GetBalanceRequest;
|
||||
import bisq.core.grpc.GetOffersGrpc;
|
||||
import bisq.core.grpc.GetOffersRequest;
|
||||
import bisq.core.grpc.GetPaymentAccountsGrpc;
|
||||
import bisq.core.grpc.GetPaymentAccountsRequest;
|
||||
import bisq.core.grpc.GetTradeStatisticsGrpc;
|
||||
import bisq.core.grpc.GetTradeStatisticsRequest;
|
||||
import bisq.core.grpc.GetVersionGrpc;
|
||||
import bisq.core.grpc.GetVersionRequest;
|
||||
import bisq.core.grpc.PlaceOfferGrpc;
|
||||
import bisq.core.grpc.PlaceOfferRequest;
|
||||
import bisq.core.grpc.StopServerGrpc;
|
||||
import bisq.core.grpc.StopServerRequest;
|
||||
import bisq.core.payment.PaymentAccount;
|
||||
import bisq.core.proto.network.CoreNetworkProtoResolver;
|
||||
import bisq.core.proto.persistable.CorePersistenceProtoResolver;
|
||||
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.grpc.StatusRuntimeException;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.lang.String.format;
|
||||
|
||||
/**
|
||||
* gRPC client.
|
||||
*
|
||||
* FIXME We get warning 'DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - direct buffer constructor: unavailable
|
||||
* java.lang.UnsupportedOperationException: Reflective setAccessible(true) disabled' which is
|
||||
* related to Java 10 changes. Requests are working but we should find out why we get that warning
|
||||
*/
|
||||
@Slf4j
|
||||
public class BisqCliMain {
|
||||
|
||||
private final ManagedChannel channel;
|
||||
private final GetVersionGrpc.GetVersionBlockingStub getVersionStub;
|
||||
private final GetBalanceGrpc.GetBalanceBlockingStub getBalanceStub;
|
||||
private final StopServerGrpc.StopServerBlockingStub stopServerStub;
|
||||
private final GetTradeStatisticsGrpc.GetTradeStatisticsBlockingStub getTradeStatisticsStub;
|
||||
private final GetOffersGrpc.GetOffersBlockingStub getOffersStub;
|
||||
private final GetPaymentAccountsGrpc.GetPaymentAccountsBlockingStub getPaymentAccountsStub;
|
||||
private final PlaceOfferGrpc.PlaceOfferBlockingStub placeOfferBlockingStub;
|
||||
private final CorePersistenceProtoResolver corePersistenceProtoResolver;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new BisqCliMain("localhost", 8888);
|
||||
}
|
||||
|
||||
private BisqCliMain(String host, int port) {
|
||||
this(ManagedChannelBuilder.forAddress(host, port)
|
||||
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
|
||||
// needing certificates.
|
||||
.usePlaintext(true).build());
|
||||
|
||||
// Simple input scanner
|
||||
// TODO use some more sophisticated input processing with validation....
|
||||
try (Scanner scanner = new Scanner(System.in);) {
|
||||
while (true) {
|
||||
long startTs = System.currentTimeMillis();
|
||||
|
||||
String[] tokens = scanner.nextLine().split(" ");
|
||||
if (tokens.length == 0) {
|
||||
return;
|
||||
}
|
||||
String command = tokens[0];
|
||||
List<String> params = new ArrayList<>();
|
||||
if (tokens.length > 1) {
|
||||
params.addAll(Arrays.asList(tokens));
|
||||
params.remove(0);
|
||||
}
|
||||
String result = "";
|
||||
|
||||
switch (command) {
|
||||
case "getVersion":
|
||||
result = getVersion();
|
||||
break;
|
||||
case "getBalance":
|
||||
result = Coin.valueOf(getBalance()).toFriendlyString();
|
||||
break;
|
||||
case "getTradeStatistics":
|
||||
List<bisq.core.trade.statistics.TradeStatistics2> tradeStatistics = getTradeStatistics().stream()
|
||||
.map(bisq.core.trade.statistics.TradeStatistics2::fromProto)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
result = tradeStatistics.toString();
|
||||
break;
|
||||
case "getOffers":
|
||||
List<bisq.core.offer.Offer> offers = getOffers().stream()
|
||||
.map(bisq.core.offer.Offer::fromProto)
|
||||
.collect(Collectors.toList());
|
||||
result = offers.toString();
|
||||
break;
|
||||
case "getPaymentAccounts":
|
||||
List<PaymentAccount> paymentAccounts = getPaymentAccounts().stream()
|
||||
.map(proto -> PaymentAccount.fromProto(proto, corePersistenceProtoResolver))
|
||||
.collect(Collectors.toList());
|
||||
result = paymentAccounts.toString();
|
||||
break;
|
||||
case "placeOffer":
|
||||
// test input: placeOffer CNY BUY 750000000 true -0.2251 1000000 500000 0.15 5a972121-c30a-4b0e-b519-b17b63795d16
|
||||
// payment accountId and currency need to be adopted
|
||||
|
||||
// We expect 9 params
|
||||
// TODO add basic input validation
|
||||
try {
|
||||
checkArgument(params.size() == 9);
|
||||
String currencyCode = params.get(0);
|
||||
String directionAsString = params.get(1);
|
||||
long priceAsLong = Long.parseLong(params.get(2));
|
||||
boolean useMarketBasedPrice = Boolean.parseBoolean(params.get(3));
|
||||
double marketPriceMargin = Double.parseDouble(params.get(4));
|
||||
long amountAsLong = Long.parseLong(params.get(5));
|
||||
long minAmountAsLong = Long.parseLong(params.get(6));
|
||||
double buyerSecurityDeposit = Double.parseDouble(params.get(7));
|
||||
String paymentAccountId = params.get(8);
|
||||
boolean success = placeOffer(currencyCode,
|
||||
directionAsString,
|
||||
priceAsLong,
|
||||
useMarketBasedPrice,
|
||||
marketPriceMargin,
|
||||
amountAsLong,
|
||||
minAmountAsLong,
|
||||
buyerSecurityDeposit,
|
||||
paymentAccountId);
|
||||
result = String.valueOf(success);
|
||||
break;
|
||||
} catch (Throwable t) {
|
||||
log.error(t.toString(), t);
|
||||
break;
|
||||
}
|
||||
case "stop":
|
||||
result = "Shut down client";
|
||||
try {
|
||||
shutdown();
|
||||
} catch (InterruptedException e) {
|
||||
log.error(e.toString(), e);
|
||||
}
|
||||
break;
|
||||
case "stopServer":
|
||||
stopServer();
|
||||
result = "Server stopped";
|
||||
break;
|
||||
default:
|
||||
result = format("Unknown command '%s'", command);
|
||||
}
|
||||
|
||||
// First response is rather slow (300 ms) but following responses are fast (3-5 ms).
|
||||
log.info("Request took: {} ms", System.currentTimeMillis() - startTs);
|
||||
log.info(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct client for accessing server using the existing channel.
|
||||
*/
|
||||
private BisqCliMain(ManagedChannel channel) {
|
||||
this.channel = channel;
|
||||
|
||||
getVersionStub = GetVersionGrpc.newBlockingStub(channel);
|
||||
getBalanceStub = GetBalanceGrpc.newBlockingStub(channel);
|
||||
getTradeStatisticsStub = GetTradeStatisticsGrpc.newBlockingStub(channel);
|
||||
getOffersStub = GetOffersGrpc.newBlockingStub(channel);
|
||||
getPaymentAccountsStub = GetPaymentAccountsGrpc.newBlockingStub(channel);
|
||||
placeOfferBlockingStub = PlaceOfferGrpc.newBlockingStub(channel);
|
||||
stopServerStub = StopServerGrpc.newBlockingStub(channel);
|
||||
|
||||
CoreNetworkProtoResolver coreNetworkProtoResolver = new CoreNetworkProtoResolver(Clock.systemDefaultZone());
|
||||
//TODO
|
||||
corePersistenceProtoResolver = new CorePersistenceProtoResolver(null, coreNetworkProtoResolver, null, null);
|
||||
}
|
||||
|
||||
private String getVersion() {
|
||||
GetVersionRequest request = GetVersionRequest.newBuilder().build();
|
||||
try {
|
||||
return getVersionStub.getVersion(request).getVersion();
|
||||
} catch (StatusRuntimeException e) {
|
||||
return "RPC failed: " + e.getStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private long getBalance() {
|
||||
GetBalanceRequest request = GetBalanceRequest.newBuilder().build();
|
||||
try {
|
||||
return getBalanceStub.getBalance(request).getBalance();
|
||||
} catch (StatusRuntimeException e) {
|
||||
log.warn("RPC failed: {}", e.getStatus());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private List<protobuf.TradeStatistics2> getTradeStatistics() {
|
||||
GetTradeStatisticsRequest request = GetTradeStatisticsRequest.newBuilder().build();
|
||||
try {
|
||||
return getTradeStatisticsStub.getTradeStatistics(request).getTradeStatisticsList();
|
||||
} catch (StatusRuntimeException e) {
|
||||
log.warn("RPC failed: {}", e.getStatus());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<protobuf.Offer> getOffers() {
|
||||
GetOffersRequest request = GetOffersRequest.newBuilder().build();
|
||||
try {
|
||||
return getOffersStub.getOffers(request).getOffersList();
|
||||
} catch (StatusRuntimeException e) {
|
||||
log.warn("RPC failed: {}", e.getStatus());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<protobuf.PaymentAccount> getPaymentAccounts() {
|
||||
GetPaymentAccountsRequest request = GetPaymentAccountsRequest.newBuilder().build();
|
||||
try {
|
||||
return getPaymentAccountsStub.getPaymentAccounts(request).getPaymentAccountsList();
|
||||
} catch (StatusRuntimeException e) {
|
||||
log.warn("RPC failed: {}", e.getStatus());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean placeOffer(String currencyCode,
|
||||
String directionAsString,
|
||||
long priceAsLong,
|
||||
boolean useMarketBasedPrice,
|
||||
double marketPriceMargin,
|
||||
long amountAsLong,
|
||||
long minAmountAsLong,
|
||||
double buyerSecurityDeposit,
|
||||
String paymentAccountId) {
|
||||
PlaceOfferRequest request = PlaceOfferRequest.newBuilder()
|
||||
.setCurrencyCode(currencyCode)
|
||||
.setDirection(directionAsString)
|
||||
.setPrice(priceAsLong)
|
||||
.setUseMarketBasedPrice(useMarketBasedPrice)
|
||||
.setMarketPriceMargin(marketPriceMargin)
|
||||
.setAmount(amountAsLong)
|
||||
.setMinAmount(minAmountAsLong)
|
||||
.setBuyerSecurityDeposit(buyerSecurityDeposit)
|
||||
.setPaymentAccountId(paymentAccountId)
|
||||
.build();
|
||||
try {
|
||||
return placeOfferBlockingStub.placeOffer(request).getResult();
|
||||
} catch (StatusRuntimeException e) {
|
||||
log.warn("RPC failed: {}", e.getStatus());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void stopServer() {
|
||||
StopServerRequest request = StopServerRequest.newBuilder().build();
|
||||
try {
|
||||
stopServerStub.stopServer(request);
|
||||
} catch (StatusRuntimeException e) {
|
||||
log.warn("RPC failed: {}", e.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
private void shutdown() throws InterruptedException {
|
||||
channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
@ -18,8 +18,6 @@
|
||||
package bisq.core.app;
|
||||
|
||||
public class AppOptionKeys {
|
||||
public static final String DESKTOP_WITH_HTTP_API = "desktopWithHttpApi";
|
||||
public static final String DESKTOP_WITH_GRPC_API = "desktopWithGrpcApi";
|
||||
public static final String APP_NAME_KEY = "appName";
|
||||
public static final String USER_DATA_DIR_KEY = "userDataDir";
|
||||
public static final String APP_DATA_DIR_KEY = "appDataDir";
|
||||
|
@ -186,8 +186,6 @@ public class BisqEnvironment extends StandardEnvironment {
|
||||
@Setter
|
||||
protected boolean isBitcoinLocalhostNodeRunning;
|
||||
@Getter
|
||||
protected String desktopWithHttpApi, desktopWithGrpcApi;
|
||||
@Getter
|
||||
protected List<String> bannedSeedNodes, bannedBtcNodes, bannedPriceRelayNodes;
|
||||
|
||||
protected final String btcNodes, seedNodes, ignoreDevMsg, useDevPrivilegeKeys, useDevMode, useTorForBtc, rpcUser, rpcPassword,
|
||||
@ -219,8 +217,6 @@ public class BisqEnvironment extends StandardEnvironment {
|
||||
appDataDir = getProperty(commandLineProperties, AppOptionKeys.APP_DATA_DIR_KEY, appDataDir(userDataDir, appName));
|
||||
staticAppDataDir = appDataDir;
|
||||
|
||||
desktopWithHttpApi = getProperty(commandLineProperties, AppOptionKeys.DESKTOP_WITH_HTTP_API, "false");
|
||||
desktopWithGrpcApi = getProperty(commandLineProperties, AppOptionKeys.DESKTOP_WITH_GRPC_API, "false");
|
||||
ignoreDevMsg = getProperty(commandLineProperties, AppOptionKeys.IGNORE_DEV_MSG_KEY, "");
|
||||
useDevPrivilegeKeys = getProperty(commandLineProperties, AppOptionKeys.USE_DEV_PRIVILEGE_KEYS, "");
|
||||
referralId = getProperty(commandLineProperties, AppOptionKeys.REFERRAL_ID, "");
|
||||
@ -398,8 +394,6 @@ public class BisqEnvironment extends StandardEnvironment {
|
||||
setProperty(NetworkOptionKeys.SEND_MSG_THROTTLE_SLEEP, sendMsgThrottleSleep);
|
||||
|
||||
setProperty(AppOptionKeys.APP_DATA_DIR_KEY, appDataDir);
|
||||
setProperty(AppOptionKeys.DESKTOP_WITH_HTTP_API, desktopWithHttpApi);
|
||||
setProperty(AppOptionKeys.DESKTOP_WITH_GRPC_API, desktopWithGrpcApi);
|
||||
setProperty(AppOptionKeys.IGNORE_DEV_MSG_KEY, ignoreDevMsg);
|
||||
setProperty(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS, useDevPrivilegeKeys);
|
||||
setProperty(AppOptionKeys.REFERRAL_ID, referralId);
|
||||
|
@ -446,16 +446,6 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
|
||||
.withRequiredArg()
|
||||
.ofType(boolean.class);
|
||||
|
||||
parser.accepts(AppOptionKeys.DESKTOP_WITH_HTTP_API,
|
||||
format("If set to true Bisq Desktop starts with Http API (default: %s)", "false"))
|
||||
.withRequiredArg()
|
||||
.ofType(boolean.class);
|
||||
|
||||
parser.accepts(AppOptionKeys.DESKTOP_WITH_GRPC_API,
|
||||
format("If set to true Bisq Desktop starts with gRPC API (default: %s)", "false"))
|
||||
.withRequiredArg()
|
||||
.ofType(boolean.class);
|
||||
|
||||
parser.accepts(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS,
|
||||
format("If that is true all the privileged features which requires a private key " +
|
||||
"to enable it are overridden by a dev key pair (This is for developers only!) (default: %s)", "false"))
|
||||
|
@ -17,8 +17,6 @@
|
||||
|
||||
package bisq.core.app;
|
||||
|
||||
import bisq.core.CoreModule;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.AppModule;
|
||||
import bisq.common.app.Version;
|
||||
|
@ -15,11 +15,9 @@
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.core;
|
||||
package bisq.core.app;
|
||||
|
||||
import bisq.core.alert.AlertModule;
|
||||
import bisq.core.app.AppOptionKeys;
|
||||
import bisq.core.app.BisqEnvironment;
|
||||
import bisq.core.btc.BitcoinModule;
|
||||
import bisq.core.dao.DaoModule;
|
||||
import bisq.core.filter.FilterModule;
|
203
core/src/main/java/bisq/core/grpc/BisqGrpcServer.java
Normal file
203
core/src/main/java/bisq/core/grpc/BisqGrpcServer.java
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq 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.
|
||||
*
|
||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.core.grpc;
|
||||
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.payment.PaymentAccount;
|
||||
import bisq.core.trade.handlers.TransactionResultHandler;
|
||||
import bisq.core.trade.statistics.TradeStatistics2;
|
||||
|
||||
import io.grpc.Server;
|
||||
import io.grpc.ServerBuilder;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
/**
|
||||
* gRPC server. Gets a instance of BisqFacade passed to access data from the running Bisq instance.
|
||||
*/
|
||||
@Slf4j
|
||||
public class BisqGrpcServer {
|
||||
|
||||
private Server server;
|
||||
|
||||
private static BisqGrpcServer instance;
|
||||
private static CoreApi coreApi;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Services
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static class GetVersionImpl extends GetVersionGrpc.GetVersionImplBase {
|
||||
@Override
|
||||
public void getVersion(GetVersionRequest req, StreamObserver<GetVersionReply> responseObserver) {
|
||||
GetVersionReply reply = GetVersionReply.newBuilder().setVersion(coreApi.getVersion()).build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
static class GetBalanceImpl extends GetBalanceGrpc.GetBalanceImplBase {
|
||||
@Override
|
||||
public void getBalance(GetBalanceRequest req, StreamObserver<GetBalanceReply> responseObserver) {
|
||||
GetBalanceReply reply = GetBalanceReply.newBuilder().setBalance(coreApi.getAvailableBalance()).build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
static class GetTradeStatisticsImpl extends GetTradeStatisticsGrpc.GetTradeStatisticsImplBase {
|
||||
@Override
|
||||
public void getTradeStatistics(GetTradeStatisticsRequest req,
|
||||
StreamObserver<GetTradeStatisticsReply> responseObserver) {
|
||||
List<protobuf.TradeStatistics2> tradeStatistics = coreApi.getTradeStatistics().stream()
|
||||
.map(TradeStatistics2::toProtoTradeStatistics2)
|
||||
.collect(Collectors.toList());
|
||||
GetTradeStatisticsReply reply = GetTradeStatisticsReply.newBuilder().addAllTradeStatistics(tradeStatistics).build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
static class GetOffersImpl extends GetOffersGrpc.GetOffersImplBase {
|
||||
@Override
|
||||
public void getOffers(GetOffersRequest req, StreamObserver<GetOffersReply> responseObserver) {
|
||||
|
||||
List<protobuf.Offer> tradeStatistics = coreApi.getOffers().stream()
|
||||
.map(Offer::toProtoMessage)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
GetOffersReply reply = GetOffersReply.newBuilder().addAllOffers(tradeStatistics).build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
static class GetPaymentAccountsImpl extends GetPaymentAccountsGrpc.GetPaymentAccountsImplBase {
|
||||
@Override
|
||||
public void getPaymentAccounts(GetPaymentAccountsRequest req,
|
||||
StreamObserver<GetPaymentAccountsReply> responseObserver) {
|
||||
|
||||
List<protobuf.PaymentAccount> tradeStatistics = coreApi.getPaymentAccounts().stream()
|
||||
.map(PaymentAccount::toProtoMessage)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
GetPaymentAccountsReply reply = GetPaymentAccountsReply.newBuilder().addAllPaymentAccounts(tradeStatistics).build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
static class PlaceOfferImpl extends PlaceOfferGrpc.PlaceOfferImplBase {
|
||||
@Override
|
||||
public void placeOffer(PlaceOfferRequest req, StreamObserver<PlaceOfferReply> responseObserver) {
|
||||
TransactionResultHandler resultHandler = transaction -> {
|
||||
PlaceOfferReply reply = PlaceOfferReply.newBuilder().setResult(true).build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
};
|
||||
coreApi.placeOffer(
|
||||
req.getCurrencyCode(),
|
||||
req.getDirection(),
|
||||
req.getPrice(),
|
||||
req.getUseMarketBasedPrice(),
|
||||
req.getMarketPriceMargin(),
|
||||
req.getAmount(),
|
||||
req.getMinAmount(),
|
||||
req.getBuyerSecurityDeposit(),
|
||||
req.getPaymentAccountId(),
|
||||
resultHandler);
|
||||
}
|
||||
}
|
||||
|
||||
static class StopServerImpl extends StopServerGrpc.StopServerImplBase {
|
||||
@Override
|
||||
public void stopServer(StopServerRequest req, StreamObserver<StopServerReply> responseObserver) {
|
||||
StopServerReply reply = StopServerReply.newBuilder().build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
|
||||
instance.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public BisqGrpcServer(CoreApi coreApi) {
|
||||
instance = this;
|
||||
|
||||
BisqGrpcServer.coreApi = coreApi;
|
||||
|
||||
try {
|
||||
start();
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error(e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void stop() {
|
||||
if (server != null) {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void start() throws IOException {
|
||||
// TODO add to options
|
||||
int port = 8888;
|
||||
|
||||
// Config services
|
||||
server = ServerBuilder.forPort(port)
|
||||
.addService(new GetVersionImpl())
|
||||
.addService(new GetBalanceImpl())
|
||||
.addService(new GetTradeStatisticsImpl())
|
||||
.addService(new GetOffersImpl())
|
||||
.addService(new GetPaymentAccountsImpl())
|
||||
.addService(new PlaceOfferImpl())
|
||||
.addService(new StopServerImpl())
|
||||
.build()
|
||||
.start();
|
||||
|
||||
log.info("Server started, listening on " + port);
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
|
||||
log.error("*** shutting down gRPC server since JVM is shutting down");
|
||||
BisqGrpcServer.this.stop();
|
||||
log.error("*** server shut down");
|
||||
}));
|
||||
}
|
||||
}
|
163
core/src/main/java/bisq/core/grpc/CoreApi.java
Normal file
163
core/src/main/java/bisq/core/grpc/CoreApi.java
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq 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.
|
||||
*
|
||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.core.grpc;
|
||||
|
||||
import bisq.core.btc.Balances;
|
||||
import bisq.core.monetary.Price;
|
||||
import bisq.core.offer.CreateOfferService;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferBookService;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
import bisq.core.offer.OpenOfferManager;
|
||||
import bisq.core.payment.PaymentAccount;
|
||||
import bisq.core.presentation.BalancePresentation;
|
||||
import bisq.core.trade.handlers.TransactionResultHandler;
|
||||
import bisq.core.trade.statistics.TradeStatistics2;
|
||||
import bisq.core.trade.statistics.TradeStatisticsManager;
|
||||
import bisq.core.user.User;
|
||||
|
||||
import bisq.common.app.Version;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Provides high level interface to functionality of core Bisq features.
|
||||
* E.g. useful for different APIs to access data of different domains of Bisq.
|
||||
*/
|
||||
@Slf4j
|
||||
public class CoreApi {
|
||||
private final Balances balances;
|
||||
private final BalancePresentation balancePresentation;
|
||||
private final OfferBookService offerBookService;
|
||||
private final TradeStatisticsManager tradeStatisticsManager;
|
||||
private final CreateOfferService createOfferService;
|
||||
private final OpenOfferManager openOfferManager;
|
||||
private final User user;
|
||||
|
||||
@Inject
|
||||
public CoreApi(Balances balances,
|
||||
BalancePresentation balancePresentation,
|
||||
OfferBookService offerBookService,
|
||||
TradeStatisticsManager tradeStatisticsManager,
|
||||
CreateOfferService createOfferService,
|
||||
OpenOfferManager openOfferManager,
|
||||
User user) {
|
||||
this.balances = balances;
|
||||
this.balancePresentation = balancePresentation;
|
||||
this.offerBookService = offerBookService;
|
||||
this.tradeStatisticsManager = tradeStatisticsManager;
|
||||
this.createOfferService = createOfferService;
|
||||
this.openOfferManager = openOfferManager;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return Version.VERSION;
|
||||
}
|
||||
|
||||
public long getAvailableBalance() {
|
||||
return balances.getAvailableBalance().get().getValue();
|
||||
}
|
||||
|
||||
public String getAvailableBalanceAsString() {
|
||||
return balancePresentation.getAvailableBalance().get();
|
||||
}
|
||||
|
||||
public List<TradeStatistics2> getTradeStatistics() {
|
||||
return new ArrayList<>(tradeStatisticsManager.getObservableTradeStatisticsSet());
|
||||
}
|
||||
|
||||
public List<Offer> getOffers() {
|
||||
return offerBookService.getOffers();
|
||||
}
|
||||
|
||||
public Set<PaymentAccount> getPaymentAccounts() {
|
||||
return user.getPaymentAccounts();
|
||||
}
|
||||
|
||||
public void placeOffer(String currencyCode,
|
||||
String directionAsString,
|
||||
long priceAsLong,
|
||||
boolean useMarketBasedPrice,
|
||||
double marketPriceMargin,
|
||||
long amountAsLong,
|
||||
long minAmountAsLong,
|
||||
double buyerSecurityDeposit,
|
||||
String paymentAccountId,
|
||||
TransactionResultHandler resultHandler) {
|
||||
String offerId = createOfferService.getRandomOfferId();
|
||||
OfferPayload.Direction direction = OfferPayload.Direction.valueOf(directionAsString);
|
||||
Price price = Price.valueOf(currencyCode, priceAsLong);
|
||||
Coin amount = Coin.valueOf(amountAsLong);
|
||||
Coin minAmount = Coin.valueOf(minAmountAsLong);
|
||||
PaymentAccount paymentAccount = user.getPaymentAccount(paymentAccountId);
|
||||
// We don't support atm funding from external wallet to keep it simple
|
||||
boolean useSavingsWallet = true;
|
||||
|
||||
placeOffer(offerId,
|
||||
currencyCode,
|
||||
direction,
|
||||
price,
|
||||
useMarketBasedPrice,
|
||||
marketPriceMargin,
|
||||
amount,
|
||||
minAmount,
|
||||
buyerSecurityDeposit,
|
||||
paymentAccount,
|
||||
useSavingsWallet,
|
||||
resultHandler);
|
||||
}
|
||||
|
||||
public void placeOffer(String offerId,
|
||||
String currencyCode,
|
||||
OfferPayload.Direction direction,
|
||||
Price price,
|
||||
boolean useMarketBasedPrice,
|
||||
double marketPriceMargin,
|
||||
Coin amount,
|
||||
Coin minAmount,
|
||||
double buyerSecurityDeposit,
|
||||
PaymentAccount paymentAccount,
|
||||
boolean useSavingsWallet,
|
||||
TransactionResultHandler resultHandler) {
|
||||
Offer offer = createOfferService.createAndGetOffer(offerId,
|
||||
direction,
|
||||
currencyCode,
|
||||
amount,
|
||||
minAmount,
|
||||
price,
|
||||
useMarketBasedPrice,
|
||||
marketPriceMargin,
|
||||
buyerSecurityDeposit,
|
||||
paymentAccount);
|
||||
|
||||
openOfferManager.placeOffer(offer,
|
||||
buyerSecurityDeposit,
|
||||
useSavingsWallet,
|
||||
resultHandler,
|
||||
log::error);
|
||||
}
|
||||
}
|
148
core/src/main/proto/grpc.proto
Normal file
148
core/src/main/proto/grpc.proto
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq 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.
|
||||
*
|
||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
package io.bisq.protobuffer;
|
||||
|
||||
// FIXME: IntelliJ does not recognize the import but the compiler does
|
||||
import "pb.proto";
|
||||
|
||||
option java_package = "bisq.core.grpc";
|
||||
option java_multiple_files = true;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Version
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
service GetVersion {
|
||||
rpc GetVersion (GetVersionRequest) returns (GetVersionReply) {
|
||||
}
|
||||
}
|
||||
|
||||
message GetVersionRequest {
|
||||
}
|
||||
|
||||
message GetVersionReply {
|
||||
string version = 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Balance
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
service GetBalance {
|
||||
rpc GetBalance (GetBalanceRequest) returns (GetBalanceReply) {
|
||||
}
|
||||
}
|
||||
|
||||
message GetBalanceRequest {
|
||||
}
|
||||
|
||||
message GetBalanceReply {
|
||||
uint64 balance = 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TradeStatistics
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
service GetTradeStatistics {
|
||||
rpc GetTradeStatistics (GetTradeStatisticsRequest) returns (GetTradeStatisticsReply) {
|
||||
}
|
||||
}
|
||||
|
||||
message GetTradeStatisticsRequest {
|
||||
}
|
||||
|
||||
// FIXME: IntelliJ does not recognize the imported TradeStatistics2 but the compiler does
|
||||
message GetTradeStatisticsReply {
|
||||
repeated TradeStatistics2 TradeStatistics = 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Offer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
service GetOffers {
|
||||
rpc GetOffers (GetOffersRequest) returns (GetOffersReply) {
|
||||
}
|
||||
}
|
||||
|
||||
message GetOffersRequest {
|
||||
}
|
||||
|
||||
// FIXME: IntelliJ does not recognize the imported Offer but the compiler does
|
||||
message GetOffersReply {
|
||||
repeated Offer offers = 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PaymentAccount
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
service GetPaymentAccounts {
|
||||
rpc GetPaymentAccounts (GetPaymentAccountsRequest) returns (GetPaymentAccountsReply) {
|
||||
}
|
||||
}
|
||||
|
||||
message GetPaymentAccountsRequest {
|
||||
}
|
||||
|
||||
// FIXME: IntelliJ does not recognize the imported PaymentAccount but the compiler does
|
||||
message GetPaymentAccountsReply {
|
||||
repeated PaymentAccount paymentAccounts = 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PlaceOffer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
service PlaceOffer {
|
||||
rpc PlaceOffer (PlaceOfferRequest) returns (PlaceOfferReply) {
|
||||
}
|
||||
}
|
||||
|
||||
message PlaceOfferRequest {
|
||||
string currencyCode = 1;
|
||||
string direction = 2;
|
||||
uint64 price = 3;
|
||||
bool useMarketBasedPrice = 4;
|
||||
double marketPriceMargin = 5;
|
||||
uint64 amount = 6;
|
||||
uint64 minAmount = 7;
|
||||
double buyerSecurityDeposit = 8;
|
||||
string paymentAccountId = 9;
|
||||
}
|
||||
|
||||
message PlaceOfferReply {
|
||||
bool result = 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// StopServer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
service StopServer {
|
||||
rpc StopServer (StopServerRequest) returns (StopServerReply) {
|
||||
}
|
||||
}
|
||||
|
||||
message StopServerRequest {
|
||||
}
|
||||
|
||||
message StopServerReply {
|
||||
}
|
23
daemon/src/main/java/bisq/daemon/app/BisqDaemon.java
Normal file
23
daemon/src/main/java/bisq/daemon/app/BisqDaemon.java
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq 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.
|
||||
*
|
||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.daemon.app;
|
||||
|
||||
import bisq.core.app.BisqHeadlessApp;
|
||||
|
||||
public class BisqDaemon extends BisqHeadlessApp {
|
||||
}
|
111
daemon/src/main/java/bisq/daemon/app/BisqDaemonMain.java
Normal file
111
daemon/src/main/java/bisq/daemon/app/BisqDaemonMain.java
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq 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.
|
||||
*
|
||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.daemon.app;
|
||||
|
||||
import bisq.core.app.BisqExecutable;
|
||||
import bisq.core.app.BisqHeadlessAppMain;
|
||||
import bisq.core.app.BisqSetup;
|
||||
import bisq.core.app.CoreModule;
|
||||
import bisq.core.grpc.BisqGrpcServer;
|
||||
import bisq.core.grpc.CoreApi;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.AppModule;
|
||||
import bisq.common.setup.CommonSetup;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class BisqDaemonMain extends BisqHeadlessAppMain implements BisqSetup.BisqSetupListener {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (BisqExecutable.setupInitialOptionParser(args)) {
|
||||
// For some reason the JavaFX launch process results in us losing the thread context class loader: reset it.
|
||||
// In order to work around a bug in JavaFX 8u25 and below, you must include the following code as the first line of your realMain method:
|
||||
Thread.currentThread().setContextClassLoader(BisqDaemonMain.class.getClassLoader());
|
||||
|
||||
new BisqDaemonMain().execute(args);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// First synchronous execution tasks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void configUserThread() {
|
||||
final ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||
.setNameFormat(this.getClass().getSimpleName())
|
||||
.setDaemon(true)
|
||||
.build();
|
||||
UserThread.setExecutor(Executors.newSingleThreadExecutor(threadFactory));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void launchApplication() {
|
||||
headlessApp = new BisqDaemon();
|
||||
CommonSetup.setup(BisqDaemonMain.this.headlessApp);
|
||||
|
||||
UserThread.execute(this::onApplicationLaunched);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onApplicationLaunched() {
|
||||
super.onApplicationLaunched();
|
||||
headlessApp.setGracefulShutDownHandler(this);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// We continue with a series of synchronous execution tasks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected AppModule getModule() {
|
||||
return new CoreModule(bisqEnvironment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyInjector() {
|
||||
super.applyInjector();
|
||||
|
||||
headlessApp.setInjector(injector);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startApplication() {
|
||||
// We need to be in user thread! We mapped at launchApplication already...
|
||||
headlessApp.startApplication();
|
||||
|
||||
// In headless mode we don't have an async behaviour so we trigger the setup by calling onApplicationStarted
|
||||
onApplicationStarted();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onApplicationStarted() {
|
||||
super.onApplicationStarted();
|
||||
|
||||
CoreApi coreApi = injector.getInstance(CoreApi.class);
|
||||
new BisqGrpcServer(coreApi);
|
||||
}
|
||||
}
|
16
daemon/src/main/java/resources/logback.xml
Normal file
16
daemon/src/main/java/resources/logback.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%highlight(%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{30}: %msg %xEx%n)</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="TRACE">
|
||||
<appender-ref ref="CONSOLE_APPENDER"/>
|
||||
</root>
|
||||
|
||||
<logger name="com.neemre.btcdcli4j" level="WARN"/>
|
||||
<logger name="io.grpc.netty" level="WARN"/>
|
||||
|
||||
</configuration>
|
@ -44,11 +44,6 @@ public class BisqAppMain extends BisqExecutable {
|
||||
super("Bisq Desktop", "bisq-desktop", Version.VERSION);
|
||||
}
|
||||
|
||||
/* @Nullable
|
||||
private BisqHttpApiServer bisqHttpApiServer;*/
|
||||
/* @Nullable
|
||||
private BisqGrpcServer bisqGrpcServer;
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (BisqExecutable.setupInitialOptionParser(args)) {
|
||||
// For some reason the JavaFX launch process results in us losing the thread context class loader: reset it.
|
||||
@ -135,20 +130,11 @@ public class BisqAppMain extends BisqExecutable {
|
||||
protected void onApplicationStarted() {
|
||||
super.onApplicationStarted();
|
||||
|
||||
/* if (runWithHttpApi()) {
|
||||
bisqHttpApiServer = new BisqHttpApiServer();
|
||||
}*/
|
||||
/*
|
||||
if (runWithGrpcApi()) {
|
||||
bisqGrpcServer = new BisqGrpcServer();
|
||||
}*/
|
||||
CoreApi coreApi = injector.getInstance(CoreApi.class);
|
||||
bisqGrpcServer = new BisqGrpcServer(coreApi);
|
||||
}
|
||||
|
||||
private boolean runWithHttpApi() {
|
||||
return bisqEnvironment.getDesktopWithHttpApi().toLowerCase().equals("true");
|
||||
}
|
||||
|
||||
private boolean runWithGrpcApi() {
|
||||
return bisqEnvironment.getDesktopWithGrpcApi().toLowerCase().equals("true");
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ package bisq.desktop.app;
|
||||
|
||||
import bisq.desktop.DesktopModule;
|
||||
|
||||
import bisq.core.CoreModule;
|
||||
import bisq.core.app.CoreModule;
|
||||
|
||||
import bisq.common.app.AppModule;
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
//
|
||||
// See https://github.com/signalapp/gradle-witness#using-witness for further details.
|
||||
|
||||
|
||||
dependencyVerification {
|
||||
verify = [
|
||||
'aopalliance:aopalliance:0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08',
|
||||
@ -32,11 +31,14 @@ dependencyVerification {
|
||||
'com.github.bisq-network.bitcoinj:bitcoinj-core:f979c2187e61ee3b08dd4cbfc49a149734cff64c045d29ed112f2e12f34068a3',
|
||||
'com.github.ravn:jsocks:3c71600af027b2b6d4244e4ad14d98ff2352a379410daebefff5d8cd48d742a4',
|
||||
'com.github.sarxos:webcam-capture:d960b7ea8ec3ddf2df0725ef214c3fccc9699ea7772df37f544e1f8e4fd665f6',
|
||||
'com.google.android:annotations:ba734e1e84c09d615af6a09d33034b4f0442f8772dec120efb376d86a565ae15',
|
||||
'com.google.api.grpc:proto-google-common-protos:bd60cd7a423b00fb824c27bdd0293aaf4781be1daba6ed256311103fb4b84108',
|
||||
'com.google.code.findbugs:jsr305:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
||||
'com.google.code.gson:gson:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
|
||||
'com.google.code.gson:gson:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
|
||||
'com.google.errorprone:error_prone_annotations:ec59f1b702d9afc09e8c3929f5c42777dec623a6ea2731ac694332c7d7680f5a',
|
||||
'com.google.guava:guava:36a666e3b71ae7f0f0dca23654b67e086e6c93d192f60ba5dfd5519db6c288c8',
|
||||
'com.google.inject:guice:d258ff1bd9b8b527872f8402648226658ad3149f1f40e74b0566d69e7e042fbc',
|
||||
'com.google.protobuf:protobuf-java:5a1e5c225791eccd3d67a598922e637406190c90155fb97f38e4eab29719324d',
|
||||
'com.google.protobuf:protobuf-java:161d7d61a8cb3970891c299578702fd079646e032329d6c2cabf998d191437c9',
|
||||
'com.google.zxing:core:11aae8fd974ab25faa8208be50468eb12349cd239e93e7c797377fa13e381729',
|
||||
'com.google.zxing:javase:0ec23e2ec12664ddd6347c8920ad647bb3b9da290f897a88516014b56cc77eb9',
|
||||
'com.googlecode.jcsv:jcsv:73ca7d715e90c8d2c2635cc284543b038245a34f70790660ed590e157b8714a2',
|
||||
@ -53,6 +55,16 @@ dependencyVerification {
|
||||
'de.jensd:fontawesomefx-materialdesignfont:dbad8dfdd1c85e298d5bbae25b2399aec9e85064db57b2427d10f3815aa98752',
|
||||
'de.jensd:fontawesomefx:73bacc991a0a6f5cf0f911767c8db161e0949dbca61e8371eb4342e3da96887b',
|
||||
'io.github.microutils:kotlin-logging:4992504fd3c6ecdf9ed10874b9508e758bb908af9e9d7af19a61e9afb6b7e27a',
|
||||
'io.grpc:grpc-api:a269094009588213ab5386a6fb92426b8056a130b2653d3b4e59e971f2f1ef08',
|
||||
'io.grpc:grpc-context:f4c8f878c320f6fb56c1c14692618f6df8253314b556176e32727afbc5921a73',
|
||||
'io.grpc:grpc-core:d67fa113fd9cc45a02710f9c41dda9c15191448c14e9e96fcc21839a41345d4c',
|
||||
'io.grpc:grpc-netty-shaded:9edfd45da473d2efbb5683fc3eaf1857e82d2148033d82dd558a7ac38731ea33',
|
||||
'io.grpc:grpc-protobuf-lite:9ba9aaa3e6997a04c707793c25e3ec88c6bad86f8d6f6b8b7a1a0c33ea2429d8',
|
||||
'io.grpc:grpc-protobuf:454dae7e246dac25526ed5b795d97a5dafedd3cc2042cfc810f02051d7d3e3cb',
|
||||
'io.grpc:grpc-stub:1532e291c0e9fd8230a6416c8ebbd902d99c7e2760241ae638ea761aa3dd5f43',
|
||||
'io.opencensus:opencensus-api:8e2cb0f6391d8eb0a1bcd01e7748883f0033b1941754f4ed3f19d2c3e4276fc8',
|
||||
'io.opencensus:opencensus-contrib-grpc-metrics:29fc79401082301542cab89d7054d2f0825f184492654c950020553ef4ff0ef8',
|
||||
'io.perfmark:perfmark-api:b734ba2149712409a44eabdb799f64768578fee0defe1418bb108fe32ea43e1a',
|
||||
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||
'net.glxn:qrgen:c85d9d8512d91e8ad11fe56259a7825bd50ce0245447e236cf168d1b17591882',
|
||||
'net.jcip:jcip-annotations:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
|
||||
|
@ -2,6 +2,8 @@ include 'assets'
|
||||
include 'common'
|
||||
include 'p2p'
|
||||
include 'core'
|
||||
include 'cli'
|
||||
include 'daemon'
|
||||
include 'desktop'
|
||||
include 'monitor'
|
||||
include 'pricenode'
|
||||
|
Loading…
Reference in New Issue
Block a user