From ed997af04306d014adb35c0b46158de48b335e17 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Thu, 29 Jul 2021 08:47:45 +0100 Subject: [PATCH] Limit order size to a minimum of 2 DOGE. The "dust" threshold is around 1 DOGE - meaning orders below this size cannot be refunded or redeemed. The simplest solution is to prevent orders of this size being placed to begin with. --- src/main/java/org/qortal/api/ApiError.java | 7 +++++-- .../api/resource/CrossChainTradeBotResource.java | 11 +++++++---- src/main/java/org/qortal/crosschain/Bitcoiny.java | 5 +++++ src/main/java/org/qortal/crosschain/Dogecoin.java | 7 +++++++ .../java/org/qortal/crosschain/ForeignBlockchain.java | 2 ++ src/main/resources/i18n/ApiError_en.properties | 2 ++ 6 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/qortal/api/ApiError.java b/src/main/java/org/qortal/api/ApiError.java index dd7fc4b0..a5c10c1a 100644 --- a/src/main/java/org/qortal/api/ApiError.java +++ b/src/main/java/org/qortal/api/ApiError.java @@ -129,7 +129,10 @@ public enum ApiError { // Foreign blockchain FOREIGN_BLOCKCHAIN_NETWORK_ISSUE(1201, 500), FOREIGN_BLOCKCHAIN_BALANCE_ISSUE(1202, 402), - FOREIGN_BLOCKCHAIN_TOO_SOON(1203, 408); + FOREIGN_BLOCKCHAIN_TOO_SOON(1203, 408), + + // Trade portal + ORDER_SIZE_TOO_SMALL(1300, 402); private static final Map map = stream(ApiError.values()).collect(toMap(apiError -> apiError.code, apiError -> apiError)); @@ -157,4 +160,4 @@ public enum ApiError { return this.status; } -} \ No newline at end of file +} diff --git a/src/main/java/org/qortal/api/resource/CrossChainTradeBotResource.java b/src/main/java/org/qortal/api/resource/CrossChainTradeBotResource.java index cd8766ca..c3d7e397 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainTradeBotResource.java +++ b/src/main/java/org/qortal/api/resource/CrossChainTradeBotResource.java @@ -107,7 +107,7 @@ public class CrossChainTradeBotResource { ) } ) - @ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.INVALID_CRITERIA, ApiError.INSUFFICIENT_BALANCE, ApiError.REPOSITORY_ISSUE}) + @ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.INVALID_CRITERIA, ApiError.INSUFFICIENT_BALANCE, ApiError.REPOSITORY_ISSUE, ApiError.ORDER_SIZE_TOO_SMALL}) @SuppressWarnings("deprecation") public String tradeBotCreator(TradeBotCreateRequest tradeBotCreateRequest) { Security.checkApiCallAllowed(request); @@ -128,10 +128,13 @@ public class CrossChainTradeBotResource { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); if (tradeBotCreateRequest.foreignAmount == null || tradeBotCreateRequest.foreignAmount <= 0) - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ORDER_SIZE_TOO_SMALL); + + if (tradeBotCreateRequest.foreignAmount < foreignBlockchain.getMinimumOrderAmount()) + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ORDER_SIZE_TOO_SMALL); if (tradeBotCreateRequest.qortAmount <= 0 || tradeBotCreateRequest.fundingQortAmount <= 0) - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ORDER_SIZE_TOO_SMALL); try (final Repository repository = RepositoryManager.getRepository()) { // Do some simple checking first @@ -283,4 +286,4 @@ public class CrossChainTradeBotResource { return atData; } -} \ No newline at end of file +} diff --git a/src/main/java/org/qortal/crosschain/Bitcoiny.java b/src/main/java/org/qortal/crosschain/Bitcoiny.java index fc98f959..5aed404c 100644 --- a/src/main/java/org/qortal/crosschain/Bitcoiny.java +++ b/src/main/java/org/qortal/crosschain/Bitcoiny.java @@ -169,6 +169,11 @@ public abstract class Bitcoiny implements ForeignBlockchain { return this.bitcoinjContext.getFeePerKb(); } + /** Returns minimum order size in sats. To be overridden for coins that need to restrict order size. */ + public long getMinimumOrderAmount() { + return 0L; + } + /** * Returns fixed P2SH spending fee, in sats per 1000bytes, optionally for historic timestamp. * diff --git a/src/main/java/org/qortal/crosschain/Dogecoin.java b/src/main/java/org/qortal/crosschain/Dogecoin.java index 8fdc6874..da24d113 100644 --- a/src/main/java/org/qortal/crosschain/Dogecoin.java +++ b/src/main/java/org/qortal/crosschain/Dogecoin.java @@ -21,6 +21,8 @@ public class Dogecoin extends Bitcoiny { private static final Coin DEFAULT_FEE_PER_KB = Coin.valueOf(500000000); // 5 DOGE per 1000 bytes + private static final long MINIMUM_ORDER_AMOUNT = 200000000L; // 2 DOGE minimum order. The RPC dust threshold is around 1 DOGE + // Temporary values until a dynamic fee system is written. private static final long MAINNET_FEE = 110000000L; private static final long NON_MAINNET_FEE = 10000L; // TODO: calibrate this @@ -150,6 +152,11 @@ public class Dogecoin extends Bitcoiny { return DEFAULT_FEE_PER_KB; } + @Override + public long getMinimumOrderAmount() { + return MINIMUM_ORDER_AMOUNT; + } + /** * Returns estimated DOGE fee, in sats per 1000bytes, optionally for historic timestamp. * diff --git a/src/main/java/org/qortal/crosschain/ForeignBlockchain.java b/src/main/java/org/qortal/crosschain/ForeignBlockchain.java index 0a71e9d9..fe64ab83 100644 --- a/src/main/java/org/qortal/crosschain/ForeignBlockchain.java +++ b/src/main/java/org/qortal/crosschain/ForeignBlockchain.java @@ -6,4 +6,6 @@ public interface ForeignBlockchain { public boolean isValidWalletKey(String walletKey); + public long getMinimumOrderAmount(); + } diff --git a/src/main/resources/i18n/ApiError_en.properties b/src/main/resources/i18n/ApiError_en.properties index 5acf2373..4010b2fb 100644 --- a/src/main/resources/i18n/ApiError_en.properties +++ b/src/main/resources/i18n/ApiError_en.properties @@ -64,3 +64,5 @@ TRANSACTION_UNKNOWN = transaction unknown TRANSFORMATION_ERROR = could not transform JSON into transaction UNAUTHORIZED = API call unauthorized + +ORDER_SIZE_TOO_SMALL = order size too small