diff --git a/src/main/java/org/qortal/api/resource/CrossChainHtlcResource.java b/src/main/java/org/qortal/api/resource/CrossChainHtlcResource.java index 05921ab1..5c77f212 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainHtlcResource.java +++ b/src/main/java/org/qortal/api/resource/CrossChainHtlcResource.java @@ -7,9 +7,11 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; +import java.io.IOException; import java.math.BigDecimal; import java.util.List; import java.util.Objects; +import java.util.concurrent.locks.ReentrantLock; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.*; @@ -22,6 +24,7 @@ import org.bitcoinj.core.*; import org.bitcoinj.script.Script; import org.qortal.api.*; import org.qortal.api.model.CrossChainBitcoinyHTLCStatus; +import org.qortal.controller.Controller; import org.qortal.crosschain.*; import org.qortal.crypto.Crypto; import org.qortal.data.at.ATData; @@ -662,6 +665,48 @@ public class CrossChainHtlcResource { return false; } + @POST + @Path("/importarchivedtrades") + @Operation( + summary = "Imports archived trades from TradeBotStatesArchive.json", + description = "This can be used to recover trades that exist in the archive only, which may be needed if a
" + + "problem occurred during the proof-of-work computation stage of a buy request.", + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "boolean")) + ) + } + ) + @ApiErrors({ApiError.REPOSITORY_ISSUE}) + @SecurityRequirement(name = "apiKey") + public boolean importArchivedTrades(@HeaderParam(Security.API_KEY_HEADER) String apiKey) { + Security.checkApiCallAllowed(request); + + try (final Repository repository = RepositoryManager.getRepository()) { + ReentrantLock blockchainLock = Controller.getInstance().getBlockchainLock(); + + blockchainLock.lockInterruptibly(); + + try { + repository.importDataFromFile("qortal-backup/TradeBotStatesArchive.json"); + repository.saveChanges(); + + return true; + + } catch (IOException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA, e); + + } finally { + blockchainLock.unlock(); + } + } catch (InterruptedException e) { + // We couldn't lock blockchain to perform import + return false; + } catch (DataException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); + } + } + private long calcFeeTimestamp(int lockTimeA, int tradeTimeout) { return (lockTimeA - tradeTimeout * 60) * 1000L; }