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 />
|
<emptyLine />
|
||||||
<package name="bisq.asset" withSubpackages="true" static="false" />
|
<package name="bisq.asset" withSubpackages="true" static="false" />
|
||||||
<emptyLine />
|
<emptyLine />
|
||||||
<package name="io.bisq.generated" withSubpackages="true" static="false" />
|
<package name="io.grpc" withSubpackages="true" static="false" />
|
||||||
<emptyLine />
|
<emptyLine />
|
||||||
<package name="com.google.protobuf" withSubpackages="true" static="false" />
|
<package name="com.google.protobuf" withSubpackages="true" static="false" />
|
||||||
<emptyLine />
|
<emptyLine />
|
||||||
|
76
build.gradle
76
build.gradle
@ -38,6 +38,7 @@ configure(subprojects) {
|
|||||||
fontawesomefxVersion = '8.0.0'
|
fontawesomefxVersion = '8.0.0'
|
||||||
fontawesomefxCommonsVersion = '9.1.2'
|
fontawesomefxCommonsVersion = '9.1.2'
|
||||||
fontawesomefxMaterialdesignfontVersion = '2.0.26-9.1.2'
|
fontawesomefxMaterialdesignfontVersion = '2.0.26-9.1.2'
|
||||||
|
grpcVersion = '1.25.0'
|
||||||
guavaVersion = '20.0'
|
guavaVersion = '20.0'
|
||||||
guiceVersion = '4.2.2'
|
guiceVersion = '4.2.2'
|
||||||
hamcrestVersion = '1.3'
|
hamcrestVersion = '1.3'
|
||||||
@ -59,7 +60,8 @@ configure(subprojects) {
|
|||||||
lombokVersion = '1.18.2'
|
lombokVersion = '1.18.2'
|
||||||
mockitoVersion = '3.0.0'
|
mockitoVersion = '3.0.0'
|
||||||
netlayerVersion = '0.6.5.2'
|
netlayerVersion = '0.6.5.2'
|
||||||
protobufVersion = '3.9.1'
|
protobufVersion = '3.10.0'
|
||||||
|
protocVersion = protobufVersion
|
||||||
pushyVersion = '0.13.2'
|
pushyVersion = '0.13.2'
|
||||||
qrgenVersion = '1.3'
|
qrgenVersion = '1.3'
|
||||||
sarxosVersion = '0.3.12'
|
sarxosVersion = '0.3.12'
|
||||||
@ -86,7 +88,9 @@ configure(subprojects) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
configure([project(':desktop'),
|
configure([project(':cli'),
|
||||||
|
project(':daemon'),
|
||||||
|
project(':desktop'),
|
||||||
project(':monitor'),
|
project(':monitor'),
|
||||||
project(':relay'),
|
project(':relay'),
|
||||||
project(':seednode'),
|
project(':seednode'),
|
||||||
@ -166,7 +170,7 @@ configure(project(':common')) {
|
|||||||
|
|
||||||
protobuf {
|
protobuf {
|
||||||
protoc {
|
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-base:$javafxVersion:$os"
|
||||||
compile "org.openjfx:javafx-graphics:$javafxVersion:$os"
|
compile "org.openjfx:javafx-graphics:$javafxVersion:$os"
|
||||||
compile "com.google.protobuf:protobuf-java:$protobufVersion"
|
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.springframework:spring-core:$springVersion"
|
||||||
compile "org.slf4j:slf4j-api:$slf4jVersion"
|
compile "org.slf4j:slf4j-api:$slf4jVersion"
|
||||||
compile "ch.qos.logback:logback-core:$logbackVersion"
|
compile "ch.qos.logback:logback-core:$logbackVersion"
|
||||||
@ -225,6 +229,8 @@ configure(project(':p2p')) {
|
|||||||
|
|
||||||
|
|
||||||
configure(project(':core')) {
|
configure(project(':core')) {
|
||||||
|
apply plugin: 'com.google.protobuf'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':assets')
|
compile project(':assets')
|
||||||
compile project(':p2p')
|
compile project(':p2p')
|
||||||
@ -250,7 +256,20 @@ configure(project(':core')) {
|
|||||||
compile("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion") {
|
compile("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion") {
|
||||||
exclude(module: 'jackson-annotations')
|
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"
|
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||||
|
|
||||||
@ -262,11 +281,47 @@ configure(project(':core')) {
|
|||||||
testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
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 {
|
test {
|
||||||
systemProperty 'jdk.attach.allowAttachSelf', true
|
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')) {
|
configure(project(':desktop')) {
|
||||||
apply plugin: 'com.github.johnrengelman.shadow'
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
@ -402,3 +457,14 @@ configure(project(':statsnode')) {
|
|||||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
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;
|
package bisq.core.app;
|
||||||
|
|
||||||
public class AppOptionKeys {
|
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 APP_NAME_KEY = "appName";
|
||||||
public static final String USER_DATA_DIR_KEY = "userDataDir";
|
public static final String USER_DATA_DIR_KEY = "userDataDir";
|
||||||
public static final String APP_DATA_DIR_KEY = "appDataDir";
|
public static final String APP_DATA_DIR_KEY = "appDataDir";
|
||||||
|
@ -186,8 +186,6 @@ public class BisqEnvironment extends StandardEnvironment {
|
|||||||
@Setter
|
@Setter
|
||||||
protected boolean isBitcoinLocalhostNodeRunning;
|
protected boolean isBitcoinLocalhostNodeRunning;
|
||||||
@Getter
|
@Getter
|
||||||
protected String desktopWithHttpApi, desktopWithGrpcApi;
|
|
||||||
@Getter
|
|
||||||
protected List<String> bannedSeedNodes, bannedBtcNodes, bannedPriceRelayNodes;
|
protected List<String> bannedSeedNodes, bannedBtcNodes, bannedPriceRelayNodes;
|
||||||
|
|
||||||
protected final String btcNodes, seedNodes, ignoreDevMsg, useDevPrivilegeKeys, useDevMode, useTorForBtc, rpcUser, rpcPassword,
|
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));
|
appDataDir = getProperty(commandLineProperties, AppOptionKeys.APP_DATA_DIR_KEY, appDataDir(userDataDir, appName));
|
||||||
staticAppDataDir = appDataDir;
|
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, "");
|
ignoreDevMsg = getProperty(commandLineProperties, AppOptionKeys.IGNORE_DEV_MSG_KEY, "");
|
||||||
useDevPrivilegeKeys = getProperty(commandLineProperties, AppOptionKeys.USE_DEV_PRIVILEGE_KEYS, "");
|
useDevPrivilegeKeys = getProperty(commandLineProperties, AppOptionKeys.USE_DEV_PRIVILEGE_KEYS, "");
|
||||||
referralId = getProperty(commandLineProperties, AppOptionKeys.REFERRAL_ID, "");
|
referralId = getProperty(commandLineProperties, AppOptionKeys.REFERRAL_ID, "");
|
||||||
@ -398,8 +394,6 @@ public class BisqEnvironment extends StandardEnvironment {
|
|||||||
setProperty(NetworkOptionKeys.SEND_MSG_THROTTLE_SLEEP, sendMsgThrottleSleep);
|
setProperty(NetworkOptionKeys.SEND_MSG_THROTTLE_SLEEP, sendMsgThrottleSleep);
|
||||||
|
|
||||||
setProperty(AppOptionKeys.APP_DATA_DIR_KEY, appDataDir);
|
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.IGNORE_DEV_MSG_KEY, ignoreDevMsg);
|
||||||
setProperty(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS, useDevPrivilegeKeys);
|
setProperty(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS, useDevPrivilegeKeys);
|
||||||
setProperty(AppOptionKeys.REFERRAL_ID, referralId);
|
setProperty(AppOptionKeys.REFERRAL_ID, referralId);
|
||||||
|
@ -446,16 +446,6 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
|
|||||||
.withRequiredArg()
|
.withRequiredArg()
|
||||||
.ofType(boolean.class);
|
.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,
|
parser.accepts(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS,
|
||||||
format("If that is true all the privileged features which requires a private key " +
|
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"))
|
"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;
|
package bisq.core.app;
|
||||||
|
|
||||||
import bisq.core.CoreModule;
|
|
||||||
|
|
||||||
import bisq.common.UserThread;
|
import bisq.common.UserThread;
|
||||||
import bisq.common.app.AppModule;
|
import bisq.common.app.AppModule;
|
||||||
import bisq.common.app.Version;
|
import bisq.common.app.Version;
|
||||||
|
@ -15,11 +15,9 @@
|
|||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* 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.alert.AlertModule;
|
||||||
import bisq.core.app.AppOptionKeys;
|
|
||||||
import bisq.core.app.BisqEnvironment;
|
|
||||||
import bisq.core.btc.BitcoinModule;
|
import bisq.core.btc.BitcoinModule;
|
||||||
import bisq.core.dao.DaoModule;
|
import bisq.core.dao.DaoModule;
|
||||||
import bisq.core.filter.FilterModule;
|
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);
|
super("Bisq Desktop", "bisq-desktop", Version.VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @Nullable
|
|
||||||
private BisqHttpApiServer bisqHttpApiServer;*/
|
|
||||||
/* @Nullable
|
|
||||||
private BisqGrpcServer bisqGrpcServer;
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
if (BisqExecutable.setupInitialOptionParser(args)) {
|
if (BisqExecutable.setupInitialOptionParser(args)) {
|
||||||
// For some reason the JavaFX launch process results in us losing the thread context class loader: reset it.
|
// 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() {
|
protected void onApplicationStarted() {
|
||||||
super.onApplicationStarted();
|
super.onApplicationStarted();
|
||||||
|
|
||||||
/* if (runWithHttpApi()) {
|
|
||||||
bisqHttpApiServer = new BisqHttpApiServer();
|
|
||||||
}*/
|
|
||||||
/*
|
/*
|
||||||
if (runWithGrpcApi()) {
|
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.desktop.DesktopModule;
|
||||||
|
|
||||||
import bisq.core.CoreModule;
|
import bisq.core.app.CoreModule;
|
||||||
|
|
||||||
import bisq.common.app.AppModule;
|
import bisq.common.app.AppModule;
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
//
|
//
|
||||||
// See https://github.com/signalapp/gradle-witness#using-witness for further details.
|
// See https://github.com/signalapp/gradle-witness#using-witness for further details.
|
||||||
|
|
||||||
|
|
||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'aopalliance:aopalliance:0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08',
|
'aopalliance:aopalliance:0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08',
|
||||||
@ -32,11 +31,14 @@ dependencyVerification {
|
|||||||
'com.github.bisq-network.bitcoinj:bitcoinj-core:f979c2187e61ee3b08dd4cbfc49a149734cff64c045d29ed112f2e12f34068a3',
|
'com.github.bisq-network.bitcoinj:bitcoinj-core:f979c2187e61ee3b08dd4cbfc49a149734cff64c045d29ed112f2e12f34068a3',
|
||||||
'com.github.ravn:jsocks:3c71600af027b2b6d4244e4ad14d98ff2352a379410daebefff5d8cd48d742a4',
|
'com.github.ravn:jsocks:3c71600af027b2b6d4244e4ad14d98ff2352a379410daebefff5d8cd48d742a4',
|
||||||
'com.github.sarxos:webcam-capture:d960b7ea8ec3ddf2df0725ef214c3fccc9699ea7772df37f544e1f8e4fd665f6',
|
'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.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.guava:guava:36a666e3b71ae7f0f0dca23654b67e086e6c93d192f60ba5dfd5519db6c288c8',
|
||||||
'com.google.inject:guice:d258ff1bd9b8b527872f8402648226658ad3149f1f40e74b0566d69e7e042fbc',
|
'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:core:11aae8fd974ab25faa8208be50468eb12349cd239e93e7c797377fa13e381729',
|
||||||
'com.google.zxing:javase:0ec23e2ec12664ddd6347c8920ad647bb3b9da290f897a88516014b56cc77eb9',
|
'com.google.zxing:javase:0ec23e2ec12664ddd6347c8920ad647bb3b9da290f897a88516014b56cc77eb9',
|
||||||
'com.googlecode.jcsv:jcsv:73ca7d715e90c8d2c2635cc284543b038245a34f70790660ed590e157b8714a2',
|
'com.googlecode.jcsv:jcsv:73ca7d715e90c8d2c2635cc284543b038245a34f70790660ed590e157b8714a2',
|
||||||
@ -53,6 +55,16 @@ dependencyVerification {
|
|||||||
'de.jensd:fontawesomefx-materialdesignfont:dbad8dfdd1c85e298d5bbae25b2399aec9e85064db57b2427d10f3815aa98752',
|
'de.jensd:fontawesomefx-materialdesignfont:dbad8dfdd1c85e298d5bbae25b2399aec9e85064db57b2427d10f3815aa98752',
|
||||||
'de.jensd:fontawesomefx:73bacc991a0a6f5cf0f911767c8db161e0949dbca61e8371eb4342e3da96887b',
|
'de.jensd:fontawesomefx:73bacc991a0a6f5cf0f911767c8db161e0949dbca61e8371eb4342e3da96887b',
|
||||||
'io.github.microutils:kotlin-logging:4992504fd3c6ecdf9ed10874b9508e758bb908af9e9d7af19a61e9afb6b7e27a',
|
'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',
|
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'net.glxn:qrgen:c85d9d8512d91e8ad11fe56259a7825bd50ce0245447e236cf168d1b17591882',
|
'net.glxn:qrgen:c85d9d8512d91e8ad11fe56259a7825bd50ce0245447e236cf168d1b17591882',
|
||||||
'net.jcip:jcip-annotations:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
|
'net.jcip:jcip-annotations:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
|
||||||
|
@ -2,6 +2,8 @@ include 'assets'
|
|||||||
include 'common'
|
include 'common'
|
||||||
include 'p2p'
|
include 'p2p'
|
||||||
include 'core'
|
include 'core'
|
||||||
|
include 'cli'
|
||||||
|
include 'daemon'
|
||||||
include 'desktop'
|
include 'desktop'
|
||||||
include 'monitor'
|
include 'monitor'
|
||||||
include 'pricenode'
|
include 'pricenode'
|
||||||
|
Loading…
Reference in New Issue
Block a user