diff --git a/cli/src/main/java/bisq/cli/ColumnHeaderConstants.java b/cli/src/main/java/bisq/cli/ColumnHeaderConstants.java index b45cd942f2..79aff0d3f9 100644 --- a/cli/src/main/java/bisq/cli/ColumnHeaderConstants.java +++ b/cli/src/main/java/bisq/cli/ColumnHeaderConstants.java @@ -42,6 +42,7 @@ class ColumnHeaderConstants { static final String COL_HEADER_UNLOCKING_BONDS_BALANCE = "Unlocking Bonds Balance"; static final String COL_HEADER_UNVERIFIED_BALANCE = "Unverified Balance"; static final String COL_HEADER_CONFIRMATIONS = "Confirmations"; + static final String COL_HEADER_IS_USED_ADDRESS = "Is Used"; static final String COL_HEADER_CREATION_DATE = padEnd("Creation Date (UTC)", 20, ' '); static final String COL_HEADER_CURRENCY = "Currency"; static final String COL_HEADER_DIRECTION = "Buy/Sell"; diff --git a/cli/src/main/java/bisq/cli/GrpcClient.java b/cli/src/main/java/bisq/cli/GrpcClient.java index f4097ad313..ea20c6aef8 100644 --- a/cli/src/main/java/bisq/cli/GrpcClient.java +++ b/cli/src/main/java/bisq/cli/GrpcClient.java @@ -135,11 +135,11 @@ public final class GrpcClient { public String getUnusedBtcAddress() { var request = GetFundingAddressesRequest.newBuilder().build(); + var addressBalances = grpcStubs.walletsService.getFundingAddresses(request) + .getAddressBalanceInfoList(); //noinspection OptionalGetWithoutIsPresent - return grpcStubs.walletsService.getFundingAddresses(request) - .getAddressBalanceInfoList() - .stream() - .filter(a -> a.getBalance() == 0 && a.getNumConfirmations() == 0) + return addressBalances.stream() + .filter(AddressBalanceInfo::getIsAddressUnused) .findFirst() .get() .getAddress(); diff --git a/cli/src/main/java/bisq/cli/TableFormat.java b/cli/src/main/java/bisq/cli/TableFormat.java index dca4aa0699..f0e5ac1ac4 100644 --- a/cli/src/main/java/bisq/cli/TableFormat.java +++ b/cli/src/main/java/bisq/cli/TableFormat.java @@ -51,18 +51,21 @@ public class TableFormat { public static String formatAddressBalanceTbl(List addressBalanceInfo) { String headerFormatString = COL_HEADER_ADDRESS + COL_HEADER_DELIMITER + COL_HEADER_AVAILABLE_BALANCE + COL_HEADER_DELIMITER - + COL_HEADER_CONFIRMATIONS + COL_HEADER_DELIMITER + "\n"; + + COL_HEADER_CONFIRMATIONS + COL_HEADER_DELIMITER + + COL_HEADER_IS_USED_ADDRESS + COL_HEADER_DELIMITER + "\n"; String headerLine = format(headerFormatString, "BTC"); String colDataFormat = "%-" + COL_HEADER_ADDRESS.length() + "s" // lt justify + " %" + (COL_HEADER_AVAILABLE_BALANCE.length() - 1) + "s" // rt justify - + " %" + COL_HEADER_CONFIRMATIONS.length() + "d"; // lt justify + + " %" + COL_HEADER_CONFIRMATIONS.length() + "d" // lt justify + + " %" + COL_HEADER_IS_USED_ADDRESS.length() + "s"; // lt justify return headerLine + addressBalanceInfo.stream() .map(info -> format(colDataFormat, info.getAddress(), formatSatoshis(info.getBalance()), - info.getNumConfirmations())) + info.getNumConfirmations(), + info.getIsAddressUnused() ? "NO" : "YES")) .collect(Collectors.joining("\n")); } diff --git a/core/src/main/java/bisq/core/api/CoreWalletsService.java b/core/src/main/java/bisq/core/api/CoreWalletsService.java index b048fcefe9..7346f11956 100644 --- a/core/src/main/java/bisq/core/api/CoreWalletsService.java +++ b/core/src/main/java/bisq/core/api/CoreWalletsService.java @@ -159,15 +159,22 @@ class CoreWalletsService { AddressBalanceInfo getAddressBalanceInfo(String addressString) { var satoshiBalance = getAddressBalance(addressString); var numConfirmations = getNumConfirmationsForMostRecentTransaction(addressString); - return new AddressBalanceInfo(addressString, satoshiBalance, numConfirmations); + Address address = getAddressEntry(addressString).getAddress(); + return new AddressBalanceInfo(addressString, + satoshiBalance, + numConfirmations, + btcWalletService.isAddressUnused(address)); } List getFundingAddresses() { verifyWalletsAreAvailable(); verifyEncryptedWalletIsUnlocked(); - // Create a new funding address if none exists. - if (btcWalletService.getAvailableAddressEntries().isEmpty()) + // Create a new unused funding address if none exists. + boolean unusedAddressExists = btcWalletService.getAvailableAddressEntries() + .stream() + .anyMatch(a -> btcWalletService.isAddressUnused(a.getAddress())); + if (!unusedAddressExists) btcWalletService.getFreshAddressEntry(); List addressStrings = btcWalletService @@ -192,7 +199,8 @@ class CoreWalletsService { return addressStrings.stream().map(address -> new AddressBalanceInfo(address, balances.getUnchecked(address), - getNumConfirmationsForMostRecentTransaction(address))) + getNumConfirmationsForMostRecentTransaction(address), + btcWalletService.isAddressUnused(getAddressEntry(address).getAddress()))) .collect(Collectors.toList()); } diff --git a/core/src/main/java/bisq/core/api/model/AddressBalanceInfo.java b/core/src/main/java/bisq/core/api/model/AddressBalanceInfo.java index a9da82a917..5921b0ad18 100644 --- a/core/src/main/java/bisq/core/api/model/AddressBalanceInfo.java +++ b/core/src/main/java/bisq/core/api/model/AddressBalanceInfo.java @@ -24,11 +24,16 @@ public class AddressBalanceInfo implements Payload { private final String address; private final long balance; // address' balance in satoshis private final long numConfirmations; // # confirmations for address' most recent tx + private final boolean isAddressUnused; - public AddressBalanceInfo(String address, long balance, long numConfirmations) { + public AddressBalanceInfo(String address, + long balance, + long numConfirmations, + boolean isAddressUnused) { this.address = address; this.balance = balance; this.numConfirmations = numConfirmations; + this.isAddressUnused = isAddressUnused; } /////////////////////////////////////////////////////////////////////////////////////////// @@ -40,13 +45,16 @@ public class AddressBalanceInfo implements Payload { return bisq.proto.grpc.AddressBalanceInfo.newBuilder() .setAddress(address) .setBalance(balance) - .setNumConfirmations(numConfirmations).build(); + .setNumConfirmations(numConfirmations) + .setIsAddressUnused(isAddressUnused) + .build(); } public static AddressBalanceInfo fromProto(bisq.proto.grpc.AddressBalanceInfo proto) { return new AddressBalanceInfo(proto.getAddress(), proto.getBalance(), - proto.getNumConfirmations()); + proto.getNumConfirmations(), + proto.getIsAddressUnused()); } @Override @@ -55,6 +63,7 @@ public class AddressBalanceInfo implements Payload { "address='" + address + '\'' + ", balance=" + balance + ", numConfirmations=" + numConfirmations + + ", isAddressUnused=" + isAddressUnused + '}'; } } diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index d2eda23c93..8a819ff83b 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -540,6 +540,7 @@ message AddressBalanceInfo { string address = 1; int64 balance = 2; int64 numConfirmations = 3; + bool isAddressUnused = 4; } ///////////////////////////////////////////////////////////////////////////////////////////