mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 15:10:44 +01:00
Use Bisq2 rest infrastructure with swagger support
This commit is contained in:
parent
dd4be1cc90
commit
44ae4017d1
31 changed files with 11799 additions and 78 deletions
14
build.gradle
14
build.gradle
|
@ -54,6 +54,7 @@ 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'
|
||||||
|
@ -76,6 +77,7 @@ 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
|
||||||
}
|
}
|
||||||
|
@ -691,7 +693,7 @@ configure(project(':seednode')) {
|
||||||
configure(project(':daonode')) {
|
configure(project(':daonode')) {
|
||||||
apply plugin: 'com.github.johnrengelman.shadow'
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
|
|
||||||
mainClassName = 'bisq.daonode.DaoNodeMain'
|
mainClassName = 'bisq.daoNode.DaoNodeRestApiApplication'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':common')
|
implementation project(':common')
|
||||||
|
@ -709,11 +711,17 @@ configure(project(':daonode')) {
|
||||||
implementation "ch.qos.logback:logback-core:$logbackVersion"
|
implementation "ch.qos.logback:logback-core:$logbackVersion"
|
||||||
implementation "org.slf4j:slf4j-api:$slf4jVersion"
|
implementation "org.slf4j:slf4j-api:$slf4jVersion"
|
||||||
|
|
||||||
implementation("com.fasterxml.jackson.core:jackson-core:$jacksonVersion")
|
/* implementation("com.fasterxml.jackson.core:jackson-core:$jacksonVersion")
|
||||||
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
|
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
|
||||||
implementation("com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion")
|
implementation("com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion")
|
||||||
|
|
||||||
implementation "com.google.protobuf:protobuf-java-util:$protobufVersion"
|
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"
|
testImplementation "org.mockito:mockito-core:$mockitoVersion"
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode;
|
package bisq.daoNode;
|
||||||
|
|
||||||
import bisq.core.app.misc.AppSetup;
|
import bisq.core.app.misc.AppSetup;
|
||||||
import bisq.core.app.misc.AppSetupWithP2PAndDAO;
|
import bisq.core.app.misc.AppSetupWithP2PAndDAO;
|
||||||
|
@ -25,26 +25,23 @@ import bisq.core.user.Preferences;
|
||||||
|
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import bisq.daonode.service.DaoNodeService;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DaoNode {
|
public class DaoNode {
|
||||||
@Setter
|
@Setter
|
||||||
private Injector injector;
|
private Injector injector;
|
||||||
private AppSetup appSetup;
|
|
||||||
private DaoNodeService daoNodeService;
|
|
||||||
private GetInventoryRequestHandler getInventoryRequestHandler;
|
private GetInventoryRequestHandler getInventoryRequestHandler;
|
||||||
|
@Getter
|
||||||
|
private DaoStateService daoStateService;
|
||||||
|
|
||||||
public DaoNode() {
|
public DaoNode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startApplication(int restServerPort) {
|
public void startApplication() {
|
||||||
appSetup = injector.getInstance(AppSetupWithP2PAndDAO.class);
|
AppSetup appSetup = injector.getInstance(AppSetupWithP2PAndDAO.class);
|
||||||
|
|
||||||
// todo should run as full dao node when in production
|
// todo should run as full dao node when in production
|
||||||
injector.getInstance(Preferences.class).setUseFullModeDaoMonitor(false);
|
injector.getInstance(Preferences.class).setUseFullModeDaoMonitor(false);
|
||||||
|
@ -52,14 +49,13 @@ public class DaoNode {
|
||||||
appSetup.start();
|
appSetup.start();
|
||||||
|
|
||||||
getInventoryRequestHandler = injector.getInstance(GetInventoryRequestHandler.class);
|
getInventoryRequestHandler = injector.getInstance(GetInventoryRequestHandler.class);
|
||||||
DaoStateService daoStateService = injector.getInstance(DaoStateService.class);
|
daoStateService = injector.getInstance(DaoStateService.class);
|
||||||
|
|
||||||
daoNodeService = new DaoNodeService(daoStateService);
|
|
||||||
daoNodeService.start(restServerPort);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutDown() {
|
public void shutDown() {
|
||||||
|
if (getInventoryRequestHandler != null) {
|
||||||
getInventoryRequestHandler.shutDown();
|
getInventoryRequestHandler.shutDown();
|
||||||
daoNodeService.shutDown();
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode;
|
package bisq.daoNode;
|
||||||
|
|
||||||
|
|
||||||
import bisq.core.app.TorSetup;
|
import bisq.core.app.TorSetup;
|
||||||
|
@ -41,27 +41,20 @@ import bisq.common.handlers.ResultHandler;
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
import com.google.inject.name.Names;
|
import com.google.inject.name.Names;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
//todo not sure if the restart handling from seed nodes is required
|
//todo not sure if the restart handling from seed nodes is required
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DaoNodeMain extends ExecutableForAppWithP2p {
|
public class DaoNodeExecutable extends ExecutableForAppWithP2p {
|
||||||
private static final long CHECK_CONNECTION_LOSS_SEC = 30;
|
private static final long CHECK_CONNECTION_LOSS_SEC = 30;
|
||||||
private static final int DEFAULT_REST_SERVER_PORT = 8080;
|
|
||||||
private static final String VERSION = "1.8.4";
|
private static final String VERSION = "1.8.4";
|
||||||
|
@Getter
|
||||||
private DaoNode daoNode;
|
private final DaoNode daoNode = new DaoNode();
|
||||||
private Timer checkConnectionLossTime;
|
private Timer checkConnectionLossTime;
|
||||||
private int restServerPort = DEFAULT_REST_SERVER_PORT;
|
|
||||||
|
|
||||||
public DaoNodeMain() {
|
public DaoNodeExecutable() {
|
||||||
super("Bisq Daonode", "bisq-daonode", "bisq_daonode", VERSION);
|
super("Bisq Dao Node", "bisq-dao-node", "bisq_dao_node", VERSION);
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
System.out.println("DaoNode.VERSION: " + VERSION);
|
|
||||||
|
|
||||||
new DaoNodeMain().execute(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,7 +74,6 @@ public class DaoNodeMain extends ExecutableForAppWithP2p {
|
||||||
protected void launchApplication() {
|
protected void launchApplication() {
|
||||||
UserThread.execute(() -> {
|
UserThread.execute(() -> {
|
||||||
try {
|
try {
|
||||||
daoNode = new DaoNode();
|
|
||||||
onApplicationLaunched();
|
onApplicationLaunched();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -129,8 +121,7 @@ public class DaoNodeMain extends ExecutableForAppWithP2p {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//todo add program arg for port
|
daoNode.startApplication();
|
||||||
daoNode.startApplication(restServerPort);
|
|
||||||
|
|
||||||
injector.getInstance(P2PService.class).addP2PServiceListener(new P2PServiceListener() {
|
injector.getInstance(P2PService.class).addP2PServiceListener(new P2PServiceListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -163,7 +154,7 @@ public class DaoNodeMain extends ExecutableForAppWithP2p {
|
||||||
boolean preventPeriodicShutdownAtSeedNode = injector.getInstance(Key.get(boolean.class,
|
boolean preventPeriodicShutdownAtSeedNode = injector.getInstance(Key.get(boolean.class,
|
||||||
Names.named(Config.PREVENT_PERIODIC_SHUTDOWN_AT_SEED_NODE)));
|
Names.named(Config.PREVENT_PERIODIC_SHUTDOWN_AT_SEED_NODE)));
|
||||||
if (!preventPeriodicShutdownAtSeedNode) {
|
if (!preventPeriodicShutdownAtSeedNode) {
|
||||||
startShutDownInterval(DaoNodeMain.this);
|
startShutDownInterval(DaoNodeExecutable.this);
|
||||||
}
|
}
|
||||||
UserThread.runAfter(() -> setupConnectionLossCheck(), 60);
|
UserThread.runAfter(() -> setupConnectionLossCheck(), 60);
|
||||||
}
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* 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 java.net.URI;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import bisq.daoNode.endpoints.ProofOfBurnApi;
|
||||||
|
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 and rest service at BASE_URL 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 {
|
||||||
|
public static final String BASE_URL = "http://localhost:8082/api/v1";
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
DaoNodeRestApiApplication daoNodeRestApiApplication = new DaoNodeRestApiApplication(args);
|
||||||
|
daoNodeRestApiApplication
|
||||||
|
.register(CustomExceptionMapper.class)
|
||||||
|
.register(StatusException.StatusExceptionMapper.class)
|
||||||
|
.register(ProofOfBurnApi.class)
|
||||||
|
.register(SwaggerResolution.class);
|
||||||
|
|
||||||
|
daoNodeRestApiApplication.startServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final DaoNodeExecutable daoNodeExecutable;
|
||||||
|
private HttpServer httpServer;
|
||||||
|
|
||||||
|
public DaoNodeRestApiApplication(String[] args) {
|
||||||
|
daoNodeExecutable = new DaoNodeExecutable();
|
||||||
|
new Thread(() -> {
|
||||||
|
daoNodeExecutable.execute(args);
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startServer() throws Exception {
|
||||||
|
httpServer = JdkHttpServerFactory.createHttpServer(URI.create(BASE_URL), this);
|
||||||
|
httpServer.createContext("/doc", new StaticFileHandler("/doc/v1/"));
|
||||||
|
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(this::stopServer));
|
||||||
|
|
||||||
|
log.info("Server started at {}.", BASE_URL);
|
||||||
|
|
||||||
|
// block and wait shut down signal, like CTRL+C
|
||||||
|
Thread.currentThread().join();
|
||||||
|
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopServer() {
|
||||||
|
daoNodeExecutable.gracefulShutDown(() -> {
|
||||||
|
httpServer.stop(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
71
daonode/src/main/java/bisq/daoNode/SwaggerResolution.java
Normal file
71
daonode/src/main/java/bisq/daoNode/SwaggerResolution.java
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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.BASE_URL));
|
||||||
|
SwaggerConfiguration configuration = new SwaggerConfiguration().openAPI(api);
|
||||||
|
Reader reader = new Reader(configuration);
|
||||||
|
OpenAPI openAPI = reader.read(application.getClasses());
|
||||||
|
swaggerJson = Json.pretty(openAPI);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return swaggerJson;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,17 +15,22 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode.dto;
|
package bisq.daoNode.dto;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimal data required for Bisq 2 reputation use case.
|
* Minimal data required for Bisq 2 reputation use case.
|
||||||
* Need to be in sync with the Bisq 2 ProofOfBurnDto class.
|
* Need to be in sync with the Bisq 2 ProofOfBurnDto class.
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
|
@Schema(title = "ProofOfBurn")
|
||||||
public class ProofOfBurnDto {
|
public class ProofOfBurnDto {
|
||||||
private String txId;
|
private final String txId;
|
||||||
private final long burnedAmount;
|
private final long burnedAmount;
|
||||||
private final int blockHeight;
|
private final int blockHeight;
|
||||||
private final long time;
|
private final long time;
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* 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.state.model.blockchain.Tx;
|
||||||
|
|
||||||
|
import bisq.common.util.Hex;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
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.DaoNode;
|
||||||
|
import bisq.daoNode.DaoNodeRestApiApplication;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Path("/proof-of-burn")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Tag(name = "Proof of burn API")
|
||||||
|
public class ProofOfBurnApi {
|
||||||
|
public static final String DESC_BLOCK_HEIGHT = "The block height from which we request the proof of burn data";
|
||||||
|
private final DaoNode daoNode;
|
||||||
|
|
||||||
|
public ProofOfBurnApi(@Context Application application) {
|
||||||
|
daoNode = ((DaoNodeRestApiApplication) application).getDaoNodeExecutable().getDaoNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 blockHeight) {
|
||||||
|
return checkNotNull(daoNode.getDaoStateService()).getProofOfBurnTxs().stream()
|
||||||
|
.filter(tx -> tx.getBlockHeight() >= blockHeight)
|
||||||
|
.map(tx -> new ProofOfBurnDto(tx.getId(),
|
||||||
|
tx.getBurntBsq(),
|
||||||
|
tx.getBlockHeight(),
|
||||||
|
tx.getTime(),
|
||||||
|
getHash(tx)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
// We strip out the version bytes
|
||||||
|
private String getHash(Tx tx) {
|
||||||
|
byte[] opReturnData = tx.getLastTxOutput().getOpReturnData();
|
||||||
|
if (opReturnData == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return Hex.encode(Arrays.copyOfRange(opReturnData, 2, 22));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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.getMessage(), exception);
|
||||||
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||||
|
.entity(new ErrorMessage(exception.getMessage()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
30
daonode/src/main/java/bisq/daoNode/error/ErrorMessage.java
Normal file
30
daonode/src/main/java/bisq/daoNode/error/ErrorMessage.java
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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 String error;
|
||||||
|
|
||||||
|
public ErrorMessage(String error) {
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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) {
|
||||||
|
return Response.status(exception.getHttpStatus())
|
||||||
|
.entity(new ErrorMessage(exception.getMessage()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
111
daonode/src/main/java/bisq/daoNode/util/StaticFileHandler.java
Normal file
111
daonode/src/main/java/bisq/daoNode/util/StaticFileHandler.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.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.NonNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
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
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
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
|
||||||
|
@Setter
|
||||||
|
@NonNull
|
||||||
|
protected String rootContext;
|
||||||
|
ClassLoader classLoader = getClass().getClassLoader();
|
||||||
|
|
||||||
|
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 = classLoader.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);
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode.service;
|
package bisq.daonodeOld.service;
|
||||||
|
|
||||||
import bisq.core.dao.state.DaoStateService;
|
import bisq.core.dao.state.DaoStateService;
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import bisq.daonode.web.WebServer;
|
import bisq.daonodeOld.web.WebServer;
|
||||||
import bisq.daonode.web.jdk.JdkServer;
|
import bisq.daonodeOld.web.jdk.JdkServer;
|
||||||
|
|
||||||
// Todo We should limit usage to localhost as its not intended at that stage to be used
|
// Todo We should limit usage to localhost as its not intended at that stage to be used
|
||||||
// as a public API, but rather be used by Bisq 2 bridge clients or BSQ explorer nodes,
|
// as a public API, but rather be used by Bisq 2 bridge clients or BSQ explorer nodes,
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode.web;
|
package bisq.daonodeOld.web;
|
||||||
|
|
||||||
public interface WebServer {
|
public interface WebServer {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode.web.jdk;
|
package bisq.daonodeOld.web.jdk;
|
||||||
|
|
||||||
import bisq.core.dao.state.DaoStateService;
|
import bisq.core.dao.state.DaoStateService;
|
||||||
|
|
||||||
|
@ -29,12 +29,12 @@ import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import static bisq.daonode.web.jdk.handler.ResourcePathElement.DAONODE;
|
import static bisq.daonodeOld.web.jdk.handler.ResourcePathElement.DAONODE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import bisq.daonode.web.WebServer;
|
import bisq.daonodeOld.web.WebServer;
|
||||||
import bisq.daonode.web.jdk.handler.RestHandler;
|
import bisq.daonodeOld.web.jdk.handler.RestHandler;
|
||||||
import com.sun.net.httpserver.HttpContext;
|
import com.sun.net.httpserver.HttpContext;
|
||||||
import com.sun.net.httpserver.HttpHandler;
|
import com.sun.net.httpserver.HttpHandler;
|
||||||
import com.sun.net.httpserver.HttpServer;
|
import com.sun.net.httpserver.HttpServer;
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode.web.jdk.handler;
|
package bisq.daonodeOld.web.jdk.handler;
|
||||||
|
|
||||||
import bisq.core.dao.state.DaoStateService;
|
import bisq.core.dao.state.DaoStateService;
|
||||||
import bisq.core.dao.state.model.blockchain.Tx;
|
import bisq.core.dao.state.model.blockchain.Tx;
|
||||||
|
@ -30,15 +30,14 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import static bisq.daonode.web.jdk.handler.HandlerUtil.sendResponse;
|
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.toJson;
|
||||||
import static bisq.daonode.web.jdk.handler.HandlerUtil.toJson;
|
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.wrapErrorResponse;
|
||||||
import static bisq.daonode.web.jdk.handler.HandlerUtil.wrapErrorResponse;
|
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.wrapResponse;
|
||||||
import static bisq.daonode.web.jdk.handler.HandlerUtil.wrapResponse;
|
import static bisq.daonodeOld.web.jdk.handler.ResourcePathElement.BLOCKHEIGHT;
|
||||||
import static bisq.daonode.web.jdk.handler.ResourcePathElement.BLOCKHEIGHT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import bisq.daonode.dto.ProofOfBurnDto;
|
import bisq.daoNode.dto.ProofOfBurnDto;
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import com.sun.net.httpserver.HttpHandler;
|
import com.sun.net.httpserver.HttpHandler;
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ import com.sun.net.httpserver.HttpHandler;
|
||||||
* Example: http://localhost:8080/daonode/proofofburn/blockheight/731270
|
* Example: http://localhost:8080/daonode/proofofburn/blockheight/731270
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class GetProofOfBurnHandler implements HttpHandler {
|
public class GetProofOfBurnHandler implements HttpHandler {
|
||||||
|
|
||||||
private final DaoStateService daoStateService;
|
private final DaoStateService daoStateService;
|
||||||
private final RequestSpec requestSpec;
|
private final RequestSpec requestSpec;
|
||||||
|
@ -73,22 +72,22 @@ class GetProofOfBurnHandler implements HttpHandler {
|
||||||
try {
|
try {
|
||||||
if (daoStateService == null) {
|
if (daoStateService == null) {
|
||||||
log.warn("DAO Node daoStateService is null; OK during web server dev/test.");
|
log.warn("DAO Node daoStateService is null; OK during web server dev/test.");
|
||||||
sendResponse(httpExchange, wrapResponse("[]"));
|
HandlerUtil.sendResponse(httpExchange, wrapResponse("[]"));
|
||||||
} else {
|
} else {
|
||||||
int blockHeight = requestSpec.getIntParam(BLOCKHEIGHT);
|
int blockHeight = requestSpec.getIntParam(BLOCKHEIGHT);
|
||||||
log.info("Requesting POB for blockheight {}.", blockHeight);
|
log.info("Requesting POB for blockheight {}.", blockHeight);
|
||||||
List<ProofOfBurnDto> data = getProofOfBurnDtoList(blockHeight);
|
List<ProofOfBurnDto> list = getProofOfBurnDtoList(blockHeight);
|
||||||
if (data != null) {
|
if (list != null) {
|
||||||
sendResponse(httpExchange, wrapResponse(toJson(data)));
|
HandlerUtil.sendResponse(httpExchange, toJson(list));
|
||||||
} else {
|
} else {
|
||||||
log.error("DAO Node Proof of Burn data for blockHeight {} is null.", blockHeight);
|
log.error("DAO Node Proof of Burn data for blockHeight {} is null.", blockHeight);
|
||||||
sendResponse(500,
|
HandlerUtil.sendResponse(500,
|
||||||
httpExchange,
|
httpExchange,
|
||||||
wrapErrorResponse(toJson("DAO Node proof of burn data is null.")));
|
wrapErrorResponse(toJson("DAO Node proof of burn data is null.")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
sendResponse(500,
|
HandlerUtil.sendResponse(500,
|
||||||
httpExchange,
|
httpExchange,
|
||||||
wrapErrorResponse(toJson(ex.getMessage())));
|
wrapErrorResponse(toJson(ex.getMessage())));
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode.web.jdk.handler;
|
package bisq.daonodeOld.web.jdk.handler;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
@ -31,17 +31,17 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
|
||||||
class HandlerUtil {
|
public class HandlerUtil {
|
||||||
|
|
||||||
static void setDefaultResponseHeaders(HttpExchange httpExchange) {
|
public static void setDefaultResponseHeaders(HttpExchange httpExchange) {
|
||||||
httpExchange.getResponseHeaders().set("Content-Type", "application/json; charset=utf-8");
|
httpExchange.getResponseHeaders().set("Content-Type", "application/json; charset=utf-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sendResponse(HttpExchange httpExchange, String response) throws IOException {
|
public static void sendResponse(HttpExchange httpExchange, String response) throws IOException {
|
||||||
sendResponse(200, httpExchange, response);
|
sendResponse(200, httpExchange, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sendResponse(int status, HttpExchange httpExchange, String response) throws IOException {
|
public static void sendResponse(int status, HttpExchange httpExchange, String response) throws IOException {
|
||||||
setDefaultResponseHeaders(httpExchange);
|
setDefaultResponseHeaders(httpExchange);
|
||||||
|
|
||||||
byte[] responseBytes = response.getBytes(UTF_8);
|
byte[] responseBytes = response.getBytes(UTF_8);
|
||||||
|
@ -52,17 +52,17 @@ class HandlerUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO make as function toWhat?
|
// TODO make as function toWhat?
|
||||||
static String wrapResponse(String jsonData) {
|
public static String wrapResponse(String jsonData) {
|
||||||
return format("{\"data\":%s}", jsonData);
|
return format("{\"data\":%s}", jsonData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO make as function toErrorWhat?
|
// TODO make as function toErrorWhat?
|
||||||
static String wrapErrorResponse(String jsonError) {
|
public static String wrapErrorResponse(String jsonError) {
|
||||||
return format("{\"error\":%s}", jsonError);
|
return format("{\"error\":%s}", jsonError);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
static String toJson(Object object) {
|
public static String toJson(Object object) {
|
||||||
return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(object);
|
return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode.web.jdk.handler;
|
package bisq.daonodeOld.web.jdk.handler;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
@ -52,7 +52,7 @@ import com.sun.net.httpserver.HttpExchange;
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class RequestSpec {
|
public class RequestSpec {
|
||||||
|
|
||||||
private final HttpExchange httpExchange;
|
private final HttpExchange httpExchange;
|
||||||
private final String method;
|
private final String method;
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode.web.jdk.handler;
|
package bisq.daonodeOld.web.jdk.handler;
|
||||||
|
|
||||||
public class ResourcePathElement {
|
public class ResourcePathElement {
|
||||||
public static String DAONODE = "daonode";
|
public static String DAONODE = "daonode";
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package bisq.daonode.web.jdk.handler;
|
package bisq.daonodeOld.web.jdk.handler;
|
||||||
|
|
||||||
import bisq.core.dao.state.DaoStateService;
|
import bisq.core.dao.state.DaoStateService;
|
||||||
|
|
||||||
|
@ -23,10 +23,10 @@ import java.io.IOException;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import static bisq.daonode.web.jdk.handler.HandlerUtil.sendResponse;
|
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.sendResponse;
|
||||||
import static bisq.daonode.web.jdk.handler.HandlerUtil.toJson;
|
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.toJson;
|
||||||
import static bisq.daonode.web.jdk.handler.HandlerUtil.wrapErrorResponse;
|
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.wrapErrorResponse;
|
||||||
import static bisq.daonode.web.jdk.handler.ResourcePathElement.PROOFOFBURN;
|
import static bisq.daonodeOld.web.jdk.handler.ResourcePathElement.PROOFOFBURN;
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
|
BIN
daonode/src/main/resources/doc/v1/favicon-16x16.png
Normal file
BIN
daonode/src/main/resources/doc/v1/favicon-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 665 B |
BIN
daonode/src/main/resources/doc/v1/favicon-32x32.png
Normal file
BIN
daonode/src/main/resources/doc/v1/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
16
daonode/src/main/resources/doc/v1/index.css
Normal file
16
daonode/src/main/resources/doc/v1/index.css
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
html {
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: -moz-scrollbars-vertical;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
19
daonode/src/main/resources/doc/v1/index.html
Normal file
19
daonode/src/main/resources/doc/v1/index.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<!-- 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>
|
80
daonode/src/main/resources/doc/v1/oauth2-redirect.html
Normal file
80
daonode/src/main/resources/doc/v1/oauth2-redirect.html
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
<!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>
|
20
daonode/src/main/resources/doc/v1/swagger-initializer.js
Normal file
20
daonode/src/main/resources/doc/v1/swagger-initializer.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
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>
|
||||||
|
};
|
3
daonode/src/main/resources/doc/v1/swagger-ui-bundle.js
Normal file
3
daonode/src/main/resources/doc/v1/swagger-ui-bundle.js
Normal file
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
11092
daonode/src/main/resources/doc/v1/swagger-ui.css
Normal file
11092
daonode/src/main/resources/doc/v1/swagger-ui.css
Normal file
File diff suppressed because it is too large
Load diff
2
daonode/src/main/resources/doc/v1/swagger-ui.js
Normal file
2
daonode/src/main/resources/doc/v1/swagger-ui.js
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue