Use Bisq2 rest infrastructure with swagger support

This commit is contained in:
chimp1984 2022-05-28 22:38:37 +02:00
parent dd4be1cc90
commit 44ae4017d1
No known key found for this signature in database
GPG key ID: 9801B4EC591F90E3
31 changed files with 11799 additions and 78 deletions

View file

@ -54,6 +54,7 @@ configure(subprojects) {
javafxVersion = '16'
javaxAnnotationVersion = '1.2'
jcsvVersion = '1.4.0'
jerseyVersion = '3.0.4'
jetbrainsAnnotationsVersion = '13.0'
jfoenixVersion = '9.0.10'
joptVersion = '5.0.4'
@ -76,6 +77,7 @@ configure(subprojects) {
slf4jVersion = '1.7.30'
sparkVersion = '2.5.2'
springBootVersion = '2.5.6'
swaggerVersion = '2.2.0'
os = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os
}
@ -691,7 +693,7 @@ configure(project(':seednode')) {
configure(project(':daonode')) {
apply plugin: 'com.github.johnrengelman.shadow'
mainClassName = 'bisq.daonode.DaoNodeMain'
mainClassName = 'bisq.daoNode.DaoNodeRestApiApplication'
dependencies {
implementation project(':common')
@ -709,11 +711,17 @@ configure(project(':daonode')) {
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-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 "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"

View file

@ -15,7 +15,7 @@
* 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.AppSetupWithP2PAndDAO;
@ -25,26 +25,23 @@ import bisq.core.user.Preferences;
import com.google.inject.Injector;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import bisq.daonode.service.DaoNodeService;
@Slf4j
public class DaoNode {
@Setter
private Injector injector;
private AppSetup appSetup;
private DaoNodeService daoNodeService;
private GetInventoryRequestHandler getInventoryRequestHandler;
@Getter
private DaoStateService daoStateService;
public DaoNode() {
}
public void startApplication(int restServerPort) {
appSetup = injector.getInstance(AppSetupWithP2PAndDAO.class);
public void startApplication() {
AppSetup appSetup = injector.getInstance(AppSetupWithP2PAndDAO.class);
// todo should run as full dao node when in production
injector.getInstance(Preferences.class).setUseFullModeDaoMonitor(false);
@ -52,14 +49,13 @@ public class DaoNode {
appSetup.start();
getInventoryRequestHandler = injector.getInstance(GetInventoryRequestHandler.class);
DaoStateService daoStateService = injector.getInstance(DaoStateService.class);
daoNodeService = new DaoNodeService(daoStateService);
daoNodeService.start(restServerPort);
daoStateService = injector.getInstance(DaoStateService.class);
}
public void shutDown() {
if (getInventoryRequestHandler != null) {
getInventoryRequestHandler.shutDown();
daoNodeService.shutDown();
}
}
}

View file

@ -15,7 +15,7 @@
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode;
package bisq.daoNode;
import bisq.core.app.TorSetup;
@ -41,27 +41,20 @@ 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 DaoNodeMain extends ExecutableForAppWithP2p {
public class DaoNodeExecutable extends ExecutableForAppWithP2p {
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 DaoNode daoNode;
@Getter
private final DaoNode daoNode = new DaoNode();
private Timer checkConnectionLossTime;
private int restServerPort = DEFAULT_REST_SERVER_PORT;
public DaoNodeMain() {
super("Bisq Daonode", "bisq-daonode", "bisq_daonode", VERSION);
}
public static void main(String[] args) {
System.out.println("DaoNode.VERSION: " + VERSION);
new DaoNodeMain().execute(args);
public DaoNodeExecutable() {
super("Bisq Dao Node", "bisq-dao-node", "bisq_dao_node", VERSION);
}
@Override
@ -81,7 +74,6 @@ public class DaoNodeMain extends ExecutableForAppWithP2p {
protected void launchApplication() {
UserThread.execute(() -> {
try {
daoNode = new DaoNode();
onApplicationLaunched();
} catch (Exception e) {
e.printStackTrace();
@ -129,8 +121,7 @@ public class DaoNodeMain extends ExecutableForAppWithP2p {
}
});
//todo add program arg for port
daoNode.startApplication(restServerPort);
daoNode.startApplication();
injector.getInstance(P2PService.class).addP2PServiceListener(new P2PServiceListener() {
@Override
@ -163,7 +154,7 @@ public class DaoNodeMain extends ExecutableForAppWithP2p {
boolean preventPeriodicShutdownAtSeedNode = injector.getInstance(Key.get(boolean.class,
Names.named(Config.PREVENT_PERIODIC_SHUTDOWN_AT_SEED_NODE)));
if (!preventPeriodicShutdownAtSeedNode) {
startShutDownInterval(DaoNodeMain.this);
startShutDownInterval(DaoNodeExecutable.this);
}
UserThread.runAfter(() -> setupConnectionLossCheck(), 60);
}

View file

@ -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);
});
}
}

View 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;
}
}

View file

@ -15,17 +15,22 @@
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.dto;
package bisq.daoNode.dto;
import lombok.Getter;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* Minimal data required for Bisq 2 reputation use case.
* Need to be in sync with the Bisq 2 ProofOfBurnDto class.
*/
@Getter
@Schema(title = "ProofOfBurn")
public class ProofOfBurnDto {
private String txId;
private final String txId;
private final long burnedAmount;
private final int blockHeight;
private final long time;

View file

@ -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));
}
}

View file

@ -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();
}
}

View 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;
}
}

View file

@ -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();
}
}
}

