Improve /crosschain/tradebot/respond with varied API errors such as BTC_BALANCE_ISSUE, BTC_NETWORK_ISSUE, etc. instead of just "false"

This commit is contained in:
catbref 2020-08-05 10:05:09 +01:00
parent 36d0abe635
commit ec2c9d2a44
2 changed files with 27 additions and 7 deletions

View File

@ -1045,7 +1045,7 @@ public class CrossChainResource {
) )
} }
) )
@ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.INVALID_ADDRESS, ApiError.INVALID_CRITERIA, ApiError.BTC_BALANCE_ISSUE, ApiError.BTC_NETWORK_ISSUE, ApiError.REPOSITORY_ISSUE})
public String tradeBotResponder(TradeBotRespondRequest tradeBotRespondRequest) { public String tradeBotResponder(TradeBotRespondRequest tradeBotRespondRequest) {
Security.checkApiCallAllowed(request); Security.checkApiCallAllowed(request);
@ -1068,9 +1068,22 @@ public class CrossChainResource {
if (crossChainTradeData.mode != BTCACCT.Mode.OFFERING) if (crossChainTradeData.mode != BTCACCT.Mode.OFFERING)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA);
boolean result = TradeBot.startResponse(repository, crossChainTradeData, tradeBotRespondRequest.xprv58, tradeBotRespondRequest.receivingAddress); TradeBot.ResponseResult result = TradeBot.startResponse(repository, crossChainTradeData, tradeBotRespondRequest.xprv58, tradeBotRespondRequest.receivingAddress);
return result ? "true" : "false"; switch (result) {
case OK:
return "true";
case INSUFFICIENT_FUNDS:
case BTC_BALANCE_ISSUE:
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.BTC_BALANCE_ISSUE);
case BTC_NETWORK_ISSUE:
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.BTC_NETWORK_ISSUE);
default:
return "false";
}
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }

View File

@ -45,6 +45,8 @@ import org.qortal.utils.NTP;
public class TradeBot { public class TradeBot {
public enum ResponseResult { OK, INSUFFICIENT_FUNDS, BTC_BALANCE_ISSUE, BTC_NETWORK_ISSUE }
private static final Logger LOGGER = LogManager.getLogger(TradeBot.class); private static final Logger LOGGER = LogManager.getLogger(TradeBot.class);
private static final Random RANDOM = new SecureRandom(); private static final Random RANDOM = new SecureRandom();
private static final long FEE_AMOUNT = 1000L; private static final long FEE_AMOUNT = 1000L;
@ -203,7 +205,7 @@ public class TradeBot {
* @return true if P2SH-A funding transaction successfully broadcast to Bitcoin network, false otherwise * @return true if P2SH-A funding transaction successfully broadcast to Bitcoin network, false otherwise
* @throws DataException * @throws DataException
*/ */
public static boolean startResponse(Repository repository, CrossChainTradeData crossChainTradeData, String xprv58, String receivingAddress) throws DataException { public static ResponseResult startResponse(Repository repository, CrossChainTradeData crossChainTradeData, String xprv58, String receivingAddress) throws DataException {
byte[] tradePrivateKey = generateTradePrivateKey(); byte[] tradePrivateKey = generateTradePrivateKey();
byte[] secretA = generateSecret(); byte[] secretA = generateSecret();
byte[] hashOfSecretA = Crypto.hash160(secretA); byte[] hashOfSecretA = Crypto.hash160(secretA);
@ -233,7 +235,7 @@ public class TradeBot {
Transaction fundingCheckTransaction = BTC.getInstance().buildSpend(xprv58, tradeForeignAddress, totalFundsRequired); Transaction fundingCheckTransaction = BTC.getInstance().buildSpend(xprv58, tradeForeignAddress, totalFundsRequired);
if (fundingCheckTransaction == null) if (fundingCheckTransaction == null)
return false; return ResponseResult.INSUFFICIENT_FUNDS;
// P2SH-A to be funded // P2SH-A to be funded
byte[] redeemScriptBytes = BTCP2SH.buildScript(tradeForeignPublicKeyHash, lockTimeA, crossChainTradeData.creatorBitcoinPKH, hashOfSecretA); byte[] redeemScriptBytes = BTCP2SH.buildScript(tradeForeignPublicKeyHash, lockTimeA, crossChainTradeData.creatorBitcoinPKH, hashOfSecretA);
@ -241,10 +243,15 @@ public class TradeBot {
// Fund P2SH-A // Fund P2SH-A
Transaction p2shFundingTransaction = BTC.getInstance().buildSpend(tradeBotData.getXprv58(), p2shAddress, crossChainTradeData.expectedBitcoin + FEE_AMOUNT); Transaction p2shFundingTransaction = BTC.getInstance().buildSpend(tradeBotData.getXprv58(), p2shAddress, crossChainTradeData.expectedBitcoin + FEE_AMOUNT);
if (p2shFundingTransaction == null) {
LOGGER.warn(() -> String.format("Unable to build P2SH-A funding transaction - lack of funds?"));
return ResponseResult.BTC_BALANCE_ISSUE;
}
if (!BTC.getInstance().broadcastTransaction(p2shFundingTransaction)) { if (!BTC.getInstance().broadcastTransaction(p2shFundingTransaction)) {
// We couldn't fund P2SH-A at this time // We couldn't fund P2SH-A at this time
LOGGER.debug(() -> String.format("Couldn't broadcast P2SH-A funding transaction?")); LOGGER.debug(() -> String.format("Couldn't broadcast P2SH-A funding transaction?"));
return false; return ResponseResult.BTC_NETWORK_ISSUE;
} }
repository.getCrossChainRepository().save(tradeBotData); repository.getCrossChainRepository().save(tradeBotData);
@ -252,7 +259,7 @@ public class TradeBot {
LOGGER.info(() -> String.format("Funding P2SH-A %s. Waiting for confirmation", p2shAddress)); LOGGER.info(() -> String.format("Funding P2SH-A %s. Waiting for confirmation", p2shAddress));
return true; return ResponseResult.OK;
} }
private static byte[] generateTradePrivateKey() { private static byte[] generateTradePrivateKey() {