From fc8af8c072af444caafe5b91abce0fa06cd4e78f Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 13 Nov 2020 11:01:02 -0300 Subject: [PATCH 1/8] Define new grpc bsq/btc balances protos This change adds proto serivces and messages to support new api implementations for serving bsq, btc or all wallet balances. - RPC GetBsqBalances will return complete BSQ balance info. - Message BsqBalanceInfo is proto returned by rpc GetBsqBalances. - RPC GetBtcBalances wil return complete BTC balance info. - Message BtcBalanceInfo is proto returned by rpc GetBtcBalances. - RPC GetBalances returns complete BTC and BSQ balance info. - Message BalancesInfo is proto returned by rpc GetBalances. RPC GetBalance remains unchnaged, still returns only the available BTC balance. It may be deprecated and removed in a future PR. --- proto/src/main/proto/grpc.proto | 48 +++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index d9e0a3973d8..901c94afa9e 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -275,6 +275,12 @@ message TradeInfo { service Wallets { rpc GetBalance (GetBalanceRequest) returns (GetBalanceReply) { } + rpc GetBalances (GetBalancesRequest) returns (GetBalancesReply) { + } + rpc GetBsqBalances (GetBsqBalancesRequest) returns (GetBsqBalancesReply) { + } + rpc GetBtcBalances (GetBtcBalancesRequest) returns (GetBtcBalancesReply) { + } rpc GetAddressBalance (GetAddressBalanceRequest) returns (GetAddressBalanceReply) { } rpc GetFundingAddresses (GetFundingAddressesRequest) returns (GetFundingAddressesReply) { @@ -296,6 +302,27 @@ message GetBalanceReply { uint64 balance = 1; } +message GetBalancesRequest { +} + +message GetBalancesReply { + BalancesInfo balances = 1; +} + +message GetBsqBalancesRequest { +} + +message GetBsqBalancesReply { + BsqBalanceInfo bsqBalanceInfo = 1; +} + +message GetBtcBalancesRequest { +} + +message GetBtcBalancesReply { + BtcBalanceInfo btcBalanceInfo = 1; +} + message GetAddressBalanceRequest { string address = 1; } @@ -340,6 +367,27 @@ message UnlockWalletRequest { message UnlockWalletReply { } +message BalancesInfo { + BsqBalanceInfo bsqBalanceInfo = 1; + BtcBalanceInfo btcBalanceInfo = 2; +} + +message BsqBalanceInfo { + uint64 availableConfirmedBalance = 1; + uint64 unverifiedBalance = 2; + uint64 unconfirmedChangeBalance = 3; + uint64 lockedForVotingBalance = 4; + uint64 lockupBondsBalance = 5; + uint64 unlockingBondsBalance = 6; +} + +message BtcBalanceInfo { + uint64 availableBalance = 1; + uint64 reservedBalance = 2; + uint64 totalAvailableBalance = 3; + uint64 lockedBalance = 4; +} + message AddressBalanceInfo { string address = 1; int64 balance = 2; From faf45ec301974b5a45af84b1e2246a6d2c1d02f4 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 13 Nov 2020 11:24:08 -0300 Subject: [PATCH 2/8] Add proto wrappers for serving bsq, btc or all balances This change adds proto wrappers for sending bsq, btc, or all balances to the CLI. They will be used in future api method implementations: getbsqbalance, getbtcbalance and getbalances. --- .../bisq/core/api/model/BalancesInfo.java | 42 +++++++++ .../bisq/core/api/model/BsqBalanceInfo.java | 87 +++++++++++++++++++ .../bisq/core/api/model/BtcBalanceInfo.java | 70 +++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 core/src/main/java/bisq/core/api/model/BalancesInfo.java create mode 100644 core/src/main/java/bisq/core/api/model/BsqBalanceInfo.java create mode 100644 core/src/main/java/bisq/core/api/model/BtcBalanceInfo.java diff --git a/core/src/main/java/bisq/core/api/model/BalancesInfo.java b/core/src/main/java/bisq/core/api/model/BalancesInfo.java new file mode 100644 index 00000000000..39179fde2b3 --- /dev/null +++ b/core/src/main/java/bisq/core/api/model/BalancesInfo.java @@ -0,0 +1,42 @@ +package bisq.core.api.model; + +import bisq.common.Payload; + +import lombok.Getter; + +@Getter +public class BalancesInfo implements Payload { + + private final BsqBalanceInfo bsqBalanceInfo; + private final BtcBalanceInfo btcBalanceInfo; + + public BalancesInfo(BsqBalanceInfo bsqBalanceInfo, BtcBalanceInfo btcBalanceInfo) { + this.bsqBalanceInfo = bsqBalanceInfo; + this.btcBalanceInfo = btcBalanceInfo; + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // PROTO BUFFER + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public bisq.proto.grpc.BalancesInfo toProtoMessage() { + return bisq.proto.grpc.BalancesInfo.newBuilder() + .setBsqBalanceInfo(bsqBalanceInfo.toProtoMessage()) + .setBtcBalanceInfo(btcBalanceInfo.toProtoMessage()) + .build(); + } + + public static BalancesInfo fromProto(bisq.proto.grpc.BalancesInfo proto) { + return new BalancesInfo(BsqBalanceInfo.fromProto(proto.getBsqBalanceInfo()), + BtcBalanceInfo.fromProto(proto.getBtcBalanceInfo())); + } + + @Override + public String toString() { + return "BalancesInfo{" + "\n" + + " " + bsqBalanceInfo.toString() + "\n" + + ", " + btcBalanceInfo.toString() + "\n" + + '}'; + } +} diff --git a/core/src/main/java/bisq/core/api/model/BsqBalanceInfo.java b/core/src/main/java/bisq/core/api/model/BsqBalanceInfo.java new file mode 100644 index 00000000000..ff314e087ba --- /dev/null +++ b/core/src/main/java/bisq/core/api/model/BsqBalanceInfo.java @@ -0,0 +1,87 @@ +package bisq.core.api.model; + +import bisq.common.Payload; + +import com.google.common.annotations.VisibleForTesting; + +import lombok.Getter; + +@Getter +public class BsqBalanceInfo implements Payload { + + // All balances are in BSQ satoshis. + private final long availableConfirmedBalance; + private final long unverifiedBalance; + private final long unconfirmedChangeBalance; + private final long lockedForVotingBalance; + private final long lockupBondsBalance; + private final long unlockingBondsBalance; + + public BsqBalanceInfo(long availableConfirmedBalance, + long unverifiedBalance, + long unconfirmedChangeBalance, + long lockedForVotingBalance, + long lockupBondsBalance, + long unlockingBondsBalance) { + this.availableConfirmedBalance = availableConfirmedBalance; + this.unverifiedBalance = unverifiedBalance; + this.unconfirmedChangeBalance = unconfirmedChangeBalance; + this.lockedForVotingBalance = lockedForVotingBalance; + this.lockupBondsBalance = lockupBondsBalance; + this.unlockingBondsBalance = unlockingBondsBalance; + } + + @VisibleForTesting + public static BsqBalanceInfo valueOf(long availableConfirmedBalance, + long unverifiedBalance, + long unconfirmedChangeBalance, + long lockedForVotingBalance, + long lockupBondsBalance, + long unlockingBondsBalance) { + // Convenience for creating a model instance instead of a proto. + return new BsqBalanceInfo(availableConfirmedBalance, + unverifiedBalance, + unconfirmedChangeBalance, + lockedForVotingBalance, + lockupBondsBalance, + unlockingBondsBalance); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // PROTO BUFFER + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public bisq.proto.grpc.BsqBalanceInfo toProtoMessage() { + return bisq.proto.grpc.BsqBalanceInfo.newBuilder() + .setAvailableConfirmedBalance(availableConfirmedBalance) + .setUnverifiedBalance(unverifiedBalance) + .setUnconfirmedChangeBalance(unconfirmedChangeBalance) + .setLockedForVotingBalance(lockedForVotingBalance) + .setLockupBondsBalance(lockupBondsBalance) + .setUnlockingBondsBalance(unlockingBondsBalance) + .build(); + + } + + public static BsqBalanceInfo fromProto(bisq.proto.grpc.BsqBalanceInfo proto) { + return new BsqBalanceInfo(proto.getAvailableConfirmedBalance(), + proto.getUnverifiedBalance(), + proto.getUnconfirmedChangeBalance(), + proto.getLockedForVotingBalance(), + proto.getLockupBondsBalance(), + proto.getUnlockingBondsBalance()); + } + + @Override + public String toString() { + return "BsqBalanceInfo{" + + "availableConfirmedBalance=" + availableConfirmedBalance + + ", unverifiedBalance=" + unverifiedBalance + + ", unconfirmedChangeBalance=" + unconfirmedChangeBalance + + ", lockedForVotingBalance=" + lockedForVotingBalance + + ", lockupBondsBalance=" + lockupBondsBalance + + ", unlockingBondsBalance=" + unlockingBondsBalance + + '}'; + } +} diff --git a/core/src/main/java/bisq/core/api/model/BtcBalanceInfo.java b/core/src/main/java/bisq/core/api/model/BtcBalanceInfo.java new file mode 100644 index 00000000000..6e8708c3e37 --- /dev/null +++ b/core/src/main/java/bisq/core/api/model/BtcBalanceInfo.java @@ -0,0 +1,70 @@ +package bisq.core.api.model; + +import bisq.common.Payload; + +import com.google.common.annotations.VisibleForTesting; + +import lombok.Getter; + +@Getter +public class BtcBalanceInfo implements Payload { + + // All balances are in BTC satoshis. + private final long availableBalance; + private final long reservedBalance; + private final long totalAvailableBalance; // available + reserved + private final long lockedBalance; + + public BtcBalanceInfo(long availableBalance, + long reservedBalance, + long totalAvailableBalance, + long lockedBalance) { + this.availableBalance = availableBalance; + this.reservedBalance = reservedBalance; + this.totalAvailableBalance = totalAvailableBalance; + this.lockedBalance = lockedBalance; + } + + @VisibleForTesting + public static BtcBalanceInfo valueOf(long availableBalance, + long reservedBalance, + long totalAvailableBalance, + long lockedBalance) { + // Convenience for creating a model instance instead of a proto. + return new BtcBalanceInfo(availableBalance, + reservedBalance, + totalAvailableBalance, + lockedBalance); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // PROTO BUFFER + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public bisq.proto.grpc.BtcBalanceInfo toProtoMessage() { + return bisq.proto.grpc.BtcBalanceInfo.newBuilder() + .setAvailableBalance(availableBalance) + .setReservedBalance(reservedBalance) + .setTotalAvailableBalance(totalAvailableBalance) + .setLockedBalance(lockedBalance) + .build(); + } + + public static BtcBalanceInfo fromProto(bisq.proto.grpc.BtcBalanceInfo proto) { + return new BtcBalanceInfo(proto.getAvailableBalance(), + proto.getReservedBalance(), + proto.getTotalAvailableBalance(), + proto.getLockedBalance()); + } + + @Override + public String toString() { + return "BtcBalanceInfo{" + + "availableBalance=" + availableBalance + + ", reservedBalance=" + reservedBalance + + ", totalAvailableBalance=" + totalAvailableBalance + + ", lockedBalance=" + lockedBalance + + '}'; + } +} From 4c03b463fefb472cf518f055ab17201bec57d352 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 13 Nov 2020 11:35:06 -0300 Subject: [PATCH 3/8] Define proto for api method 'getunusedbsqaddress' This change adds a proto to support a future api implementation for getting an unused, bsq funding address. --- proto/src/main/proto/grpc.proto | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 901c94afa9e..8f9ca52813c 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -283,6 +283,8 @@ service Wallets { } rpc GetAddressBalance (GetAddressBalanceRequest) returns (GetAddressBalanceReply) { } + rpc GetUnusedBsqAddress (GetUnusedBsqAddressRequest) returns (GetUnusedBsqAddressReply) { + } rpc GetFundingAddresses (GetFundingAddressesRequest) returns (GetFundingAddressesReply) { } rpc SetWalletPassword (SetWalletPasswordRequest) returns (SetWalletPasswordReply) { @@ -331,6 +333,13 @@ message GetAddressBalanceReply { AddressBalanceInfo addressBalanceInfo = 1; } +message GetUnusedBsqAddressRequest { +} + +message GetUnusedBsqAddressReply { + string address = 1; +} + message GetFundingAddressesRequest { } From 3e98910cc6e620ee2a56d001de9b53d984d25498 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 13 Nov 2020 11:44:42 -0300 Subject: [PATCH 4/8] Define proto fapi method 'sendbsq' This change adds the proto to support a future api implementation for transfering bsq. --- proto/src/main/proto/grpc.proto | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 8f9ca52813c..b18dab2e7ae 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -285,6 +285,8 @@ service Wallets { } rpc GetUnusedBsqAddress (GetUnusedBsqAddressRequest) returns (GetUnusedBsqAddressReply) { } + rpc SendBsq (SendBsqRequest) returns (SendBsqReply) { + } rpc GetFundingAddresses (GetFundingAddressesRequest) returns (GetFundingAddressesReply) { } rpc SetWalletPassword (SetWalletPasswordRequest) returns (SetWalletPasswordReply) { @@ -340,6 +342,14 @@ message GetUnusedBsqAddressReply { string address = 1; } +message SendBsqRequest { + string address = 1; + double amount = 2; +} + +message SendBsqReply { +} + message GetFundingAddressesRequest { } From 9f033ee572aa3afb41cf58e7aa6f64e7a7da9223 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 13 Nov 2020 12:03:15 -0300 Subject: [PATCH 5/8] Add proto fields to support trade fee currency choice This change adds proto support for paying maker fees in bsq or btc. The implementation will come in a future PR. - Added makerFeeCurrencyCode field to CreateOfferRequest proto. - Added isCurrencyForMakerFeeBtc field to OfferInfo proto wrapper. - Add takerFeeCurrencyCode field to TakeOfferRequest proto. --- proto/src/main/proto/grpc.proto | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index b18dab2e7ae..5005ad1eef8 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -81,6 +81,7 @@ message CreateOfferRequest { uint64 minAmount = 7; double buyerSecurityDeposit = 8; string paymentAccountId = 9; + string makerFeeCurrencyCode = 10; } message CreateOfferReply { @@ -105,13 +106,14 @@ message OfferInfo { uint64 volume = 8; uint64 minVolume = 9; uint64 buyerSecurityDeposit = 10; - string paymentAccountId = 11; - string paymentMethodId = 12; - string paymentMethodShortName = 13; - string baseCurrencyCode = 14; - string counterCurrencyCode = 15; - uint64 date = 16; - string state = 17; + bool isCurrencyForMakerFeeBtc = 11; + string paymentAccountId = 12; + string paymentMethodId = 13; + string paymentMethodShortName = 14; + string baseCurrencyCode = 15; + string counterCurrencyCode = 16; + uint64 date = 17; + string state = 18; } /////////////////////////////////////////////////////////////////////////////////////////// @@ -198,6 +200,7 @@ service Trades { message TakeOfferRequest { string offerId = 1; string paymentAccountId = 2; + string takerFeeCurrencyCode = 3; } message TakeOfferReply { From c1c099c8320c5f19bed6e7b4ac1c1f6594be0d78 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 13 Nov 2020 12:40:16 -0300 Subject: [PATCH 6/8] Implement and test api method 'getunusedbsqaddress' - Added new method to CLI, split some long msg strings into two lines, and added a white space after a braceless else statement. - Added the gRPC server boilerplate. - Added the core implementation. - Added a test, and moved method wallet tests into their own package. --- apitest/docs/build-run.md | 2 +- .../java/bisq/apitest/method/MethodTest.java | 5 ++ .../apitest/method/wallet/BsqWalletTest.java | 59 +++++++++++++++++++ .../method/{ => wallet}/GetBalanceTest.java | 6 +- .../{ => wallet}/WalletProtectionTest.java | 6 +- .../bisq/apitest/scenario/WalletTest.java | 2 +- cli/src/main/java/bisq/cli/CliMain.java | 21 +++++-- core/src/main/java/bisq/core/api/CoreApi.java | 4 ++ .../bisq/core/api/CoreWalletsService.java | 8 +++ .../bisq/daemon/grpc/GrpcWalletsService.java | 19 ++++++ 10 files changed, 124 insertions(+), 8 deletions(-) create mode 100644 apitest/src/test/java/bisq/apitest/method/wallet/BsqWalletTest.java rename apitest/src/test/java/bisq/apitest/method/{ => wallet}/GetBalanceTest.java (96%) rename apitest/src/test/java/bisq/apitest/method/{ => wallet}/WalletProtectionTest.java (98%) diff --git a/apitest/docs/build-run.md b/apitest/docs/build-run.md index 308fe02cf66..9d1165ca88e 100644 --- a/apitest/docs/build-run.md +++ b/apitest/docs/build-run.md @@ -48,7 +48,7 @@ To run all test cases in a package: To run a single test case: - $ ./gradlew :apitest:test --tests "bisq.apitest.method.GetBalanceTest" -DrunApiTests=true + $ ./gradlew :apitest:test --tests "bisq.apitest.method.wallet.GetBalanceTest" -DrunApiTests=true To run test cases from Intellij, add two JVM arguments to your JUnit launchers: diff --git a/apitest/src/test/java/bisq/apitest/method/MethodTest.java b/apitest/src/test/java/bisq/apitest/method/MethodTest.java index 43073ba995b..39cb0b5e971 100644 --- a/apitest/src/test/java/bisq/apitest/method/MethodTest.java +++ b/apitest/src/test/java/bisq/apitest/method/MethodTest.java @@ -26,6 +26,7 @@ import bisq.proto.grpc.GetOfferRequest; import bisq.proto.grpc.GetPaymentAccountsRequest; import bisq.proto.grpc.GetTradeRequest; +import bisq.proto.grpc.GetUnusedBsqAddressRequest; import bisq.proto.grpc.KeepFundsRequest; import bisq.proto.grpc.LockWalletRequest; import bisq.proto.grpc.MarketPriceRequest; @@ -107,6 +108,10 @@ protected final GetBalanceRequest createBalanceRequest() { return GetBalanceRequest.newBuilder().build(); } + protected final GetUnusedBsqAddressRequest createGetUnusedBsqAddressRequest() { + return GetUnusedBsqAddressRequest.newBuilder().build(); + } + protected final SetWalletPasswordRequest createSetWalletPasswordRequest(String password) { return SetWalletPasswordRequest.newBuilder().setPassword(password).build(); } diff --git a/apitest/src/test/java/bisq/apitest/method/wallet/BsqWalletTest.java b/apitest/src/test/java/bisq/apitest/method/wallet/BsqWalletTest.java new file mode 100644 index 00000000000..b4ae0bff0b8 --- /dev/null +++ b/apitest/src/test/java/bisq/apitest/method/wallet/BsqWalletTest.java @@ -0,0 +1,59 @@ +package bisq.apitest.method.wallet; + +import org.bitcoinj.core.LegacyAddress; +import org.bitcoinj.core.NetworkParameters; + +import lombok.extern.slf4j.Slf4j; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind; +import static bisq.apitest.config.BisqAppConfig.alicedaemon; +import static bisq.apitest.config.BisqAppConfig.seednode; +import static org.bitcoinj.core.NetworkParameters.PAYMENT_PROTOCOL_ID_MAINNET; +import static org.bitcoinj.core.NetworkParameters.PAYMENT_PROTOCOL_ID_REGTEST; +import static org.bitcoinj.core.NetworkParameters.PAYMENT_PROTOCOL_ID_TESTNET; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation; + + + +import bisq.apitest.method.MethodTest; + +// @Disabled +@Slf4j +@TestMethodOrder(OrderAnnotation.class) +public class BsqWalletTest extends MethodTest { + + @BeforeAll + public static void setUp() { + startSupportingApps(false, + true, + bitcoind, + seednode, + alicedaemon); + } + + @Test + @Order(1) + public void testGetUnusedBsqAddress() { + var request = createGetUnusedBsqAddressRequest(); + + String address = grpcStubs(alicedaemon).walletsService.getUnusedBsqAddress(request).getAddress(); + assertFalse(address.isEmpty()); + assertTrue(address.startsWith("B")); + + NetworkParameters networkParameters = LegacyAddress.getParametersFromAddress(address.substring(1)); + String addressNetwork = networkParameters.getPaymentProtocolId(); + assertNotEquals(PAYMENT_PROTOCOL_ID_MAINNET, addressNetwork); + // TODO Fix bug(?) causing the regtest bsq address network to be evaluated as 'testnet' here. + assertTrue(addressNetwork.equals(PAYMENT_PROTOCOL_ID_TESTNET) + || addressNetwork.equals(PAYMENT_PROTOCOL_ID_REGTEST)); + } + +} diff --git a/apitest/src/test/java/bisq/apitest/method/GetBalanceTest.java b/apitest/src/test/java/bisq/apitest/method/wallet/GetBalanceTest.java similarity index 96% rename from apitest/src/test/java/bisq/apitest/method/GetBalanceTest.java rename to apitest/src/test/java/bisq/apitest/method/wallet/GetBalanceTest.java index 1d44590837b..b31ccd99e02 100644 --- a/apitest/src/test/java/bisq/apitest/method/GetBalanceTest.java +++ b/apitest/src/test/java/bisq/apitest/method/wallet/GetBalanceTest.java @@ -15,7 +15,7 @@ * along with Bisq. If not, see . */ -package bisq.apitest.method; +package bisq.apitest.method.wallet; import bisq.proto.grpc.GetBalanceRequest; @@ -36,6 +36,10 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation; + + +import bisq.apitest.method.MethodTest; + @Disabled @Slf4j @TestMethodOrder(OrderAnnotation.class) diff --git a/apitest/src/test/java/bisq/apitest/method/WalletProtectionTest.java b/apitest/src/test/java/bisq/apitest/method/wallet/WalletProtectionTest.java similarity index 98% rename from apitest/src/test/java/bisq/apitest/method/WalletProtectionTest.java rename to apitest/src/test/java/bisq/apitest/method/wallet/WalletProtectionTest.java index 08547e9ebb9..82174f5195a 100644 --- a/apitest/src/test/java/bisq/apitest/method/WalletProtectionTest.java +++ b/apitest/src/test/java/bisq/apitest/method/wallet/WalletProtectionTest.java @@ -1,4 +1,4 @@ -package bisq.apitest.method; +package bisq.apitest.method.wallet; import io.grpc.StatusRuntimeException; @@ -18,6 +18,10 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation; + + +import bisq.apitest.method.MethodTest; + @SuppressWarnings("ResultOfMethodCallIgnored") @Disabled @Slf4j diff --git a/apitest/src/test/java/bisq/apitest/scenario/WalletTest.java b/apitest/src/test/java/bisq/apitest/scenario/WalletTest.java index ecd38dc2295..36e16142eaf 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/WalletTest.java +++ b/apitest/src/test/java/bisq/apitest/scenario/WalletTest.java @@ -35,7 +35,7 @@ import bisq.apitest.method.MethodTest; -import bisq.apitest.method.WalletProtectionTest; +import bisq.apitest.method.wallet.WalletProtectionTest; @Slf4j @TestMethodOrder(MethodOrderer.OrderAnnotation.class) diff --git a/cli/src/main/java/bisq/cli/CliMain.java b/cli/src/main/java/bisq/cli/CliMain.java index ec0e5e71bb6..cfeb1981db9 100644 --- a/cli/src/main/java/bisq/cli/CliMain.java +++ b/cli/src/main/java/bisq/cli/CliMain.java @@ -29,6 +29,7 @@ import bisq.proto.grpc.GetOffersRequest; import bisq.proto.grpc.GetPaymentAccountsRequest; import bisq.proto.grpc.GetTradeRequest; +import bisq.proto.grpc.GetUnusedBsqAddressRequest; import bisq.proto.grpc.GetVersionRequest; import bisq.proto.grpc.KeepFundsRequest; import bisq.proto.grpc.LockWalletRequest; @@ -90,6 +91,7 @@ private enum Method { getbalance, getaddressbalance, getfundingaddresses, + getunusedbsqaddress, lockwallet, unlockwallet, removewalletpassword, @@ -205,6 +207,12 @@ public static void run(String[] args) { out.println(formatAddressBalanceTbl(reply.getAddressBalanceInfoList())); return; } + case getunusedbsqaddress: { + var request = GetUnusedBsqAddressRequest.newBuilder().build(); + var reply = walletsService.getUnusedBsqAddress(request); + out.println(reply.getAddress()); + return; + } case createoffer: { if (nonOptionArgs.size() < 9) throw new IllegalArgumentException("incorrect parameter count," @@ -223,6 +231,7 @@ public static void run(String[] args) { marketPriceMargin = new BigDecimal(nonOptionArgs.get(7)); else fixedPrice = nonOptionArgs.get(7); + var securityDeposit = new BigDecimal(nonOptionArgs.get(8)); var request = CreateOfferRequest.newBuilder() @@ -283,7 +292,8 @@ public static void run(String[] args) { } case takeoffer: { if (nonOptionArgs.size() < 3) - throw new IllegalArgumentException("incorrect parameter count, expecting offer id, payment acct id"); + throw new IllegalArgumentException("incorrect parameter count, " + + " expecting offer id, payment acct id"); var offerId = nonOptionArgs.get(1); var paymentAccountId = nonOptionArgs.get(2); @@ -297,7 +307,8 @@ public static void run(String[] args) { } case gettrade: { if (nonOptionArgs.size() < 2) - throw new IllegalArgumentException("incorrect parameter count, expecting trade id, [,showcontract = true|false]"); + throw new IllegalArgumentException("incorrect parameter count, " + + " expecting trade id [,showcontract = true|false]"); var tradeId = nonOptionArgs.get(1); var showContract = false; @@ -352,7 +363,8 @@ public static void run(String[] args) { } case withdrawfunds: { if (nonOptionArgs.size() < 3) - throw new IllegalArgumentException("incorrect parameter count, expecting trade id, bitcoin wallet address"); + throw new IllegalArgumentException("incorrect parameter count, " + + " expecting trade id, bitcoin wallet address"); var tradeId = nonOptionArgs.get(1); var address = nonOptionArgs.get(2); @@ -485,6 +497,7 @@ private static void printHelp(OptionParser parser, PrintStream stream) { stream.format(rowFormat, "getbalance", "", "Get server wallet balance"); stream.format(rowFormat, "getaddressbalance", "address", "Get server wallet address balance"); stream.format(rowFormat, "getfundingaddresses", "", "Get BTC funding addresses"); + stream.format(rowFormat, "getunusedbsqaddress", "", "Get unused BSQ address"); stream.format(rowFormat, "createoffer", "payment acct id, buy | sell, currency code, \\", "Create and place an offer"); stream.format(rowFormat, "", "amount (btc), min amount, use mkt based price, \\", ""); stream.format(rowFormat, "", "fixed price (btc) | mkt price margin (%), \\", ""); @@ -493,7 +506,7 @@ private static void printHelp(OptionParser parser, PrintStream stream) { stream.format(rowFormat, "getoffer", "offer id", "Get current offer with id"); stream.format(rowFormat, "getoffers", "buy | sell, currency code", "Get current offers"); stream.format(rowFormat, "takeoffer", "offer id", "Take offer with id"); - stream.format(rowFormat, "gettrade", "trade id [,showcontract]", "Get trade summary or full contract"); + stream.format(rowFormat, "gettrade", "trade id [,showcontract = true|false]", "Get trade summary or full contract"); stream.format(rowFormat, "confirmpaymentstarted", "trade id", "Confirm payment started"); stream.format(rowFormat, "confirmpaymentreceived", "trade id", "Confirm payment received"); stream.format(rowFormat, "keepfunds", "trade id", "Keep received funds in Bisq wallet"); diff --git a/core/src/main/java/bisq/core/api/CoreApi.java b/core/src/main/java/bisq/core/api/CoreApi.java index 7cfcc5ce152..4e569d8a342 100644 --- a/core/src/main/java/bisq/core/api/CoreApi.java +++ b/core/src/main/java/bisq/core/api/CoreApi.java @@ -229,6 +229,10 @@ public List getFundingAddresses() { return walletsService.getFundingAddresses(); } + public String getUnusedBsqAddress() { + return walletsService.getUnusedBsqAddress(); + } + public void setWalletPassword(String password, String newPassword) { walletsService.setWalletPassword(password, newPassword); } diff --git a/core/src/main/java/bisq/core/api/CoreWalletsService.java b/core/src/main/java/bisq/core/api/CoreWalletsService.java index fc15ec5062a..37ec60d0d52 100644 --- a/core/src/main/java/bisq/core/api/CoreWalletsService.java +++ b/core/src/main/java/bisq/core/api/CoreWalletsService.java @@ -20,6 +20,7 @@ import bisq.core.api.model.AddressBalanceInfo; import bisq.core.btc.Balances; import bisq.core.btc.model.AddressEntry; +import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.btc.wallet.WalletsManager; @@ -55,6 +56,7 @@ class CoreWalletsService { private final Balances balances; private final WalletsManager walletsManager; + private final BsqWalletService bsqWalletService; private final BtcWalletService btcWalletService; @Nullable @@ -66,9 +68,11 @@ class CoreWalletsService { @Inject public CoreWalletsService(Balances balances, WalletsManager walletsManager, + BsqWalletService bsqWalletService, BtcWalletService btcWalletService) { this.balances = balances; this.walletsManager = walletsManager; + this.bsqWalletService = bsqWalletService; this.btcWalletService = btcWalletService; } @@ -134,6 +138,10 @@ List getFundingAddresses() { .collect(Collectors.toList()); } + String getUnusedBsqAddress() { + return bsqWalletService.getUnusedBsqAddressAsString(); + } + int getNumConfirmationsForMostRecentTransaction(String addressString) { Address address = getAddressEntry(addressString).getAddress(); TransactionConfidence confidence = btcWalletService.getConfidenceForAddress(address); diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java index 1b5cb42e4cc..81d0c9d3730 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java @@ -26,6 +26,8 @@ import bisq.proto.grpc.GetBalanceRequest; import bisq.proto.grpc.GetFundingAddressesReply; import bisq.proto.grpc.GetFundingAddressesRequest; +import bisq.proto.grpc.GetUnusedBsqAddressReply; +import bisq.proto.grpc.GetUnusedBsqAddressRequest; import bisq.proto.grpc.LockWalletReply; import bisq.proto.grpc.LockWalletRequest; import bisq.proto.grpc.RemoveWalletPasswordReply; @@ -109,6 +111,23 @@ public void getFundingAddresses(GetFundingAddressesRequest req, throw ex; } } + + @Override + public void getUnusedBsqAddress(GetUnusedBsqAddressRequest req, + StreamObserver responseObserver) { + try { + String address = coreApi.getUnusedBsqAddress(); + var reply = GetUnusedBsqAddressReply.newBuilder() + .setAddress(address) + .build(); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + } catch (IllegalStateException cause) { + var ex = new StatusRuntimeException(Status.UNKNOWN.withDescription(cause.getMessage())); + responseObserver.onError(ex); + throw ex; + } + } @Override public void setWalletPassword(SetWalletPasswordRequest req, From 7c2068e3c1d3a53ce45124c8a728a4aeec96d28a Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 13 Nov 2020 12:45:40 -0300 Subject: [PATCH 7/8] Add teardown to test case --- .../test/java/bisq/apitest/method/wallet/BsqWalletTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apitest/src/test/java/bisq/apitest/method/wallet/BsqWalletTest.java b/apitest/src/test/java/bisq/apitest/method/wallet/BsqWalletTest.java index b4ae0bff0b8..406308a919c 100644 --- a/apitest/src/test/java/bisq/apitest/method/wallet/BsqWalletTest.java +++ b/apitest/src/test/java/bisq/apitest/method/wallet/BsqWalletTest.java @@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -56,4 +57,8 @@ public void testGetUnusedBsqAddress() { || addressNetwork.equals(PAYMENT_PROTOCOL_ID_REGTEST)); } + @AfterAll + public static void tearDown() { + tearDownScaffold(); + } } From 8dc1a74c8b5e11312a5b3e9db5581981dc70c68b Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 13 Nov 2020 12:55:48 -0300 Subject: [PATCH 8/8] Remove trailing spaces in blank line --- daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java index 81d0c9d3730..3e636a663d8 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java @@ -111,7 +111,7 @@ public void getFundingAddresses(GetFundingAddressesRequest req, throw ex; } } - + @Override public void getUnusedBsqAddress(GetUnusedBsqAddressRequest req, StreamObserver responseObserver) {