View 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());
}
}
}

View file

@ -15,7 +15,7 @@
* 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;
@ -23,8 +23,8 @@ import lombok.extern.slf4j.Slf4j;
import bisq.daonode.web.WebServer;
import bisq.daonode.web.jdk.JdkServer;
import bisq.daonodeOld.web.WebServer;
import bisq.daonodeOld.web.jdk.JdkServer;
// 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,

View file

@ -15,7 +15,7 @@
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.daonode.web;
package bisq.daonodeOld.web;
public interface WebServer {

View file

@ -15,7 +15,7 @@
* 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;
@ -29,12 +29,12 @@ import java.util.concurrent.Executor;
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.daonode.web.jdk.handler.RestHandler;
import bisq.daonodeOld.web.WebServer;
import bisq.daonodeOld.web.jdk.handler.RestHandler;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

View file

@ -15,7 +15,7 @@
* 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.model.blockchain.Tx;
@ -30,15 +30,14 @@ import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import static bisq.daonode.web.jdk.handler.HandlerUtil.sendResponse;
import static bisq.daonode.web.jdk.handler.HandlerUtil.toJson;
import static bisq.daonode.web.jdk.handler.HandlerUtil.wrapErrorResponse;
import static bisq.daonode.web.jdk.handler.HandlerUtil.wrapResponse;
import static bisq.daonode.web.jdk.handler.ResourcePathElement.BLOCKHEIGHT;
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.toJson;
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.wrapErrorResponse;
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.wrapResponse;
import static bisq.daonodeOld.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.HttpHandler;
@ -50,7 +49,7 @@ import com.sun.net.httpserver.HttpHandler;
* Example: http://localhost:8080/daonode/proofofburn/blockheight/731270
*/
@Slf4j
class GetProofOfBurnHandler implements HttpHandler {
public class GetProofOfBurnHandler implements HttpHandler {
private final DaoStateService daoStateService;
private final RequestSpec requestSpec;
@ -73,22 +72,22 @@ class GetProofOfBurnHandler implements HttpHandler {
try {
if (daoStateService == null) {
log.warn("DAO Node daoStateService is null; OK during web server dev/test.");
sendResponse(httpExchange, wrapResponse("[]"));
HandlerUtil.sendResponse(httpExchange, wrapResponse("[]"));
} else {
int blockHeight = requestSpec.getIntParam(BLOCKHEIGHT);
log.info("Requesting POB for blockheight {}.", blockHeight);
List<ProofOfBurnDto> data = getProofOfBurnDtoList(blockHeight);
if (data != null) {
sendResponse(httpExchange, wrapResponse(toJson(data)));
List<ProofOfBurnDto> list = getProofOfBurnDtoList(blockHeight);
if (list != null) {
HandlerUtil.sendResponse(httpExchange, toJson(list));
} else {
log.error("DAO Node Proof of Burn data for blockHeight {} is null.", blockHeight);
sendResponse(500,
HandlerUtil.sendResponse(500,
httpExchange,
wrapErrorResponse(toJson("DAO Node proof of burn data is null.")));
}
}
} catch (RuntimeException ex) {
sendResponse(500,
HandlerUtil.sendResponse(500,
httpExchange,
wrapErrorResponse(toJson(ex.getMessage())));
}

View file

@ -15,7 +15,7 @@
* 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;
@ -31,17 +31,17 @@ import static java.nio.charset.StandardCharsets.UTF_8;
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");
}
static void sendResponse(HttpExchange httpExchange, String response) throws IOException {
public static void sendResponse(HttpExchange httpExchange, String response) throws IOException {
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);
byte[] responseBytes = response.getBytes(UTF_8);
@ -52,17 +52,17 @@ class HandlerUtil {
}
// TODO make as function toWhat?
static String wrapResponse(String jsonData) {
public static String wrapResponse(String jsonData) {
return format("{\"data\":%s}", jsonData);
}
// TODO make as function toErrorWhat?
static String wrapErrorResponse(String jsonError) {
public static String wrapErrorResponse(String jsonError) {
return format("{\"error\":%s}", jsonError);
}
@SneakyThrows
static String toJson(Object object) {
public static String toJson(Object object) {
return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(object);
}
}

View file

@ -15,7 +15,7 @@
* 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.URISyntaxException;
@ -52,7 +52,7 @@ import com.sun.net.httpserver.HttpExchange;
*/
@Getter
@Slf4j
class RequestSpec {
public class RequestSpec {
private final HttpExchange httpExchange;
private final String method;

View file

@ -15,7 +15,7 @@
* 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 static String DAONODE = "daonode";

View file

@ -15,7 +15,7 @@
* 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;
@ -23,10 +23,10 @@ import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import static bisq.daonode.web.jdk.handler.HandlerUtil.sendResponse;
import static bisq.daonode.web.jdk.handler.HandlerUtil.toJson;
import static bisq.daonode.web.jdk.handler.HandlerUtil.wrapErrorResponse;
import static bisq.daonode.web.jdk.handler.ResourcePathElement.PROOFOFBURN;
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.sendResponse;
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.toJson;
import static bisq.daonodeOld.web.jdk.handler.HandlerUtil.wrapErrorResponse;
import static bisq.daonodeOld.web.jdk.handler.ResourcePathElement.PROOFOFBURN;
import static java.util.Objects.requireNonNull;

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

View 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;
}

View 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>

View 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>

View 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>
};

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