diff --git a/src/main/java/org/qortal/api/resource/CrossChainBitcoinResource.java b/src/main/java/org/qortal/api/resource/CrossChainBitcoinResource.java index 6f3b9f50..ff4aee02 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainBitcoinResource.java +++ b/src/main/java/org/qortal/api/resource/CrossChainBitcoinResource.java @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody; 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 org.bitcoinj.core.Coin; import org.bitcoinj.core.Transaction; import org.qortal.api.ApiError; import org.qortal.api.ApiErrors; @@ -265,4 +266,117 @@ public class CrossChainBitcoinResource { return CrossChainUtils.buildServerConfigurationInfo(Bitcoin.getInstance()); } + + @GET + @Path("/feekb") + @Operation( + summary = "Returns Bitcoin fee per Kb.", + description = "Returns Bitcoin fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getBitcoinFeePerKb() { + Bitcoin bitcoin = Bitcoin.getInstance(); + + return String.valueOf(bitcoin.getFeePerKb().value); + } + + @POST + @Path("/updatefeekb") + @Operation( + summary = "Sets Bitcoin fee per Kb.", + description = "Sets Bitcoin fee per Kb.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee per Kb", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setBitcoinFeePerKb(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + Bitcoin bitcoin = Bitcoin.getInstance(); + + try { + return CrossChainUtils.setFeePerKb(bitcoin, fee); + } catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } + + @GET + @Path("/feeceiling") + @Operation( + summary = "Returns Bitcoin fee per Kb.", + description = "Returns Bitcoin fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getBitcoinFeeCeiling() { + Bitcoin bitcoin = Bitcoin.getInstance(); + + return String.valueOf(bitcoin.getFeeCeiling()); + } + + @POST + @Path("/updatefeeceiling") + @Operation( + summary = "Sets Bitcoin fee ceiling.", + description = "Sets Bitcoin fee ceiling.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setBitcoinFeeCeiling(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + Bitcoin bitcoin = Bitcoin.getInstance(); + + try { + return CrossChainUtils.setFeeCeiling(bitcoin, fee); + } + catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } } diff --git a/src/main/java/org/qortal/api/resource/CrossChainDigibyteResource.java b/src/main/java/org/qortal/api/resource/CrossChainDigibyteResource.java index 898754d6..d78a4ed9 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainDigibyteResource.java +++ b/src/main/java/org/qortal/api/resource/CrossChainDigibyteResource.java @@ -265,4 +265,117 @@ public class CrossChainDigibyteResource { return CrossChainUtils.buildServerConfigurationInfo(Digibyte.getInstance()); } -} + + @GET + @Path("/feekb") + @Operation( + summary = "Returns Digibyte fee per Kb.", + description = "Returns Digibyte fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getDigibyteFeePerKb() { + Digibyte digibyte = Digibyte.getInstance(); + + return String.valueOf(digibyte.getFeePerKb().value); + } + + @POST + @Path("/updatefeekb") + @Operation( + summary = "Sets Digibyte fee per Kb.", + description = "Sets Digibyte fee per Kb.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee per Kb", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setDigibyteFeePerKb(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + Digibyte digibyte = Digibyte.getInstance(); + + try { + return CrossChainUtils.setFeePerKb(digibyte, fee); + } catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } + + @GET + @Path("/feeceiling") + @Operation( + summary = "Returns Digibyte fee per Kb.", + description = "Returns Digibyte fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getDigibyteFeeCeiling() { + Digibyte digibyte = Digibyte.getInstance(); + + return String.valueOf(digibyte.getFeeCeiling()); + } + + @POST + @Path("/updatefeeceiling") + @Operation( + summary = "Sets Digibyte fee ceiling.", + description = "Sets Digibyte fee ceiling.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setDigibyteFeeCeiling(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + Digibyte digibyte = Digibyte.getInstance(); + + try { + return CrossChainUtils.setFeeCeiling(digibyte, fee); + } + catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/qortal/api/resource/CrossChainDogecoinResource.java b/src/main/java/org/qortal/api/resource/CrossChainDogecoinResource.java index 1608c90e..8575a28d 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainDogecoinResource.java +++ b/src/main/java/org/qortal/api/resource/CrossChainDogecoinResource.java @@ -265,4 +265,117 @@ public class CrossChainDogecoinResource { return CrossChainUtils.buildServerConfigurationInfo(Dogecoin.getInstance()); } -} + + @GET + @Path("/feekb") + @Operation( + summary = "Returns Dogecoin fee per Kb.", + description = "Returns Dogecoin fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getDogecoinFeePerKb() { + Dogecoin dogecoin = Dogecoin.getInstance(); + + return String.valueOf(dogecoin.getFeePerKb().value); + } + + @POST + @Path("/updatefeekb") + @Operation( + summary = "Sets Dogecoin fee per Kb.", + description = "Sets Dogecoin fee per Kb.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee per Kb", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setDogecoinFeePerKb(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + Dogecoin dogecoin = Dogecoin.getInstance(); + + try { + return CrossChainUtils.setFeePerKb(dogecoin, fee); + } catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } + + @GET + @Path("/feeceiling") + @Operation( + summary = "Returns Dogecoin fee per Kb.", + description = "Returns Dogecoin fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getDogecoinFeeCeiling() { + Dogecoin dogecoin = Dogecoin.getInstance(); + + return String.valueOf(dogecoin.getFeeCeiling()); + } + + @POST + @Path("/updatefeeceiling") + @Operation( + summary = "Sets Dogecoin fee ceiling.", + description = "Sets Dogecoin fee ceiling.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setDogecoinFeeCeiling(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + Dogecoin dogecoin = Dogecoin.getInstance(); + + try { + return CrossChainUtils.setFeeCeiling(dogecoin, fee); + } + catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/qortal/api/resource/CrossChainLitecoinResource.java b/src/main/java/org/qortal/api/resource/CrossChainLitecoinResource.java index 3296c3ca..7667eea1 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainLitecoinResource.java +++ b/src/main/java/org/qortal/api/resource/CrossChainLitecoinResource.java @@ -304,4 +304,117 @@ public class CrossChainLitecoinResource { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE); } } + + @GET + @Path("/feekb") + @Operation( + summary = "Returns Litecoin fee per Kb.", + description = "Returns Litecoin fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getLitecoinFeePerKb() { + Litecoin litecoin = Litecoin.getInstance(); + + return String.valueOf(litecoin.getFeePerKb().value); + } + + @POST + @Path("/updatefeekb") + @Operation( + summary = "Sets Litecoin fee per Kb.", + description = "Sets Litecoin fee per Kb.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee per Kb", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setLitecoinFeePerKb(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + Litecoin litecoin = Litecoin.getInstance(); + + try { + return CrossChainUtils.setFeePerKb(litecoin, fee); + } catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } + + @GET + @Path("/feeceiling") + @Operation( + summary = "Returns Litecoin fee per Kb.", + description = "Returns Litecoin fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getLitecoinFeeCeiling() { + Litecoin litecoin = Litecoin.getInstance(); + + return String.valueOf(litecoin.getFeeCeiling()); + } + + @POST + @Path("/updatefeeceiling") + @Operation( + summary = "Sets Litecoin fee ceiling.", + description = "Sets Litecoin fee ceiling.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setLitecoinFeeCeiling(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + Litecoin litecoin = Litecoin.getInstance(); + + try { + return CrossChainUtils.setFeeCeiling(litecoin, fee); + } + catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } } \ No newline at end of file diff --git a/src/main/java/org/qortal/api/resource/CrossChainPirateChainResource.java b/src/main/java/org/qortal/api/resource/CrossChainPirateChainResource.java index 0e29e892..03ff43b8 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainPirateChainResource.java +++ b/src/main/java/org/qortal/api/resource/CrossChainPirateChainResource.java @@ -351,4 +351,117 @@ public class CrossChainPirateChainResource { return CrossChainUtils.buildServerConfigurationInfo(PirateChain.getInstance()); } + + @GET + @Path("/feekb") + @Operation( + summary = "Returns PirateChain fee per Kb.", + description = "Returns PirateChain fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getPirateChainFeePerKb() { + PirateChain pirateChain = PirateChain.getInstance(); + + return String.valueOf(pirateChain.getFeePerKb().value); + } + + @POST + @Path("/updatefeekb") + @Operation( + summary = "Sets PirateChain fee per Kb.", + description = "Sets PirateChain fee per Kb.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee per Kb", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setPirateChainFeePerKb(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + PirateChain pirateChain = PirateChain.getInstance(); + + try { + return CrossChainUtils.setFeePerKb(pirateChain, fee); + } catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } + + @GET + @Path("/feeceiling") + @Operation( + summary = "Returns PirateChain fee per Kb.", + description = "Returns PirateChain fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getPirateChainFeeCeiling() { + PirateChain pirateChain = PirateChain.getInstance(); + + return String.valueOf(pirateChain.getFeeCeiling()); + } + + @POST + @Path("/updatefeeceiling") + @Operation( + summary = "Sets PirateChain fee ceiling.", + description = "Sets PirateChain fee ceiling.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setPirateChainFeeCeiling(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + PirateChain pirateChain = PirateChain.getInstance(); + + try { + return CrossChainUtils.setFeeCeiling(pirateChain, fee); + } + catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } } diff --git a/src/main/java/org/qortal/api/resource/CrossChainRavencoinResource.java b/src/main/java/org/qortal/api/resource/CrossChainRavencoinResource.java index 9b702b25..ce5cd668 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainRavencoinResource.java +++ b/src/main/java/org/qortal/api/resource/CrossChainRavencoinResource.java @@ -265,4 +265,117 @@ public class CrossChainRavencoinResource { return CrossChainUtils.buildServerConfigurationInfo(Ravencoin.getInstance()); } + + @GET + @Path("/feekb") + @Operation( + summary = "Returns Ravencoin fee per Kb.", + description = "Returns Ravencoin fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getRavencoinFeePerKb() { + Ravencoin ravencoin = Ravencoin.getInstance(); + + return String.valueOf(ravencoin.getFeePerKb().value); + } + + @POST + @Path("/updatefeekb") + @Operation( + summary = "Sets Ravencoin fee per Kb.", + description = "Sets Ravencoin fee per Kb.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee per Kb", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setRavencoinFeePerKb(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + Ravencoin ravencoin = Ravencoin.getInstance(); + + try { + return CrossChainUtils.setFeePerKb(ravencoin, fee); + } catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } + + @GET + @Path("/feeceiling") + @Operation( + summary = "Returns Ravencoin fee per Kb.", + description = "Returns Ravencoin fee per Kb.", + responses = { + @ApiResponse( + content = @Content( + schema = @Schema( + type = "number" + ) + ) + ) + } + ) + public String getRavencoinFeeCeiling() { + Ravencoin ravencoin = Ravencoin.getInstance(); + + return String.valueOf(ravencoin.getFeeCeiling()); + } + + @POST + @Path("/updatefeeceiling") + @Operation( + summary = "Sets Ravencoin fee ceiling.", + description = "Sets Ravencoin fee ceiling.", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "number", + description = "the fee", + example = "100" + ) + ) + ), + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "number", description = "fee")) + ) + } + ) + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_CRITERIA}) + public String setRavencoinFeeCeiling(@HeaderParam(Security.API_KEY_HEADER) String apiKey, String fee) { + Security.checkApiCallAllowed(request); + + Ravencoin ravencoin = Ravencoin.getInstance(); + + try { + return CrossChainUtils.setFeeCeiling(ravencoin, fee); + } + catch (IllegalArgumentException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); + } + } } diff --git a/src/main/java/org/qortal/api/resource/CrossChainUtils.java b/src/main/java/org/qortal/api/resource/CrossChainUtils.java index d45ba257..6e631b7a 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainUtils.java +++ b/src/main/java/org/qortal/api/resource/CrossChainUtils.java @@ -2,6 +2,7 @@ package org.qortal.api.resource; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.bitcoinj.core.Coin; import org.qortal.crosschain.*; import java.util.ArrayList; @@ -44,4 +45,44 @@ public class CrossChainUtils { return infos; } -} + + /** + * Set Fee Per Kb + * + * @param bitcoiny the blockchain support + * @param fee the fee in satoshis + * + * @return the fee if valid + * + * @throws IllegalArgumentException if invalid + */ + public static String setFeePerKb(Bitcoiny bitcoiny, String fee) throws IllegalArgumentException { + + long satoshis = Long.parseLong(fee); + if( satoshis < 0 ) throw new IllegalArgumentException("can't set fee to negative number"); + + bitcoiny.setFeePerKb(Coin.valueOf(satoshis) ); + + return String.valueOf(bitcoiny.getFeePerKb().value); + } + + /** + * Set Fee Ceiling + * + * @param bitcoiny the blockchain support + * @param fee the fee in satoshis + * + * @return the fee if valid + * + * @throws IllegalArgumentException if invalid + */ + public static String setFeeCeiling(Bitcoiny bitcoiny, String fee) throws IllegalArgumentException{ + + long satoshis = Long.parseLong(fee); + if( satoshis < 0 ) throw new IllegalArgumentException("can't set fee to negative number"); + + bitcoiny.setFeeCeiling( Long.parseLong(fee)); + + return String.valueOf(bitcoiny.getFeeCeiling()); + } +} \ No newline at end of file diff --git a/src/main/java/org/qortal/crosschain/Bitcoin.java b/src/main/java/org/qortal/crosschain/Bitcoin.java index b2a016e7..e11dde0b 100644 --- a/src/main/java/org/qortal/crosschain/Bitcoin.java +++ b/src/main/java/org/qortal/crosschain/Bitcoin.java @@ -22,8 +22,6 @@ public class Bitcoin extends Bitcoiny { private static final long MINIMUM_ORDER_AMOUNT = 100000; // 0.001 BTC minimum order, due to high fees // Temporary values until a dynamic fee system is written. - private static final long OLD_FEE_AMOUNT = 4_000L; // Not 5000 so that existing P2SH-B can output 1000, avoiding dust issue, leaving 4000 for fees. - private static final long NEW_FEE_TIMESTAMP = 1598280000000L; // milliseconds since epoch private static final long NEW_FEE_AMOUNT = 6_000L; private static final long NON_MAINNET_FEE = 1000L; // enough for TESTNET3 and should be OK for REGTEST @@ -125,11 +123,7 @@ public class Bitcoin extends Bitcoiny { @Override public long getP2shFee(Long timestamp) { - // TODO: This will need to be replaced with something better in the near future! - if (timestamp != null && timestamp < NEW_FEE_TIMESTAMP) - return OLD_FEE_AMOUNT; - - return NEW_FEE_AMOUNT; + return this.getFeeCeiling(); } }, TEST3 { @@ -186,6 +180,16 @@ public class Bitcoin extends Bitcoiny { } }; + private long feeCeiling = NEW_FEE_AMOUNT; + + public long getFeeCeiling() { + return feeCeiling; + } + + public void setFeeCeiling(long feeCeiling) { + this.feeCeiling = feeCeiling; + } + public abstract NetworkParameters getParams(); public abstract Collection getServers(); public abstract String getGenesisHash(); @@ -199,7 +203,7 @@ public class Bitcoin extends Bitcoiny { // Constructors and instance private Bitcoin(BitcoinNet bitcoinNet, BitcoinyBlockchainProvider blockchain, Context bitcoinjContext, String currencyCode) { - super(blockchain, bitcoinjContext, currencyCode); + super(blockchain, bitcoinjContext, currencyCode, bitcoinjContext.getFeePerKb()); this.bitcoinNet = bitcoinNet; LOGGER.info(() -> String.format("Starting Bitcoin support using %s", this.bitcoinNet.name())); @@ -244,6 +248,16 @@ public class Bitcoin extends Bitcoiny { return this.bitcoinNet.getP2shFee(timestamp); } + @Override + public long getFeeCeiling() { + return this.bitcoinNet.getFeeCeiling(); + } + + @Override + public void setFeeCeiling(long fee) { + + this.bitcoinNet.setFeeCeiling( fee ); + } /** * Returns bitcoinj transaction sending amount to recipient using 20 sat/byte fee. * diff --git a/src/main/java/org/qortal/crosschain/Bitcoiny.java b/src/main/java/org/qortal/crosschain/Bitcoiny.java index b7614d1e..1ae70fe9 100644 --- a/src/main/java/org/qortal/crosschain/Bitcoiny.java +++ b/src/main/java/org/qortal/crosschain/Bitcoiny.java @@ -53,12 +53,15 @@ public abstract class Bitcoiny implements ForeignBlockchain { /** Byte offset into raw block headers to block timestamp. */ private static final int TIMESTAMP_OFFSET = 4 + 32 + 32; + protected Coin feePerKb; + // Constructors and instance - protected Bitcoiny(BitcoinyBlockchainProvider blockchainProvider, Context bitcoinjContext, String currencyCode) { + protected Bitcoiny(BitcoinyBlockchainProvider blockchainProvider, Context bitcoinjContext, String currencyCode, Coin feePerKb) { this.blockchainProvider = blockchainProvider; this.bitcoinjContext = bitcoinjContext; this.currencyCode = currencyCode; + this.feePerKb = feePerKb; this.params = this.bitcoinjContext.getParams(); } @@ -167,7 +170,11 @@ public abstract class Bitcoiny implements ForeignBlockchain { /** Returns fee per transaction KB. To be overridden for testnet/regtest. */ public Coin getFeePerKb() { - return this.bitcoinjContext.getFeePerKb(); + return this.feePerKb; + } + + public void setFeePerKb(Coin feePerKb) { + this.feePerKb = feePerKb; } /** Returns minimum order size in sats. To be overridden for coins that need to restrict order size. */ @@ -757,6 +764,10 @@ public abstract class Bitcoiny implements ForeignBlockchain { } while (true); } + public abstract long getFeeCeiling(); + + public abstract void setFeeCeiling(long fee); + // UTXOProvider support static class WalletAwareUTXOProvider implements UTXOProvider { diff --git a/src/main/java/org/qortal/crosschain/Digibyte.java b/src/main/java/org/qortal/crosschain/Digibyte.java index bda6c18d..e8e8d7d3 100644 --- a/src/main/java/org/qortal/crosschain/Digibyte.java +++ b/src/main/java/org/qortal/crosschain/Digibyte.java @@ -63,8 +63,7 @@ public class Digibyte extends Bitcoiny { @Override public long getP2shFee(Long timestamp) { - // TODO: This will need to be replaced with something better in the near future! - return MAINNET_FEE; + return this.getFeeCeiling(); } }, TEST3 { @@ -114,6 +113,16 @@ public class Digibyte extends Bitcoiny { } }; + private long feeCeiling = MAINNET_FEE; + + public long getFeeCeiling() { + return feeCeiling; + } + + public void setFeeCeiling(long feeCeiling) { + this.feeCeiling = feeCeiling; + } + public abstract NetworkParameters getParams(); public abstract Collection getServers(); public abstract String getGenesisHash(); @@ -127,7 +136,7 @@ public class Digibyte extends Bitcoiny { // Constructors and instance private Digibyte(DigibyteNet digibyteNet, BitcoinyBlockchainProvider blockchain, Context bitcoinjContext, String currencyCode) { - super(blockchain, bitcoinjContext, currencyCode); + super(blockchain, bitcoinjContext, currencyCode, DEFAULT_FEE_PER_KB); this.digibyteNet = digibyteNet; LOGGER.info(() -> String.format("Starting Digibyte support using %s", this.digibyteNet.name())); @@ -156,11 +165,6 @@ public class Digibyte extends Bitcoiny { // Actual useful methods for use by other classes - @Override - public Coin getFeePerKb() { - return DEFAULT_FEE_PER_KB; - } - @Override public long getMinimumOrderAmount() { return MINIMUM_ORDER_AMOUNT; @@ -177,4 +181,14 @@ public class Digibyte extends Bitcoiny { return this.digibyteNet.getP2shFee(timestamp); } + @Override + public long getFeeCeiling() { + return this.digibyteNet.getFeeCeiling(); + } + + @Override + public void setFeeCeiling(long fee) { + + this.digibyteNet.setFeeCeiling( fee ); + } } diff --git a/src/main/java/org/qortal/crosschain/Dogecoin.java b/src/main/java/org/qortal/crosschain/Dogecoin.java index c687ca60..ca96ef7c 100644 --- a/src/main/java/org/qortal/crosschain/Dogecoin.java +++ b/src/main/java/org/qortal/crosschain/Dogecoin.java @@ -63,8 +63,7 @@ public class Dogecoin extends Bitcoiny { @Override public long getP2shFee(Long timestamp) { - // TODO: This will need to be replaced with something better in the near future! - return MAINNET_FEE; + return this.getFeeCeiling(); } }, TEST3 { @@ -114,6 +113,16 @@ public class Dogecoin extends Bitcoiny { } }; + private long feeCeiling = MAINNET_FEE; + + public long getFeeCeiling() { + return feeCeiling; + } + + public void setFeeCeiling(long feeCeiling) { + this.feeCeiling = feeCeiling; + } + public abstract NetworkParameters getParams(); public abstract Collection getServers(); public abstract String getGenesisHash(); @@ -127,7 +136,7 @@ public class Dogecoin extends Bitcoiny { // Constructors and instance private Dogecoin(DogecoinNet dogecoinNet, BitcoinyBlockchainProvider blockchain, Context bitcoinjContext, String currencyCode) { - super(blockchain, bitcoinjContext, currencyCode); + super(blockchain, bitcoinjContext, currencyCode, DEFAULT_FEE_PER_KB); this.dogecoinNet = dogecoinNet; LOGGER.info(() -> String.format("Starting Dogecoin support using %s", this.dogecoinNet.name())); @@ -156,11 +165,6 @@ public class Dogecoin extends Bitcoiny { // Actual useful methods for use by other classes - @Override - public Coin getFeePerKb() { - return DEFAULT_FEE_PER_KB; - } - @Override public long getMinimumOrderAmount() { return MINIMUM_ORDER_AMOUNT; @@ -177,4 +181,14 @@ public class Dogecoin extends Bitcoiny { return this.dogecoinNet.getP2shFee(timestamp); } + @Override + public long getFeeCeiling() { + return this.dogecoinNet.getFeeCeiling(); + } + + @Override + public void setFeeCeiling(long fee) { + + this.dogecoinNet.setFeeCeiling( fee ); + } } diff --git a/src/main/java/org/qortal/crosschain/Litecoin.java b/src/main/java/org/qortal/crosschain/Litecoin.java index d87cd1a1..96c13532 100644 --- a/src/main/java/org/qortal/crosschain/Litecoin.java +++ b/src/main/java/org/qortal/crosschain/Litecoin.java @@ -67,8 +67,7 @@ public class Litecoin extends Bitcoiny { @Override public long getP2shFee(Long timestamp) { - // TODO: This will need to be replaced with something better in the near future! - return MAINNET_FEE; + return this.getFeeCeiling(); } }, TEST3 { @@ -123,6 +122,16 @@ public class Litecoin extends Bitcoiny { } }; + private long feeCeiling = MAINNET_FEE; + + public long getFeeCeiling() { + return feeCeiling; + } + + public void setFeeCeiling(long feeCeiling) { + this.feeCeiling = feeCeiling; + } + public abstract NetworkParameters getParams(); public abstract Collection getServers(); public abstract String getGenesisHash(); @@ -136,7 +145,7 @@ public class Litecoin extends Bitcoiny { // Constructors and instance private Litecoin(LitecoinNet litecoinNet, BitcoinyBlockchainProvider blockchain, Context bitcoinjContext, String currencyCode) { - super(blockchain, bitcoinjContext, currencyCode); + super(blockchain, bitcoinjContext, currencyCode, DEFAULT_FEE_PER_KB); this.litecoinNet = litecoinNet; LOGGER.info(() -> String.format("Starting Litecoin support using %s", this.litecoinNet.name())); @@ -165,12 +174,6 @@ public class Litecoin extends Bitcoiny { // Actual useful methods for use by other classes - /** Default Litecoin fee is lower than Bitcoin: only 10sats/byte. */ - @Override - public Coin getFeePerKb() { - return DEFAULT_FEE_PER_KB; - } - @Override public long getMinimumOrderAmount() { return MINIMUM_ORDER_AMOUNT; @@ -187,4 +190,14 @@ public class Litecoin extends Bitcoiny { return this.litecoinNet.getP2shFee(timestamp); } + @Override + public long getFeeCeiling() { + return this.litecoinNet.getFeeCeiling(); + } + + @Override + public void setFeeCeiling(long fee) { + + this.litecoinNet.setFeeCeiling( fee ); + } } diff --git a/src/main/java/org/qortal/crosschain/PirateChain.java b/src/main/java/org/qortal/crosschain/PirateChain.java index 3f3cba47..d0f9317d 100644 --- a/src/main/java/org/qortal/crosschain/PirateChain.java +++ b/src/main/java/org/qortal/crosschain/PirateChain.java @@ -67,8 +67,7 @@ public class PirateChain extends Bitcoiny { @Override public long getP2shFee(Long timestamp) { - // TODO: This will need to be replaced with something better in the near future! - return MAINNET_FEE; + return this.getFeeCeiling(); } }, TEST3 { @@ -118,6 +117,16 @@ public class PirateChain extends Bitcoiny { } }; + private long feeCeiling = MAINNET_FEE; + + public long getFeeCeiling() { + return feeCeiling; + } + + public void setFeeCeiling(long feeCeiling) { + this.feeCeiling = feeCeiling; + } + public abstract NetworkParameters getParams(); public abstract Collection getServers(); public abstract String getGenesisHash(); @@ -131,7 +140,7 @@ public class PirateChain extends Bitcoiny { // Constructors and instance private PirateChain(PirateChainNet pirateChainNet, BitcoinyBlockchainProvider blockchain, Context bitcoinjContext, String currencyCode) { - super(blockchain, bitcoinjContext, currencyCode); + super(blockchain, bitcoinjContext, currencyCode, DEFAULT_FEE_PER_KB); this.pirateChainNet = pirateChainNet; LOGGER.info(() -> String.format("Starting Pirate Chain support using %s", this.pirateChainNet.name())); @@ -160,12 +169,6 @@ public class PirateChain extends Bitcoiny { // Actual useful methods for use by other classes - /** Default Litecoin fee is lower than Bitcoin: only 10sats/byte. */ - @Override - public Coin getFeePerKb() { - return DEFAULT_FEE_PER_KB; - } - @Override public long getMinimumOrderAmount() { return MINIMUM_ORDER_AMOUNT; @@ -182,6 +185,16 @@ public class PirateChain extends Bitcoiny { return this.pirateChainNet.getP2shFee(timestamp); } + @Override + public long getFeeCeiling() { + return this.pirateChainNet.getFeeCeiling(); + } + + @Override + public void setFeeCeiling(long fee) { + + this.pirateChainNet.setFeeCeiling( fee ); + } /** * Returns confirmed balance, based on passed payment script. *

diff --git a/src/main/java/org/qortal/crosschain/Ravencoin.java b/src/main/java/org/qortal/crosschain/Ravencoin.java index d9301f48..b4ed1a13 100644 --- a/src/main/java/org/qortal/crosschain/Ravencoin.java +++ b/src/main/java/org/qortal/crosschain/Ravencoin.java @@ -65,8 +65,7 @@ public class Ravencoin extends Bitcoiny { @Override public long getP2shFee(Long timestamp) { - // TODO: This will need to be replaced with something better in the near future! - return MAINNET_FEE; + return this.getFeeCeiling(); } }, TEST3 { @@ -116,6 +115,16 @@ public class Ravencoin extends Bitcoiny { } }; + private long feeCeiling = MAINNET_FEE; + + public long getFeeCeiling() { + return feeCeiling; + } + + public void setFeeCeiling(long feeCeiling) { + this.feeCeiling = feeCeiling; + } + public abstract NetworkParameters getParams(); public abstract Collection getServers(); public abstract String getGenesisHash(); @@ -129,7 +138,7 @@ public class Ravencoin extends Bitcoiny { // Constructors and instance private Ravencoin(RavencoinNet ravencoinNet, BitcoinyBlockchainProvider blockchain, Context bitcoinjContext, String currencyCode) { - super(blockchain, bitcoinjContext, currencyCode); + super(blockchain, bitcoinjContext, currencyCode, DEFAULT_FEE_PER_KB); this.ravencoinNet = ravencoinNet; LOGGER.info(() -> String.format("Starting Ravencoin support using %s", this.ravencoinNet.name())); @@ -158,11 +167,6 @@ public class Ravencoin extends Bitcoiny { // Actual useful methods for use by other classes - @Override - public Coin getFeePerKb() { - return DEFAULT_FEE_PER_KB; - } - @Override public long getMinimumOrderAmount() { return MINIMUM_ORDER_AMOUNT; @@ -179,4 +183,14 @@ public class Ravencoin extends Bitcoiny { return this.ravencoinNet.getP2shFee(timestamp); } + @Override + public long getFeeCeiling() { + return this.ravencoinNet.getFeeCeiling(); + } + + @Override + public void setFeeCeiling(long fee) { + + this.ravencoinNet.setFeeCeiling( fee ); + } }