Requesting BTC/LTC wallet balance now accepts public key xpub/tpub too

This commit is contained in:
catbref 2020-12-07 15:40:05 +00:00
parent cf82813280
commit 23f0969b2d
4 changed files with 28 additions and 21 deletions

View File

@ -33,15 +33,15 @@ public class CrossChainBitcoinResource {
@Path("/walletbalance") @Path("/walletbalance")
@Operation( @Operation(
summary = "Returns BTC balance for hierarchical, deterministic BIP32 wallet", summary = "Returns BTC balance for hierarchical, deterministic BIP32 wallet",
description = "Supply BIP32 'm' private key in base58, starting with 'xprv' for mainnet, 'tprv' for testnet", description = "Supply BIP32 'm' private/public key in base58, starting with 'xprv'/'xpub' for mainnet, 'tprv'/'tpub' for testnet",
requestBody = @RequestBody( requestBody = @RequestBody(
required = true, required = true,
content = @Content( content = @Content(
mediaType = MediaType.TEXT_PLAIN, mediaType = MediaType.TEXT_PLAIN,
schema = @Schema( schema = @Schema(
type = "string", type = "string",
description = "BIP32 'm' private key in base58", description = "BIP32 'm' private/public key in base58",
example = "tprv___________________________________________________________________________________________________________" example = "tpub___________________________________________________________________________________________________________"
) )
) )
), ),
@ -52,15 +52,15 @@ public class CrossChainBitcoinResource {
} }
) )
@ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE}) @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE})
public String getBitcoinWalletBalance(String xprv58) { public String getBitcoinWalletBalance(String key58) {
Security.checkApiCallAllowed(request); Security.checkApiCallAllowed(request);
Bitcoin bitcoin = Bitcoin.getInstance(); Bitcoin bitcoin = Bitcoin.getInstance();
if (!bitcoin.isValidXprv(xprv58)) if (!bitcoin.isValidDeterministicKey(key58))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY);
Long balance = bitcoin.getWalletBalance(xprv58); Long balance = bitcoin.getWalletBalance(key58);
if (balance == null) if (balance == null)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE);
@ -102,7 +102,7 @@ public class CrossChainBitcoinResource {
if (!bitcoin.isValidAddress(bitcoinSendRequest.receivingAddress)) if (!bitcoin.isValidAddress(bitcoinSendRequest.receivingAddress))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
if (!bitcoin.isValidXprv(bitcoinSendRequest.xprv58)) if (!bitcoin.isValidDeterministicKey(bitcoinSendRequest.xprv58))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY);
Transaction spendTransaction = bitcoin.buildSpend(bitcoinSendRequest.xprv58, Transaction spendTransaction = bitcoin.buildSpend(bitcoinSendRequest.xprv58,

View File

@ -33,15 +33,15 @@ public class CrossChainLitecoinResource {
@Path("/walletbalance") @Path("/walletbalance")
@Operation( @Operation(
summary = "Returns LTC balance for hierarchical, deterministic BIP32 wallet", summary = "Returns LTC balance for hierarchical, deterministic BIP32 wallet",
description = "Supply BIP32 'm' private key in base58, starting with 'xprv' for mainnet, 'tprv' for testnet", description = "Supply BIP32 'm' private/public key in base58, starting with 'xprv'/'xpub' for mainnet, 'tprv'/'tpub' for testnet",
requestBody = @RequestBody( requestBody = @RequestBody(
required = true, required = true,
content = @Content( content = @Content(
mediaType = MediaType.TEXT_PLAIN, mediaType = MediaType.TEXT_PLAIN,
schema = @Schema( schema = @Schema(
type = "string", type = "string",
description = "BIP32 'm' private key in base58", description = "BIP32 'm' private/public key in base58",
example = "tprv___________________________________________________________________________________________________________" example = "tpub___________________________________________________________________________________________________________"
) )
) )
), ),
@ -52,15 +52,15 @@ public class CrossChainLitecoinResource {
} }
) )
@ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE}) @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE})
public String getLitecoinWalletBalance(String xprv58) { public String getLitecoinWalletBalance(String key58) {
Security.checkApiCallAllowed(request); Security.checkApiCallAllowed(request);
Litecoin litecoin = Litecoin.getInstance(); Litecoin litecoin = Litecoin.getInstance();
if (!litecoin.isValidXprv(xprv58)) if (!litecoin.isValidDeterministicKey(key58))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY);
Long balance = litecoin.getWalletBalance(xprv58); Long balance = litecoin.getWalletBalance(key58);
if (balance == null) if (balance == null)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.FOREIGN_BLOCKCHAIN_NETWORK_ISSUE);
@ -102,7 +102,7 @@ public class CrossChainLitecoinResource {
if (!litecoin.isValidAddress(litecoinSendRequest.receivingAddress)) if (!litecoin.isValidAddress(litecoinSendRequest.receivingAddress))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
if (!litecoin.isValidXprv(litecoinSendRequest.xprv58)) if (!litecoin.isValidDeterministicKey(litecoinSendRequest.xprv58))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY);
Transaction spendTransaction = litecoin.buildSpend(litecoinSendRequest.xprv58, Transaction spendTransaction = litecoin.buildSpend(litecoinSendRequest.xprv58,

View File

@ -98,7 +98,7 @@ public abstract class Bitcoiny implements ForeignBlockchain {
@Override @Override
public boolean isValidWalletKey(String walletKey) { public boolean isValidWalletKey(String walletKey) {
return this.isValidXprv(walletKey); return this.isValidDeterministicKey(walletKey);
} }
// Actual useful methods for use by other classes // Actual useful methods for use by other classes
@ -111,10 +111,10 @@ public abstract class Bitcoiny implements ForeignBlockchain {
return Amounts.prettyAmount(amount) + " " + this.currencyCode; return Amounts.prettyAmount(amount) + " " + this.currencyCode;
} }
public boolean isValidXprv(String xprv58) { public boolean isValidDeterministicKey(String key58) {
try { try {
Context.propagate(this.bitcoinjContext); Context.propagate(this.bitcoinjContext);
DeterministicKey.deserializeB58(null, xprv58, this.params); DeterministicKey.deserializeB58(null, key58, this.params);
return true; return true;
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return false; return false;
@ -307,13 +307,20 @@ public abstract class Bitcoiny implements ForeignBlockchain {
/** /**
* Returns unspent Bitcoin balance given 'm' BIP32 key. * Returns unspent Bitcoin balance given 'm' BIP32 key.
* *
* @param xprv58 BIP32 extended Bitcoin private key * @param key58 BIP32/HD extended Bitcoin private/public key
* @return unspent BTC balance, or null if unable to determine balance * @return unspent BTC balance, or null if unable to determine balance
*/ */
public Long getWalletBalance(String xprv58) { public Long getWalletBalance(String key58) {
Context.propagate(bitcoinjContext); Context.propagate(bitcoinjContext);
Wallet wallet = Wallet.fromSpendingKeyB58(this.params, xprv58, DeterministicHierarchy.BIP32_STANDARDISATION_TIME_SECS); final DeterministicKey watchKey = DeterministicKey.deserializeB58(null, key58, this.params);
Wallet wallet;
if (watchKey.hasPrivKey())
wallet = Wallet.fromSpendingKeyB58(this.params, key58, DeterministicHierarchy.BIP32_STANDARDISATION_TIME_SECS);
else
wallet = Wallet.fromWatchingKeyB58(this.params, key58, DeterministicHierarchy.BIP32_STANDARDISATION_TIME_SECS);
wallet.setUTXOProvider(new WalletAwareUTXOProvider(this, wallet)); wallet.setUTXOProvider(new WalletAwareUTXOProvider(this, wallet));
Coin balance = wallet.getBalance(); Coin balance = wallet.getBalance();

View File

@ -53,7 +53,7 @@ public class Pay {
params = bitcoiny.getNetworkParameters(); params = bitcoiny.getNetworkParameters();
xprv58 = args[argIndex++]; xprv58 = args[argIndex++];
if (!bitcoiny.isValidXprv(xprv58)) if (!bitcoiny.isValidDeterministicKey(xprv58))
usage("xprv invalid"); usage("xprv invalid");
address = Address.fromString(params, args[argIndex++]); address = Address.fromString(params, args[argIndex++]);