Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stub out api method 'sendbsq' in core #4800

Merged
merged 12 commits into from
Dec 3, 2020
2 changes: 1 addition & 1 deletion apitest/docs/build-run.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
68 changes: 66 additions & 2 deletions apitest/src/test/java/bisq/apitest/method/MethodTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,31 @@

package bisq.apitest.method;

import bisq.proto.grpc.AddressBalanceInfo;
import bisq.proto.grpc.BalancesInfo;
import bisq.proto.grpc.BsqBalanceInfo;
import bisq.proto.grpc.BtcBalanceInfo;
import bisq.proto.grpc.CancelOfferRequest;
import bisq.proto.grpc.ConfirmPaymentReceivedRequest;
import bisq.proto.grpc.ConfirmPaymentStartedRequest;
import bisq.proto.grpc.CreatePaymentAccountRequest;
import bisq.proto.grpc.GetAddressBalanceRequest;
import bisq.proto.grpc.GetBalanceRequest;
import bisq.proto.grpc.GetBalancesRequest;
import bisq.proto.grpc.GetBsqBalancesRequest;
import bisq.proto.grpc.GetBtcBalancesRequest;
import bisq.proto.grpc.GetFundingAddressesRequest;
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;
import bisq.proto.grpc.OfferInfo;
import bisq.proto.grpc.RegisterDisputeAgentRequest;
import bisq.proto.grpc.RemoveWalletPasswordRequest;
import bisq.proto.grpc.SendBsqRequest;
import bisq.proto.grpc.SetWalletPasswordRequest;
import bisq.proto.grpc.TakeOfferRequest;
import bisq.proto.grpc.TradeInfo;
Expand Down Expand Up @@ -103,10 +113,27 @@ public static void startSupportingApps(boolean registerDisputeAgents,

// Convenience methods for building gRPC request objects

@Deprecated
protected final GetBalanceRequest createBalanceRequest() {
return GetBalanceRequest.newBuilder().build();
}

protected final GetBalancesRequest createGetBalancesRequest() {
return GetBalancesRequest.newBuilder().build();
}

protected final GetAddressBalanceRequest createGetAddressBalanceRequest(String address) {
return GetAddressBalanceRequest.newBuilder().setAddress(address).build();
}

protected final GetBsqBalancesRequest createGetBsqBalancesRequest() {
return GetBsqBalancesRequest.newBuilder().build();
}

protected final GetBtcBalancesRequest createBtcBalancesRequest() {
return GetBtcBalancesRequest.newBuilder().build();
}

protected final SetWalletPasswordRequest createSetWalletPasswordRequest(String password) {
return SetWalletPasswordRequest.newBuilder().setPassword(password).build();
}
Expand All @@ -127,6 +154,14 @@ protected final LockWalletRequest createLockWalletRequest() {
return LockWalletRequest.newBuilder().build();
}

protected final GetUnusedBsqAddressRequest createGetUnusedBsqAddressRequest() {
return GetUnusedBsqAddressRequest.newBuilder().build();
}

protected final SendBsqRequest createSendBsqRequest(String address, double amount) {
return SendBsqRequest.newBuilder().setAddress(address).setAmount(amount).build();
}

protected final GetFundingAddressesRequest createGetFundingAddressesRequest() {
return GetFundingAddressesRequest.newBuilder().build();
}
Expand All @@ -143,8 +178,12 @@ protected final CancelOfferRequest createCancelOfferRequest(String offerId) {
return CancelOfferRequest.newBuilder().setId(offerId).build();
}

protected final TakeOfferRequest createTakeOfferRequest(String offerId, String paymentAccountId) {
return TakeOfferRequest.newBuilder().setOfferId(offerId).setPaymentAccountId(paymentAccountId).build();
protected final TakeOfferRequest createTakeOfferRequest(String offerId,
String paymentAccountId) {
return TakeOfferRequest.newBuilder()
.setOfferId(offerId)
.setPaymentAccountId(paymentAccountId)
.build();
}

protected final GetTradeRequest createGetTradeRequest(String tradeId) {
Expand Down Expand Up @@ -174,10 +213,27 @@ protected final WithdrawFundsRequest createWithdrawFundsRequest(String tradeId,

// Convenience methods for calling frequently used & thoroughly tested gRPC services.

@Deprecated
protected final long getBalance(BisqAppConfig bisqAppConfig) {
return grpcStubs(bisqAppConfig).walletsService.getBalance(createBalanceRequest()).getBalance();
}

protected final BalancesInfo getBalances(BisqAppConfig bisqAppConfig) {
return grpcStubs(bisqAppConfig).walletsService.getBalances(createGetBalancesRequest()).getBalances();
}

protected final BsqBalanceInfo getBsqBalances(BisqAppConfig bisqAppConfig) {
return grpcStubs(bisqAppConfig).walletsService.getBsqBalances(createGetBsqBalancesRequest()).getBsqBalanceInfo();
}

protected final BtcBalanceInfo getBtcBalances(BisqAppConfig bisqAppConfig) {
return grpcStubs(bisqAppConfig).walletsService.getBtcBalances(createBtcBalancesRequest()).getBtcBalanceInfo();
}

protected final AddressBalanceInfo getAddressBalance(BisqAppConfig bisqAppConfig, String address) {
return grpcStubs(bisqAppConfig).walletsService.getAddressBalance(createGetAddressBalanceRequest(address)).getAddressBalanceInfo();
}

protected final void unlockWallet(BisqAppConfig bisqAppConfig, String password, long timeout) {
//noinspection ResultOfMethodCallIgnored
grpcStubs(bisqAppConfig).walletsService.unlockWallet(createUnlockWalletRequest(password, timeout));
Expand All @@ -188,6 +244,14 @@ protected final void lockWallet(BisqAppConfig bisqAppConfig) {
grpcStubs(bisqAppConfig).walletsService.lockWallet(createLockWalletRequest());
}

protected final String getUnusedBsqAddress(BisqAppConfig bisqAppConfig) {
return grpcStubs(bisqAppConfig).walletsService.getUnusedBsqAddress(createGetUnusedBsqAddressRequest()).getAddress();
}

protected final void sendBsq(BisqAppConfig bisqAppConfig, String address, double amount) {
grpcStubs(bisqAppConfig).walletsService.sendBsq(createSendBsqRequest(address, amount));
}

protected final String getUnusedBtcAddress(BisqAppConfig bisqAppConfig) {
//noinspection OptionalGetWithoutIsPresent
return grpcStubs(bisqAppConfig).walletsService.getFundingAddresses(createGetFundingAddressesRequest())
Expand Down
244 changes: 244 additions & 0 deletions apitest/src/test/java/bisq/apitest/method/wallet/BsqWalletTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
package bisq.apitest.method.wallet;

import bisq.proto.grpc.BsqBalanceInfo;

import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.core.NetworkParameters;

import lombok.extern.slf4j.Slf4j;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
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.arbdaemon;
import static bisq.apitest.config.BisqAppConfig.bobdaemon;
import static bisq.apitest.config.BisqAppConfig.seednode;
import static bisq.cli.TableFormat.formatBsqBalanceInfoTbl;
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.assertEquals;
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.config.BisqAppConfig;
import bisq.apitest.method.MethodTest;

@Disabled
@Slf4j
@TestMethodOrder(OrderAnnotation.class)
public class BsqWalletTest extends MethodTest {

// Alice's regtest BSQ wallet is initialized with 1,000,000 BSQ.
private static final bisq.core.api.model.BsqBalanceInfo ALICES_INITIAL_BSQ_BALANCES =
expectedBsqBalanceModel(100000000,
0,
0,
0,
0,
0);

// Bob's regtest BSQ wallet is initialized with 1,500,000 BSQ.
private static final bisq.core.api.model.BsqBalanceInfo BOBS_INITIAL_BSQ_BALANCES =
expectedBsqBalanceModel(150000000,
0,
0,
0,
0,
0);

private static final double SEND_BSQ_AMOUNT = 25000.50;

@BeforeAll
public static void setUp() {
startSupportingApps(false,
true,
bitcoind,
seednode,
arbdaemon,
alicedaemon,
bobdaemon);
}

@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));
}

@Test
@Order(2)
public void testInitialBsqBalances(final TestInfo testInfo) {
BsqBalanceInfo alicesBsqBalances = getBsqBalances(alicedaemon);
log.info("{} -> Alice's BSQ Initial Balances -> \n{}",
testName(testInfo),
formatBsqBalanceInfoTbl(alicesBsqBalances));
verifyBsqBalances(ALICES_INITIAL_BSQ_BALANCES, alicesBsqBalances);

BsqBalanceInfo bobsBsqBalances = getBsqBalances(bobdaemon);
log.info("{} -> Bob's BSQ Initial Balances -> \n{}",
testName(testInfo),
formatBsqBalanceInfoTbl(bobsBsqBalances));
verifyBsqBalances(BOBS_INITIAL_BSQ_BALANCES, bobsBsqBalances);
}

@Test
@Order(3)
public void testSendBsqAndCheckBalancesBeforeGeneratingBtcBlock(final TestInfo testInfo) {
String bobsBsqAddress = getUnusedBsqAddress(bobdaemon);
sendBsq(alicedaemon, bobsBsqAddress, SEND_BSQ_AMOUNT);
sleep(2000);

BsqBalanceInfo alicesBsqBalances = getBsqBalances(alicedaemon);
BsqBalanceInfo bobsBsqBalances = waitForNonZeroUnverifiedBalance(bobdaemon);

log.info("BSQ Balances Before BTC Block Gen...");
printBobAndAliceBsqBalances(testInfo,
bobsBsqBalances,
alicesBsqBalances,
alicedaemon);

verifyBsqBalances(expectedBsqBalanceModel(150000000,
2500050,
0,
0,
0,
0),
bobsBsqBalances);

verifyBsqBalances(expectedBsqBalanceModel(97499950,
97499950,
97499950,
0,
0,
0),
alicesBsqBalances);
}

@Test
@Order(4)
public void testBalancesAfterSendingBsqAndGeneratingBtcBlock(final TestInfo testInfo) {
// There is a wallet persist delay; we have to
// wait for both wallets to be saved to disk.
genBtcBlocksThenWait(1, 4000);

BsqBalanceInfo alicesBsqBalances = getBsqBalances(alicedaemon);
BsqBalanceInfo bobsBsqBalances = waitForNewAvailableConfirmedBalance(bobdaemon, 150000000);

log.info("See Available Confirmed BSQ Balances...");
printBobAndAliceBsqBalances(testInfo,
bobsBsqBalances,
alicesBsqBalances,
alicedaemon);

verifyBsqBalances(expectedBsqBalanceModel(152500050,
0,
0,
0,
0,
0),
bobsBsqBalances);

verifyBsqBalances(expectedBsqBalanceModel(97499950,
0,
0,
0,
0,
0),
alicesBsqBalances);
}

@AfterAll
public static void tearDown() {
tearDownScaffold();
}

private void verifyBsqBalances(bisq.core.api.model.BsqBalanceInfo expected,
BsqBalanceInfo actual) {
assertEquals(expected.getAvailableConfirmedBalance(), actual.getAvailableConfirmedBalance());
assertEquals(expected.getUnverifiedBalance(), actual.getUnverifiedBalance());
assertEquals(expected.getUnconfirmedChangeBalance(), actual.getUnconfirmedChangeBalance());
assertEquals(expected.getLockedForVotingBalance(), actual.getLockedForVotingBalance());
assertEquals(expected.getLockupBondsBalance(), actual.getLockupBondsBalance());
assertEquals(expected.getUnlockingBondsBalance(), actual.getUnlockingBondsBalance());
}

private BsqBalanceInfo waitForNonZeroUnverifiedBalance(BisqAppConfig daemon) {
// A BSQ recipient needs to wait for her daemon to detect a new tx.
// Loop here until her unverifiedBalance != 0, or give up after 15 seconds.
// A slow test is preferred over a flaky test.
BsqBalanceInfo bsqBalance = getBsqBalances(daemon);
for (int numRequests = 1; numRequests <= 15 && bsqBalance.getUnverifiedBalance() == 0; numRequests++) {
sleep(1000);
bsqBalance = getBsqBalances(daemon);
}
return bsqBalance;
}

private BsqBalanceInfo waitForNewAvailableConfirmedBalance(BisqAppConfig daemon,
long staleBalance) {
BsqBalanceInfo bsqBalance = getBsqBalances(daemon);
for (int numRequests = 1;
numRequests <= 15 && bsqBalance.getAvailableConfirmedBalance() == staleBalance;
numRequests++) {
sleep(1000);
bsqBalance = getBsqBalances(daemon);
}
return bsqBalance;
}

@SuppressWarnings("SameParameterValue")
private void printBobAndAliceBsqBalances(final TestInfo testInfo,
BsqBalanceInfo bobsBsqBalances,
BsqBalanceInfo alicesBsqBalances,
BisqAppConfig senderApp) {
log.info("{} -> Bob's BSQ Balances After {} {} BSQ-> \n{}",
testName(testInfo),
senderApp.equals(bobdaemon) ? "Sending" : "Receiving",
SEND_BSQ_AMOUNT,
formatBsqBalanceInfoTbl(bobsBsqBalances));

log.info("{} -> Alice's Balances After {} {} BSQ-> \n{}",
testName(testInfo),
senderApp.equals(alicedaemon) ? "Sending" : "Receiving",
SEND_BSQ_AMOUNT,
formatBsqBalanceInfoTbl(alicesBsqBalances));
}

@SuppressWarnings("SameParameterValue")
private static bisq.core.api.model.BsqBalanceInfo expectedBsqBalanceModel(long availableConfirmedBalance,
long unverifiedBalance,
long unconfirmedChangeBalance,
long lockedForVotingBalance,
long lockupBondsBalance,
long unlockingBondsBalance) {
return bisq.core.api.model.BsqBalanceInfo.valueOf(availableConfirmedBalance,
unverifiedBalance,
unconfirmedChangeBalance,
lockedForVotingBalance,
lockupBondsBalance,
unlockingBondsBalance);
}
}
Loading