mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Merge pull request #6313 from ghubstan/remove-subproject-daonode
Remove subproject daonode
This commit is contained in:
commit
869fdad705
53
build.gradle
53
build.gradle
@ -54,7 +54,6 @@ configure(subprojects) {
|
|||||||
javafxVersion = '16'
|
javafxVersion = '16'
|
||||||
javaxAnnotationVersion = '1.2'
|
javaxAnnotationVersion = '1.2'
|
||||||
jcsvVersion = '1.4.0'
|
jcsvVersion = '1.4.0'
|
||||||
jerseyVersion = '3.0.4'
|
|
||||||
jetbrainsAnnotationsVersion = '13.0'
|
jetbrainsAnnotationsVersion = '13.0'
|
||||||
jfoenixVersion = '9.0.10'
|
jfoenixVersion = '9.0.10'
|
||||||
joptVersion = '5.0.4'
|
joptVersion = '5.0.4'
|
||||||
@ -77,7 +76,6 @@ configure(subprojects) {
|
|||||||
slf4jVersion = '1.7.30'
|
slf4jVersion = '1.7.30'
|
||||||
sparkVersion = '2.5.2'
|
sparkVersion = '2.5.2'
|
||||||
springBootVersion = '2.5.6'
|
springBootVersion = '2.5.6'
|
||||||
swaggerVersion = '2.2.0'
|
|
||||||
|
|
||||||
os = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os
|
os = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os
|
||||||
}
|
}
|
||||||
@ -105,7 +103,6 @@ configure([project(':cli'),
|
|||||||
project(':seednode'),
|
project(':seednode'),
|
||||||
project(':statsnode'),
|
project(':statsnode'),
|
||||||
project(':pricenode'),
|
project(':pricenode'),
|
||||||
project(':daonode'),
|
|
||||||
project(':apitest')]) {
|
project(':apitest')]) {
|
||||||
|
|
||||||
apply plugin: 'application'
|
apply plugin: 'application'
|
||||||
@ -689,56 +686,6 @@ configure(project(':seednode')) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(project(':daonode')) {
|
|
||||||
apply plugin: 'com.github.johnrengelman.shadow'
|
|
||||||
|
|
||||||
mainClassName = 'bisq.daoNode.DaoNodeRestApiApplication'
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(':common')
|
|
||||||
implementation project(':proto')
|
|
||||||
implementation project(':p2p')
|
|
||||||
implementation project(':core')
|
|
||||||
implementation "com.google.guava:guava:$guavaVersion"
|
|
||||||
implementation("com.google.inject:guice:$guiceVersion") {
|
|
||||||
exclude(module: 'guava')
|
|
||||||
}
|
|
||||||
|
|
||||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
implementation "ch.qos.logback:logback-classic:$logbackVersion"
|
|
||||||
implementation "ch.qos.logback:logback-core:$logbackVersion"
|
|
||||||
implementation "org.slf4j:slf4j-api:$slf4jVersion"
|
|
||||||
|
|
||||||
/* implementation("com.fasterxml.jackson.core:jackson-core:$jacksonVersion")
|
|
||||||
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
|
|
||||||
implementation("com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion")
|
|
||||||
|
|
||||||
implementation "com.google.protobuf:protobuf-java-util:$protobufVersion"*/
|
|
||||||
|
|
||||||
implementation("org.glassfish.jersey.containers:jersey-container-jdk-http:$jerseyVersion")
|
|
||||||
implementation("org.glassfish.jersey.media:jersey-media-json-jackson:$jerseyVersion")
|
|
||||||
implementation("org.glassfish.jersey.inject:jersey-hk2:$jerseyVersion")
|
|
||||||
implementation("org.glassfish.jaxb:jaxb-runtime:3.0.2")
|
|
||||||
implementation("io.swagger.core.v3:swagger-jaxrs2-jakarta:$swaggerVersion")
|
|
||||||
|
|
||||||
testImplementation "org.mockito:mockito-core:$mockitoVersion"
|
|
||||||
|
|
||||||
testCompileOnly "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
testImplementation "org.apache.httpcomponents:httpclient:$httpclientVersion"
|
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
|
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
|
|
||||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
testLogging {
|
|
||||||
events "passed", "skipped", "failed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configure(project(':statsnode')) {
|
configure(project(':statsnode')) {
|
||||||
mainClassName = 'bisq.statistics.StatisticsMain'
|
mainClassName = 'bisq.statistics.StatisticsMain'
|
||||||
|
|
||||||
|
@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode;
|
|
||||||
|
|
||||||
import bisq.common.config.Config;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import bisq.daonode.endpoints.AccountAgeApi;
|
|
||||||
import bisq.daonode.endpoints.BondedReputationApi;
|
|
||||||
import bisq.daonode.endpoints.ProofOfBurnApi;
|
|
||||||
import bisq.daonode.endpoints.SignedWitnessApi;
|
|
||||||
import bisq.daonode.error.CustomExceptionMapper;
|
|
||||||
import bisq.daonode.error.StatusException;
|
|
||||||
import bisq.daonode.util.StaticFileHandler;
|
|
||||||
import com.sun.net.httpserver.HttpServer;
|
|
||||||
import org.glassfish.jersey.jdkhttp.JdkHttpServerFactory;
|
|
||||||
import org.glassfish.jersey.server.ResourceConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Application to start and config the rest service.
|
|
||||||
* This creates a rest service for clients to connect and for users to browse the documentation.
|
|
||||||
* <p>
|
|
||||||
* Swagger doc are available at <a href="http://localhost:8082/doc/v1/index.html">REST API documentation</a>
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class DaoNodeRestApiApplication extends ResourceConfig {
|
|
||||||
@Getter
|
|
||||||
private static String baseUrl;
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
DaoNodeRestApiApplication daoNodeRestApiApplication = new DaoNodeRestApiApplication();
|
|
||||||
daoNodeRestApiApplication.startDaoNode(args, config -> {
|
|
||||||
daoNodeRestApiApplication
|
|
||||||
.register(CustomExceptionMapper.class)
|
|
||||||
.register(StatusException.StatusExceptionMapper.class)
|
|
||||||
.register(ProofOfBurnApi.class)
|
|
||||||
.register(BondedReputationApi.class)
|
|
||||||
.register(AccountAgeApi.class)
|
|
||||||
.register(SignedWitnessApi.class)
|
|
||||||
.register(SwaggerResolution.class);
|
|
||||||
daoNodeRestApiApplication.startServer(config.daoNodeApiUrl, config.daoNodeApiPort);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final ServiceNode serviceNode;
|
|
||||||
|
|
||||||
private HttpServer httpServer;
|
|
||||||
|
|
||||||
public DaoNodeRestApiApplication() {
|
|
||||||
serviceNode = new ServiceNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startDaoNode(String[] args, Consumer<Config> configConsumer) {
|
|
||||||
new Thread(() -> {
|
|
||||||
serviceNode.execute(args);
|
|
||||||
configConsumer.accept(serviceNode.getConfig());
|
|
||||||
try {
|
|
||||||
// Keep running
|
|
||||||
Thread.currentThread().setName("daoNodeThread");
|
|
||||||
Thread.currentThread().join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.error("daoNodeThread interrupted", e);
|
|
||||||
e.printStackTrace();
|
|
||||||
shutDown();
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startServer(String url, int port) {
|
|
||||||
baseUrl = url + ":" + port + "/api/v1";
|
|
||||||
httpServer = JdkHttpServerFactory.createHttpServer(URI.create(baseUrl), this);
|
|
||||||
httpServer.createContext("/doc", new StaticFileHandler("/doc/v1/"));
|
|
||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(this::shutDown));
|
|
||||||
|
|
||||||
log.info("Server started at {}.", baseUrl);
|
|
||||||
|
|
||||||
// block and wait shut down signal, like CTRL+C
|
|
||||||
try {
|
|
||||||
Thread.currentThread().setName("serverThread");
|
|
||||||
Thread.currentThread().join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.error("serverThread interrupted", e);
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
shutDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void shutDown() {
|
|
||||||
if (serviceNode != null) {
|
|
||||||
serviceNode.gracefulShutDown(this::stopServer);
|
|
||||||
} else {
|
|
||||||
stopServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopServer() {
|
|
||||||
if (httpServer != null) {
|
|
||||||
httpServer.stop(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,210 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode;
|
|
||||||
|
|
||||||
|
|
||||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
|
||||||
import bisq.core.app.TorSetup;
|
|
||||||
import bisq.core.app.misc.AppSetupWithP2PAndDAO;
|
|
||||||
import bisq.core.app.misc.ExecutableForAppWithP2p;
|
|
||||||
import bisq.core.app.misc.ModuleForAppWithP2p;
|
|
||||||
import bisq.core.dao.governance.bond.reputation.BondedReputationRepository;
|
|
||||||
import bisq.core.dao.state.DaoStateService;
|
|
||||||
import bisq.core.dao.state.DaoStateSnapshotService;
|
|
||||||
import bisq.core.user.Cookie;
|
|
||||||
import bisq.core.user.CookieKey;
|
|
||||||
import bisq.core.user.Preferences;
|
|
||||||
import bisq.core.user.User;
|
|
||||||
|
|
||||||
import bisq.network.p2p.P2PService;
|
|
||||||
import bisq.network.p2p.P2PServiceListener;
|
|
||||||
import bisq.network.p2p.peers.PeerManager;
|
|
||||||
|
|
||||||
import bisq.common.Timer;
|
|
||||||
import bisq.common.UserThread;
|
|
||||||
import bisq.common.app.AppModule;
|
|
||||||
import bisq.common.app.Version;
|
|
||||||
import bisq.common.config.BaseCurrencyNetwork;
|
|
||||||
import bisq.common.config.Config;
|
|
||||||
import bisq.common.handlers.ResultHandler;
|
|
||||||
|
|
||||||
import com.google.inject.Key;
|
|
||||||
import com.google.inject.name.Names;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
//todo not sure if the restart handling from seed nodes is required
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class ServiceNode extends ExecutableForAppWithP2p {
|
|
||||||
private static final long CHECK_CONNECTION_LOSS_SEC = 30;
|
|
||||||
|
|
||||||
private Timer checkConnectionLossTime;
|
|
||||||
@Getter
|
|
||||||
private DaoStateService daoStateService;
|
|
||||||
@Getter
|
|
||||||
private BondedReputationRepository bondedReputationRepository;
|
|
||||||
@Getter
|
|
||||||
private AccountAgeWitnessService accountAgeWitnessService;
|
|
||||||
|
|
||||||
public ServiceNode() {
|
|
||||||
super("Bisq Dao Node", "bisq-dao-node", "bisq_dao_node", Version.VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Config getConfig() {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doExecute() {
|
|
||||||
super.doExecute();
|
|
||||||
|
|
||||||
checkMemory(config, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void launchApplication() {
|
|
||||||
UserThread.execute(() -> {
|
|
||||||
try {
|
|
||||||
onApplicationLaunched();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// We continue with a series of synchronous execution tasks
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AppModule getModule() {
|
|
||||||
return new ModuleForAppWithP2p(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void applyInjector() {
|
|
||||||
super.applyInjector();
|
|
||||||
|
|
||||||
injector.getInstance(DaoStateSnapshotService.class).setDaoRequiresRestartHandler(this::gracefulShutDown);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void startApplication() {
|
|
||||||
super.startApplication();
|
|
||||||
|
|
||||||
Cookie cookie = injector.getInstance(User.class).getCookie();
|
|
||||||
cookie.getAsOptionalBoolean(CookieKey.CLEAN_TOR_DIR_AT_RESTART).ifPresent(wasCleanTorDirSet -> {
|
|
||||||
if (wasCleanTorDirSet) {
|
|
||||||
injector.getInstance(TorSetup.class).cleanupTorFiles(() -> {
|
|
||||||
log.info("Tor directory reset");
|
|
||||||
cookie.remove(CookieKey.CLEAN_TOR_DIR_AT_RESTART);
|
|
||||||
}, log::error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
injector.getInstance(Preferences.class).setUseFullModeDaoMonitor(false);
|
|
||||||
injector.getInstance(AppSetupWithP2PAndDAO.class).start();
|
|
||||||
|
|
||||||
daoStateService = injector.getInstance(DaoStateService.class);
|
|
||||||
accountAgeWitnessService = injector.getInstance(AccountAgeWitnessService.class);
|
|
||||||
bondedReputationRepository = injector.getInstance(BondedReputationRepository.class);
|
|
||||||
|
|
||||||
injector.getInstance(P2PService.class).addP2PServiceListener(new P2PServiceListener() {
|
|
||||||
@Override
|
|
||||||
public void onDataReceived() {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNoSeedNodeAvailable() {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNoPeersAvailable() {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUpdatedDataReceived() {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTorNodeReady() {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onHiddenServicePublished() {
|
|
||||||
boolean preventPeriodicShutdownAtSeedNode = injector.getInstance(Key.get(boolean.class,
|
|
||||||
Names.named(Config.PREVENT_PERIODIC_SHUTDOWN_AT_SEED_NODE)));
|
|
||||||
if (!preventPeriodicShutdownAtSeedNode) {
|
|
||||||
startShutDownInterval(ServiceNode.this);
|
|
||||||
}
|
|
||||||
UserThread.runAfter(() -> setupConnectionLossCheck(), 60);
|
|
||||||
|
|
||||||
accountAgeWitnessService.onAllServicesInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSetupFailed(Throwable throwable) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestCustomBridges() {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupConnectionLossCheck() {
|
|
||||||
// For dev testing (usually on BTC_REGTEST) we don't want to get the seed shut
|
|
||||||
// down as it is normal that the seed is the only actively running node.
|
|
||||||
if (Config.baseCurrencyNetwork() == BaseCurrencyNetwork.BTC_REGTEST) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checkConnectionLossTime != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkConnectionLossTime = UserThread.runPeriodically(() -> {
|
|
||||||
if (injector.getInstance(PeerManager.class).getNumAllConnectionsLostEvents() > 1) {
|
|
||||||
// We set a flag to clear tor cache files at re-start. We cannot clear it now as Tor is used and
|
|
||||||
// that can cause problems.
|
|
||||||
injector.getInstance(User.class).getCookie().putAsBoolean(CookieKey.CLEAN_TOR_DIR_AT_RESTART, true);
|
|
||||||
shutDown(this);
|
|
||||||
}
|
|
||||||
}, CHECK_CONNECTION_LOSS_SEC);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void gracefulShutDown() {
|
|
||||||
gracefulShutDown(() -> {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void gracefulShutDown(ResultHandler resultHandler) {
|
|
||||||
super.gracefulShutDown(resultHandler);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import io.swagger.v3.core.util.Json;
|
|
||||||
import io.swagger.v3.jaxrs2.Reader;
|
|
||||||
import io.swagger.v3.oas.annotations.Hidden;
|
|
||||||
import io.swagger.v3.oas.integration.SwaggerConfiguration;
|
|
||||||
import io.swagger.v3.oas.models.OpenAPI;
|
|
||||||
import io.swagger.v3.oas.models.info.Info;
|
|
||||||
import io.swagger.v3.oas.models.info.License;
|
|
||||||
import io.swagger.v3.oas.models.servers.Server;
|
|
||||||
import jakarta.ws.rs.GET;
|
|
||||||
import jakarta.ws.rs.Path;
|
|
||||||
import jakarta.ws.rs.Produces;
|
|
||||||
import jakarta.ws.rs.core.Application;
|
|
||||||
import jakarta.ws.rs.core.Context;
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Path("openapi.json")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Hidden
|
|
||||||
public class SwaggerResolution {
|
|
||||||
private static String swaggerJson;
|
|
||||||
|
|
||||||
@GET
|
|
||||||
public String swagIt(@Context Application application) {
|
|
||||||
if (swaggerJson == null) {
|
|
||||||
try {
|
|
||||||
OpenAPI api = new OpenAPI();
|
|
||||||
Info info = new Info()
|
|
||||||
.title("Bisq DAO node REST API")
|
|
||||||
.description("This is the rest API description for the Bisq DAO node, For more Information about Bisq, see https://bisq.network")
|
|
||||||
.license(new License()
|
|
||||||
.name("GNU Affero General Public License")
|
|
||||||
.url("https://github.com/bisq-network/bisq2/blob/main/LICENSE"));
|
|
||||||
|
|
||||||
api.info(info).addServersItem(new Server().url(DaoNodeRestApiApplication.getBaseUrl()));
|
|
||||||
SwaggerConfiguration configuration = new SwaggerConfiguration().openAPI(api);
|
|
||||||
Reader reader = new Reader(configuration);
|
|
||||||
OpenAPI openAPI = reader.read(application.getClasses());
|
|
||||||
swaggerJson = Json.pretty(openAPI);
|
|
||||||
} catch (Exception exception) {
|
|
||||||
log.error("", exception);
|
|
||||||
throw new RuntimeException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return swaggerJson;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode.dto;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimal data required for Bisq 2 bonded reputation use case.
|
|
||||||
* Need to be in sync with the Bisq 2 BondedReputationDto class.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Slf4j
|
|
||||||
@Schema(title = "BondedReputation")
|
|
||||||
public class BondedReputationDto {
|
|
||||||
private final long amount;
|
|
||||||
private final long time;
|
|
||||||
private final String hash;
|
|
||||||
private final int blockHeight;
|
|
||||||
private final int lockTime;
|
|
||||||
|
|
||||||
public BondedReputationDto(long amount, long time, String hash, int blockHeight, int lockTime) {
|
|
||||||
this.amount = amount;
|
|
||||||
this.time = time;
|
|
||||||
this.hash = hash;
|
|
||||||
this.blockHeight = blockHeight;
|
|
||||||
this.lockTime = lockTime;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode.dto;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimal data required for Bisq 2 proof of burn use case.
|
|
||||||
* Need to be in sync with the Bisq 2 ProofOfBurnDto class.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Schema(title = "ProofOfBurn")
|
|
||||||
public class ProofOfBurnDto {
|
|
||||||
private final long amount;
|
|
||||||
private final long time;
|
|
||||||
private final String hash;
|
|
||||||
private final int blockHeight;
|
|
||||||
|
|
||||||
public ProofOfBurnDto(long amount, long time, String hash, int blockHeight) {
|
|
||||||
this.amount = amount;
|
|
||||||
this.time = time;
|
|
||||||
this.hash = hash;
|
|
||||||
this.blockHeight = blockHeight;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode.endpoints;
|
|
||||||
|
|
||||||
import bisq.core.account.witness.AccountAgeWitness;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import bisq.daonode.DaoNodeRestApiApplication;
|
|
||||||
import bisq.daonode.ServiceNode;
|
|
||||||
import bisq.daonode.dto.ProofOfBurnDto;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Content;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import jakarta.ws.rs.GET;
|
|
||||||
import jakarta.ws.rs.Path;
|
|
||||||
import jakarta.ws.rs.PathParam;
|
|
||||||
import jakarta.ws.rs.Produces;
|
|
||||||
import jakarta.ws.rs.core.Application;
|
|
||||||
import jakarta.ws.rs.core.Context;
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Endpoint for getting the account age date from a given hash as hex string.
|
|
||||||
* Used for reputation system in Bisq 2.
|
|
||||||
* <a href="http://localhost:8082/api/v1/account-age/get-date/dd75a7175c7c83fe9a4729e36b85f5fbc44e29ae">Request with hash</a>
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Path("/account-age")
|
|
||||||
@Produces(MediaType.TEXT_PLAIN)
|
|
||||||
@Tag(name = "Account age API")
|
|
||||||
public class AccountAgeApi {
|
|
||||||
private static final String DESC_HASH = "The hash of the account age witness as hex string";
|
|
||||||
private final ServiceNode serviceNode;
|
|
||||||
|
|
||||||
public AccountAgeApi(@Context Application application) {
|
|
||||||
serviceNode = ((DaoNodeRestApiApplication) application).getServiceNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(description = "Request the account age date")
|
|
||||||
@ApiResponse(responseCode = "200", description = "The account age date",
|
|
||||||
content = {@Content(mediaType = MediaType.TEXT_PLAIN,
|
|
||||||
schema = @Schema(allOf = ProofOfBurnDto.class))}
|
|
||||||
)
|
|
||||||
@GET
|
|
||||||
@Path("get-date/{hash}")
|
|
||||||
public Long getDate(@Parameter(description = DESC_HASH)
|
|
||||||
@PathParam("hash")
|
|
||||||
String hash) {
|
|
||||||
return checkNotNull(serviceNode.getAccountAgeWitnessService()).getWitnessByHashAsHex(hash)
|
|
||||||
.map(AccountAgeWitness::getDate)
|
|
||||||
.orElse(-1L);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode.endpoints;
|
|
||||||
|
|
||||||
import bisq.core.dao.governance.bond.reputation.BondedReputationRepository;
|
|
||||||
import bisq.core.dao.state.DaoStateService;
|
|
||||||
import bisq.core.dao.state.model.blockchain.Tx;
|
|
||||||
|
|
||||||
import bisq.common.util.Hex;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import bisq.daonode.DaoNodeRestApiApplication;
|
|
||||||
import bisq.daonode.ServiceNode;
|
|
||||||
import bisq.daonode.dto.BondedReputationDto;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Content;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import jakarta.ws.rs.GET;
|
|
||||||
import jakarta.ws.rs.Path;
|
|
||||||
import jakarta.ws.rs.PathParam;
|
|
||||||
import jakarta.ws.rs.Produces;
|
|
||||||
import jakarta.ws.rs.core.Application;
|
|
||||||
import jakarta.ws.rs.core.Context;
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Endpoint for getting the bonded reputation data from a given block height.
|
|
||||||
* Used for reputation system in Bisq 2.
|
|
||||||
* <a href="http://localhost:8082/api/v1/bonded-reputation/get-bonded-reputation/0">Request with block height 0</a>
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Path("/bonded-reputation")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Tag(name = "Bonded reputation API")
|
|
||||||
public class BondedReputationApi {
|
|
||||||
private static final String DESC_BLOCK_HEIGHT = "The block height from which we request the bonded reputation data";
|
|
||||||
private final BondedReputationRepository bondedReputationRepository;
|
|
||||||
private final DaoStateService daoStateService;
|
|
||||||
|
|
||||||
public BondedReputationApi(@Context Application application) {
|
|
||||||
ServiceNode serviceNode = ((DaoNodeRestApiApplication) application).getServiceNode();
|
|
||||||
daoStateService = serviceNode.getDaoStateService();
|
|
||||||
bondedReputationRepository = serviceNode.getBondedReputationRepository();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(description = "Request the bonded reputation data")
|
|
||||||
@ApiResponse(responseCode = "200", description = "The bonded reputation data",
|
|
||||||
content = {@Content(mediaType = MediaType.APPLICATION_JSON,
|
|
||||||
schema = @Schema(allOf = BondedReputationDto.class))}
|
|
||||||
)
|
|
||||||
@GET
|
|
||||||
@Path("get-bonded-reputation/{block-height}")
|
|
||||||
public List<BondedReputationDto> getBondedReputation(@Parameter(description = DESC_BLOCK_HEIGHT)
|
|
||||||
@PathParam("block-height")
|
|
||||||
int fromBlockHeight) {
|
|
||||||
return bondedReputationRepository.getActiveBonds().stream()
|
|
||||||
.map(bondedReputation -> {
|
|
||||||
Optional<Tx> optionalTx = daoStateService.getTx(bondedReputation.getLockupTxId());
|
|
||||||
if (optionalTx.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Tx tx = optionalTx.get();
|
|
||||||
int blockHeight = tx.getBlockHeight();
|
|
||||||
if (blockHeight >= fromBlockHeight) {
|
|
||||||
return new BondedReputationDto(bondedReputation.getAmount(),
|
|
||||||
tx.getTime(),
|
|
||||||
Hex.encode(bondedReputation.getBondedAsset().getHash()),
|
|
||||||
blockHeight,
|
|
||||||
bondedReputation.getLockTime()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}).filter(Objects::nonNull)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode.endpoints;
|
|
||||||
|
|
||||||
import bisq.core.dao.governance.proofofburn.ProofOfBurnService;
|
|
||||||
|
|
||||||
import bisq.common.util.Hex;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import bisq.daonode.DaoNodeRestApiApplication;
|
|
||||||
import bisq.daonode.ServiceNode;
|
|
||||||
import bisq.daonode.dto.ProofOfBurnDto;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Content;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import jakarta.ws.rs.GET;
|
|
||||||
import jakarta.ws.rs.Path;
|
|
||||||
import jakarta.ws.rs.PathParam;
|
|
||||||
import jakarta.ws.rs.Produces;
|
|
||||||
import jakarta.ws.rs.core.Application;
|
|
||||||
import jakarta.ws.rs.core.Context;
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Endpoint for getting the proof of burn data from a given block height.
|
|
||||||
* Used for reputation system in Bisq 2.
|
|
||||||
* <a href="http://localhost:8082/api/v1/proof-of-burn/get-proof-of-burn/0">Request with block height 0</a>
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Path("/proof-of-burn")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Tag(name = "Proof of burn API")
|
|
||||||
public class ProofOfBurnApi {
|
|
||||||
private static final String DESC_BLOCK_HEIGHT = "The block height from which we request the proof of burn data";
|
|
||||||
private final ServiceNode serviceNode;
|
|
||||||
|
|
||||||
public ProofOfBurnApi(@Context Application application) {
|
|
||||||
serviceNode = ((DaoNodeRestApiApplication) application).getServiceNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(description = "Request the proof of burn data")
|
|
||||||
@ApiResponse(responseCode = "200", description = "The proof of burn data",
|
|
||||||
content = {@Content(mediaType = MediaType.APPLICATION_JSON,
|
|
||||||
schema = @Schema(allOf = ProofOfBurnDto.class))}
|
|
||||||
)
|
|
||||||
@GET
|
|
||||||
@Path("get-proof-of-burn/{block-height}")
|
|
||||||
public List<ProofOfBurnDto> getProofOfBurn(@Parameter(description = DESC_BLOCK_HEIGHT)
|
|
||||||
@PathParam("block-height")
|
|
||||||
int fromBlockHeight) {
|
|
||||||
return checkNotNull(serviceNode.getDaoStateService()).getProofOfBurnTxs().stream()
|
|
||||||
.filter(tx -> tx.getBlockHeight() >= fromBlockHeight)
|
|
||||||
.map(tx -> new ProofOfBurnDto(tx.getBurntBsq(),
|
|
||||||
tx.getTime(),
|
|
||||||
Hex.encode(ProofOfBurnService.getHashFromOpReturnData(tx)),
|
|
||||||
tx.getBlockHeight()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode.endpoints;
|
|
||||||
|
|
||||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import bisq.daonode.DaoNodeRestApiApplication;
|
|
||||||
import bisq.daonode.ServiceNode;
|
|
||||||
import bisq.daonode.dto.ProofOfBurnDto;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Content;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import jakarta.ws.rs.GET;
|
|
||||||
import jakarta.ws.rs.Path;
|
|
||||||
import jakarta.ws.rs.PathParam;
|
|
||||||
import jakarta.ws.rs.Produces;
|
|
||||||
import jakarta.ws.rs.core.Application;
|
|
||||||
import jakarta.ws.rs.core.Context;
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Endpoint for getting the signed witness date from a given hash as hex string.
|
|
||||||
* Used for reputation system in Bisq 2.
|
|
||||||
* <a href="http://localhost:8082/api/v1/signed-witness/get-date/dd75a7175c7c83fe9a4729e36b85f5fbc44e29ae">Request with hash</a>
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Path("/signed-witness")
|
|
||||||
@Produces(MediaType.TEXT_PLAIN)
|
|
||||||
@Tag(name = "Signed witness API")
|
|
||||||
public class SignedWitnessApi {
|
|
||||||
private static final String DESC_HASH = "The hash of the signed account age witness as hex string";
|
|
||||||
private final ServiceNode serviceNode;
|
|
||||||
|
|
||||||
public SignedWitnessApi(@Context Application application) {
|
|
||||||
serviceNode = ((DaoNodeRestApiApplication) application).getServiceNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(description = "Request the signed witness date")
|
|
||||||
@ApiResponse(responseCode = "200", description = "The signed witness date",
|
|
||||||
content = {@Content(mediaType = MediaType.TEXT_PLAIN,
|
|
||||||
schema = @Schema(allOf = ProofOfBurnDto.class))}
|
|
||||||
)
|
|
||||||
@GET
|
|
||||||
@Path("get-date/{hash}")
|
|
||||||
public Long getDate(@Parameter(description = DESC_HASH)
|
|
||||||
@PathParam("hash")
|
|
||||||
String hash) {
|
|
||||||
AccountAgeWitnessService accountAgeWitnessService = checkNotNull(serviceNode.getAccountAgeWitnessService());
|
|
||||||
return accountAgeWitnessService.getWitnessByHashAsHex(hash)
|
|
||||||
.map(accountAgeWitnessService::getWitnessSignDate)
|
|
||||||
.orElse(-1L);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode.error;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import jakarta.ws.rs.ext.ExceptionMapper;
|
|
||||||
import jakarta.ws.rs.ext.Provider;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Provider
|
|
||||||
public class CustomExceptionMapper implements ExceptionMapper<Exception> {
|
|
||||||
@Override
|
|
||||||
public Response toResponse(Exception exception) {
|
|
||||||
log.error("", exception);
|
|
||||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
|
||||||
.entity(new ErrorMessage(exception.getMessage()))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode.error;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class ErrorMessage {
|
|
||||||
private final String error;
|
|
||||||
|
|
||||||
public ErrorMessage(String error) {
|
|
||||||
this.error = error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode.error;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import jakarta.ws.rs.ext.ExceptionMapper;
|
|
||||||
import jakarta.ws.rs.ext.Provider;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Provider
|
|
||||||
public class StatusException extends RuntimeException {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
protected Response.Status httpStatus;
|
|
||||||
|
|
||||||
public StatusException() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public StatusException(Response.Status httpStatus, String message) {
|
|
||||||
super(message);
|
|
||||||
this.httpStatus = httpStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class StatusExceptionMapper implements ExceptionMapper<StatusException> {
|
|
||||||
@Override
|
|
||||||
public Response toResponse(StatusException exception) {
|
|
||||||
log.error("", exception);
|
|
||||||
return Response.status(exception.getHttpStatus())
|
|
||||||
.entity(new ErrorMessage(exception.getMessage()))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.daonode.util;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import com.sun.net.httpserver.Headers;
|
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
|
||||||
import com.sun.net.httpserver.HttpHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JDK Server needs handler for serving files, will change in JDK 18
|
|
||||||
* Currently this is only to serve the swagger-ui content to the client.
|
|
||||||
* So any call to this handler must begin with api/v1. We keep v1 in case
|
|
||||||
* we will have incompatible changes in the future.
|
|
||||||
* This handler is limited to html,css,json and javascript files.
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class StaticFileHandler implements HttpHandler {
|
|
||||||
private static final String NOT_FOUND = "404 (Not Found)\n";
|
|
||||||
public static final String[] VALID_SUFFIX = {".html", ".json", ".css", ".js"};
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
protected final String rootContext;
|
|
||||||
|
|
||||||
public StaticFileHandler(String rootContext) {
|
|
||||||
this.rootContext = rootContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handle(HttpExchange exchange) throws IOException {
|
|
||||||
URI uri = exchange.getRequestURI();
|
|
||||||
|
|
||||||
log.debug("requesting: " + uri.getPath());
|
|
||||||
String filename = uri.getPath();
|
|
||||||
if (filename == null || !filename.startsWith(rootContext) ||
|
|
||||||
Arrays.stream(VALID_SUFFIX).noneMatch(filename::endsWith)) {
|
|
||||||
respond404(exchange);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// resource loading without leading slash
|
|
||||||
String resourceName = filename.replace("..", "");
|
|
||||||
if (filename.charAt(0) == '/') {
|
|
||||||
resourceName = filename.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// we are using getResourceAsStream to ultimately prevent load from parent directories
|
|
||||||
try (InputStream resource = getClass().getClassLoader().getResourceAsStream(resourceName)) {
|
|
||||||
if (resource == null) {
|
|
||||||
respond404(exchange);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log.debug("sending: " + resourceName);
|
|
||||||
// Object exists and is a file: accept with response code 200.
|
|
||||||
String mime = "text/html";
|
|
||||||
if (resourceName.endsWith(".js")) mime = "application/javascript";
|
|
||||||
if (resourceName.endsWith(".json")) mime = "application/json";
|
|
||||||
if (resourceName.endsWith(".css")) mime = "text/css";
|
|
||||||
if (resourceName.endsWith(".png")) mime = "image/png";
|
|
||||||
|
|
||||||
Headers headers = exchange.getResponseHeaders();
|
|
||||||
headers.set("Content-Type", mime);
|
|
||||||
headers.add("Cache-Control", "max-age=3600"); // cache static content on browser for 3600 seconds
|
|
||||||
exchange.sendResponseHeaders(200, 0);
|
|
||||||
|
|
||||||
try (OutputStream outputStream = exchange.getResponseBody()) {
|
|
||||||
byte[] buffer = new byte[0x10000];
|
|
||||||
int count;
|
|
||||||
while ((count = resource.read(buffer)) >= 0) {
|
|
||||||
outputStream.write(buffer, 0, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void respond404(HttpExchange exchange) throws IOException {
|
|
||||||
// Object does not exist or is not a file: reject with 404 error.
|
|
||||||
exchange.sendResponseHeaders(404, NOT_FOUND.length());
|
|
||||||
try (OutputStream outputStream = exchange.getResponseBody()) {
|
|
||||||
outputStream.write(NOT_FOUND.getBytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 665 B |
Binary file not shown.
Before Width: | Height: | Size: 628 B |
@ -1,16 +0,0 @@
|
|||||||
html {
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: -moz-scrollbars-vertical;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*:before,
|
|
||||||
*:after {
|
|
||||||
box-sizing: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
<!-- HTML for static distribution bundle build -->
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Swagger UI</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css"/>
|
|
||||||
<link rel="stylesheet" type="text/css" href="index.css"/>
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32"/>
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="swagger-ui"></div>
|
|
||||||
<script src="./swagger-ui-bundle.js" charset="UTF-8"></script>
|
|
||||||
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"></script>
|
|
||||||
<script src="./swagger-initializer.js" charset="UTF-8"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,80 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en-US">
|
|
||||||
<head>
|
|
||||||
<title>Swagger UI: OAuth2 Redirect</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
function run () {
|
|
||||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
|
||||||
var sentState = oauth2.state;
|
|
||||||
var redirectUrl = oauth2.redirectUrl;
|
|
||||||
var isValid, qp, arr;
|
|
||||||
|
|
||||||
if (/code|token|error/.test(window.location.hash)) {
|
|
||||||
qp = window.location.hash.substring(1);
|
|
||||||
} else {
|
|
||||||
qp = location.search.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
arr = qp.split("&");
|
|
||||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
|
|
||||||
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
|
||||||
function (key, value) {
|
|
||||||
return key === "" ? value : decodeURIComponent(value);
|
|
||||||
}
|
|
||||||
) : {};
|
|
||||||
|
|
||||||
isValid = qp.state === sentState;
|
|
||||||
|
|
||||||
if ((
|
|
||||||
oauth2.auth.schema.get("flow") === "accessCode" ||
|
|
||||||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
|
||||||
oauth2.auth.schema.get("flow") === "authorization_code"
|
|
||||||
) && !oauth2.auth.code) {
|
|
||||||
if (!isValid) {
|
|
||||||
oauth2.errCb({
|
|
||||||
authId: oauth2.auth.name,
|
|
||||||
source: "auth",
|
|
||||||
level: "warning",
|
|
||||||
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qp.code) {
|
|
||||||
delete oauth2.state;
|
|
||||||
oauth2.auth.code = qp.code;
|
|
||||||
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
|
||||||
} else {
|
|
||||||
let oauthErrorMsg;
|
|
||||||
if (qp.error) {
|
|
||||||
oauthErrorMsg = "["+qp.error+"]: " +
|
|
||||||
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
|
||||||
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
oauth2.errCb({
|
|
||||||
authId: oauth2.auth.name,
|
|
||||||
source: "auth",
|
|
||||||
level: "error",
|
|
||||||
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
|
||||||
}
|
|
||||||
window.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.readyState !== 'loading') {
|
|
||||||
run();
|
|
||||||
} else {
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
run();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,20 +0,0 @@
|
|||||||
window.onload = function() {
|
|
||||||
//<editor-fold desc="Changeable Configuration Block">
|
|
||||||
|
|
||||||
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
|
|
||||||
window.ui = SwaggerUIBundle({
|
|
||||||
url: "/api/v1/openapi.json",
|
|
||||||
dom_id: '#swagger-ui',
|
|
||||||
deepLinking: true,
|
|
||||||
presets: [
|
|
||||||
SwaggerUIBundle.presets.apis,
|
|
||||||
SwaggerUIStandalonePreset
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
SwaggerUIBundle.plugins.DownloadUrl
|
|
||||||
],
|
|
||||||
layout: "StandaloneLayout"
|
|
||||||
});
|
|
||||||
|
|
||||||
//</editor-fold>
|
|
||||||
};
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,15 +0,0 @@
|
|||||||
<?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{15}: %msg %xEx%n)</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<root level="TRACE">
|
|
||||||
<appender-ref ref="CONSOLE_APPENDER"/>
|
|
||||||
</root>
|
|
||||||
|
|
||||||
<logger name="com.msopentech.thali.toronionproxy.OnionProxyManagerEventHandler" level="INFO"/>
|
|
||||||
|
|
||||||
</configuration>
|
|
@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration>
|
|
||||||
<!--
|
|
||||||
The :daemon & :cli jars contain their own logback.xml config files, which causes chatty logback startup.
|
|
||||||
To avoid chatty logback msgs during its configuration, pass logback.configurationFile as a system property:
|
|
||||||
-Dlogback.configurationFile=apitest/build/resources/main/logback.xml
|
|
||||||
The gradle build file takes care of adding this system property to the bisq-apitest script.
|
|
||||||
-->
|
|
||||||
<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="INFO">
|
|
||||||
<appender-ref ref="CONSOLE_APPENDER"/>
|
|
||||||
</root>
|
|
||||||
|
|
||||||
<logger name="io.grpc.netty" level="WARN"/>
|
|
||||||
</configuration>
|
|
@ -11,7 +11,6 @@ include 'pricenode'
|
|||||||
include 'relay'
|
include 'relay'
|
||||||
include 'seednode'
|
include 'seednode'
|
||||||
include 'statsnode'
|
include 'statsnode'
|
||||||
include 'daonode'
|
|
||||||
include 'apitest'
|
include 'apitest'
|
||||||
|
|
||||||
rootProject.name = 'bisq'
|
rootProject.name = 'bisq'
|
||||||
|
Loading…
Reference in New Issue
Block a user