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

Append nullable withdrawalTxId field to Trade proto message #4937

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 60 additions & 7 deletions apitest/src/test/java/bisq/apitest/method/MethodTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@
import bisq.proto.grpc.RegisterDisputeAgentRequest;
import bisq.proto.grpc.RemoveWalletPasswordRequest;
import bisq.proto.grpc.SendBsqRequest;
import bisq.proto.grpc.SendBtcRequest;
import bisq.proto.grpc.SetTxFeeRatePreferenceRequest;
import bisq.proto.grpc.SetWalletPasswordRequest;
import bisq.proto.grpc.TakeOfferRequest;
import bisq.proto.grpc.TradeInfo;
import bisq.proto.grpc.TxInfo;
import bisq.proto.grpc.UnlockWalletRequest;
import bisq.proto.grpc.UnsetTxFeeRatePreferenceRequest;
import bisq.proto.grpc.WithdrawFundsRequest;
Expand Down Expand Up @@ -160,8 +162,26 @@ protected final GetUnusedBsqAddressRequest createGetUnusedBsqAddressRequest() {
return GetUnusedBsqAddressRequest.newBuilder().build();
}

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

protected final SendBtcRequest createSendBtcRequest(String address,
String amount,
String txFeeRate,
String memo) {
return SendBtcRequest.newBuilder()
.setAddress(address)
.setAmount(amount)
.setTxFeeRate(txFeeRate)
.setMemo(memo)
.build();
}

protected final GetFundingAddressesRequest createGetFundingAddressesRequest() {
Expand Down Expand Up @@ -208,10 +228,13 @@ protected final KeepFundsRequest createKeepFundsRequest(String tradeId) {
.build();
}

protected final WithdrawFundsRequest createWithdrawFundsRequest(String tradeId, String address) {
protected final WithdrawFundsRequest createWithdrawFundsRequest(String tradeId,
String address,
String memo) {
return WithdrawFundsRequest.newBuilder()
.setTradeId(tradeId)
.setAddress(address)
.setMemo(memo)
.build();
}

Expand Down Expand Up @@ -247,9 +270,36 @@ protected final String getUnusedBsqAddress(BisqAppConfig bisqAppConfig) {
return grpcStubs(bisqAppConfig).walletsService.getUnusedBsqAddress(createGetUnusedBsqAddressRequest()).getAddress();
}

protected final void sendBsq(BisqAppConfig bisqAppConfig, String address, String amount) {
protected final TxInfo sendBsq(BisqAppConfig bisqAppConfig,
String address,
String amount) {
return sendBsq(bisqAppConfig, address, amount, "");
}

protected final TxInfo sendBsq(BisqAppConfig bisqAppConfig,
String address,
String amount,
String txFeeRate) {
//noinspection ResultOfMethodCallIgnored
return grpcStubs(bisqAppConfig).walletsService.sendBsq(createSendBsqRequest(address,
amount,
txFeeRate))
.getTxInfo();
}

protected final TxInfo sendBtc(BisqAppConfig bisqAppConfig, String address, String amount) {
return sendBtc(bisqAppConfig, address, amount, "", "");
}

protected final TxInfo sendBtc(BisqAppConfig bisqAppConfig,
String address,
String amount,
String txFeeRate,
String memo) {
//noinspection ResultOfMethodCallIgnored
grpcStubs(bisqAppConfig).walletsService.sendBsq(createSendBsqRequest(address, amount));
return grpcStubs(bisqAppConfig).walletsService.sendBtc(
createSendBtcRequest(address, amount, txFeeRate, memo))
.getTxInfo();
}

protected final String getUnusedBtcAddress(BisqAppConfig bisqAppConfig) {
Expand Down Expand Up @@ -354,8 +404,11 @@ protected final void keepFunds(BisqAppConfig bisqAppConfig, String tradeId) {
}

@SuppressWarnings("ResultOfMethodCallIgnored")
protected final void withdrawFunds(BisqAppConfig bisqAppConfig, String tradeId, String address) {
var req = createWithdrawFundsRequest(tradeId, address);
protected final void withdrawFunds(BisqAppConfig bisqAppConfig,
String tradeId,
String address,
String memo) {
var req = createWithdrawFundsRequest(tradeId, address, memo);
grpcStubs(bisqAppConfig).tradesService.withdrawFunds(req);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ protected final void logTrade(Logger log,
TestInfo testInfo,
String description,
TradeInfo trade) {
log.info(String.format("%s %s%n%s",
testName(testInfo),
description.toUpperCase(),
format(trade)));
if (log.isDebugEnabled()) {
log.debug(String.format("%s %s%n%s",
testName(testInfo),
description.toUpperCase(),
format(trade)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public void testBobsBtcWithdrawalToExternalAddress(final TestInfo testInfo) {
logTrade(log, testInfo, "Bob's view before withdrawing funds to external wallet", trade);

String toAddress = bitcoinCli.getNewBtcAddress();
withdrawFunds(bobdaemon, tradeId, toAddress);
withdrawFunds(bobdaemon, tradeId, toAddress, "to whom it may concern");

genBtcBlocksThenWait(1, 2250);

Expand All @@ -158,7 +158,7 @@ public void testBobsBtcWithdrawalToExternalAddress(final TestInfo testInfo) {
verifyExpectedProtocolStatus(trade);
logTrade(log, testInfo, "Bob's view after withdrawing funds to external wallet", trade);
BtcBalanceInfo currentBalance = getBtcBalances(bobdaemon);
log.info("{} Bob's current available balance: {} BTC",
log.debug("{} Bob's current available balance: {} BTC",
testName(testInfo),
formatSatoshis(currentBalance.getAvailableBalance()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public void testInitialBsqBalances(final TestInfo testInfo) {
@Order(3)
public void testSendBsqAndCheckBalancesBeforeGeneratingBtcBlock(final TestInfo testInfo) {
String bobsBsqAddress = getUnusedBsqAddress(bobdaemon);
sendBsq(alicedaemon, bobsBsqAddress, SEND_BSQ_AMOUNT);
sendBsq(alicedaemon, bobsBsqAddress, SEND_BSQ_AMOUNT, "100");
sleep(2000);

BsqBalanceInfo alicesBsqBalances = getBsqBalances(alicedaemon);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static bisq.cli.TableFormat.formatBtcBalanceInfoTbl;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation;


Expand Down Expand Up @@ -92,6 +93,42 @@ public void testFundAlicesBtcWallet(final TestInfo testInfo) {
formatBtcBalanceInfoTbl(btcBalanceInfo));
}

@Test
@Order(3)
public void testAliceSendBTCToBob(TestInfo testInfo) {
String bobsBtcAddress = getUnusedBtcAddress(bobdaemon);
log.debug("Sending 5.5 BTC From Alice to Bob @ {}", bobsBtcAddress);

sendBtc(alicedaemon,
bobsBtcAddress,
"5.50",
"100",
"to whom it may concern");
genBtcBlocksThenWait(1, 3000);

BtcBalanceInfo alicesBalances = getBtcBalances(alicedaemon);

log.debug("{} Alice's BTC Balances:\n{}",
testName(testInfo),
formatBtcBalanceInfoTbl(alicesBalances));
bisq.core.api.model.BtcBalanceInfo alicesExpectedBalances =
bisq.core.api.model.BtcBalanceInfo.valueOf(700000000,
0,
700000000,
0);
verifyBtcBalances(alicesExpectedBalances, alicesBalances);

BtcBalanceInfo bobsBalances = getBtcBalances(bobdaemon);
log.debug("{} Bob's BTC Balances:\n{}",
testName(testInfo),
formatBtcBalanceInfoTbl(bobsBalances));
// We cannot (?) predict the exact tx size and calculate how much in tx fees were
// deducted from the 5.5 BTC sent to Bob, but we do know Bob should have something
// between 15.49978000 and 15.49978100 BTC.
assertTrue(bobsBalances.getAvailableBalance() >= 1549978000);
assertTrue(bobsBalances.getAvailableBalance() <= 1549978100);
}

@AfterAll
public static void tearDown() {
tearDownScaffold();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public void testBtcWalletFunding(final TestInfo testInfo) {

btcWalletTest.testInitialBtcBalances(testInfo);
btcWalletTest.testFundAlicesBtcWallet(testInfo);
btcWalletTest.testAliceSendBTCToBob(testInfo);
}

@Test
Expand Down
102 changes: 78 additions & 24 deletions cli/src/main/java/bisq/cli/CliMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@
import bisq.proto.grpc.RegisterDisputeAgentRequest;
import bisq.proto.grpc.RemoveWalletPasswordRequest;
import bisq.proto.grpc.SendBsqRequest;
import bisq.proto.grpc.SendBtcRequest;
import bisq.proto.grpc.SetTxFeeRatePreferenceRequest;
import bisq.proto.grpc.SetWalletPasswordRequest;
import bisq.proto.grpc.TakeOfferRequest;
import bisq.proto.grpc.TxInfo;
import bisq.proto.grpc.UnlockWalletRequest;
import bisq.proto.grpc.UnsetTxFeeRatePreferenceRequest;
import bisq.proto.grpc.WithdrawFundsRequest;
Expand Down Expand Up @@ -110,6 +112,7 @@ private enum Method {
getfundingaddresses,
getunusedbsqaddress,
sendbsq,
sendbtc,
gettxfeerate,
settxfeerate,
unsettxfeerate,
Expand Down Expand Up @@ -259,19 +262,50 @@ public static void run(String[] args) {
throw new IllegalArgumentException("no bsq amount specified");

var amount = nonOptionArgs.get(2);
verifyStringIsValidDecimal(amount);

try {
Double.parseDouble(amount);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(format("'%s' is not a number", amount));
}
var txFeeRate = nonOptionArgs.size() == 4 ? nonOptionArgs.get(3) : "";
if (!txFeeRate.isEmpty())
verifyStringIsValidLong(txFeeRate);

var request = SendBsqRequest.newBuilder()
.setAddress(address)
.setAmount(amount)
.setTxFeeRate(txFeeRate)
.build();
var reply = walletsService.sendBsq(request);
TxInfo txInfo = reply.getTxInfo();
out.printf("%s bsq sent to %s in tx %s%n", amount, address, txInfo.getId());
return;
}
case sendbtc: {
if (nonOptionArgs.size() < 2)
throw new IllegalArgumentException("no btc address specified");

var address = nonOptionArgs.get(1);

if (nonOptionArgs.size() < 3)
throw new IllegalArgumentException("no btc amount specified");

var amount = nonOptionArgs.get(2);
verifyStringIsValidDecimal(amount);

// TODO Find a better way to handle the two optional parameters.
var txFeeRate = nonOptionArgs.size() >= 4 ? nonOptionArgs.get(3) : "";
if (!txFeeRate.isEmpty())
verifyStringIsValidLong(txFeeRate);

var memo = nonOptionArgs.size() == 5 ? nonOptionArgs.get(4) : "";

var request = SendBtcRequest.newBuilder()
.setAddress(address)
.setAmount(amount)
.setTxFeeRate(txFeeRate)
.setMemo(memo)
.build();
walletsService.sendBsq(request);
out.printf("%s BSQ sent to %s%n", amount, address);
var reply = walletsService.sendBtc(request);
TxInfo txInfo = reply.getTxInfo();
out.printf("%s btc sent to %s in tx %s%n", amount, address, txInfo.getId());
return;
}
case gettxfeerate: {
Expand All @@ -284,13 +318,7 @@ public static void run(String[] args) {
if (nonOptionArgs.size() < 2)
throw new IllegalArgumentException("no tx fee rate specified");

long txFeeRate;
try {
txFeeRate = Long.parseLong(nonOptionArgs.get(2));
} catch (NumberFormatException e) {
throw new IllegalArgumentException(format("'%s' is not a number", nonOptionArgs.get(2)));
}

var txFeeRate = toLong(nonOptionArgs.get(2));
var request = SetTxFeeRatePreferenceRequest.newBuilder()
.setTxFeeRatePreference(txFeeRate)
.build();
Expand Down Expand Up @@ -472,16 +500,21 @@ public static void run(String[] args) {
case withdrawfunds: {
if (nonOptionArgs.size() < 3)
throw new IllegalArgumentException("incorrect parameter count, "
+ " expecting trade id, bitcoin wallet address");
+ " expecting trade id, bitcoin wallet address [,\"memo\"]");

var tradeId = nonOptionArgs.get(1);
var address = nonOptionArgs.get(2);
// A multi-word memo must be double quoted.
var memo = nonOptionArgs.size() == 4
? nonOptionArgs.get(3)
: "";
var request = WithdrawFundsRequest.newBuilder()
.setTradeId(tradeId)
.setAddress(address)
.setMemo(memo)
.build();
tradesService.withdrawFunds(request);
out.printf("funds from trade %s sent to btc address %s%n", tradeId, address);
out.printf("trade %s funds sent to btc address %s%n", tradeId, address);
return;
}
case getpaymentmethods: {
Expand Down Expand Up @@ -560,12 +593,7 @@ public static void run(String[] args) {
if (nonOptionArgs.size() < 3)
throw new IllegalArgumentException("no unlock timeout specified");

long timeout;
try {
timeout = Long.parseLong(nonOptionArgs.get(2));
} catch (NumberFormatException e) {
throw new IllegalArgumentException(format("'%s' is not a number", nonOptionArgs.get(2)));
}
var timeout = toLong(nonOptionArgs.get(2));
var request = UnlockWalletRequest.newBuilder()
.setPassword(nonOptionArgs.get(1))
.setTimeout(timeout).build();
Expand Down Expand Up @@ -627,6 +655,30 @@ private static Method getMethodFromCmd(String methodName) {
return Method.valueOf(methodName.toLowerCase());
}

private static void verifyStringIsValidDecimal(String param) {
try {
Double.parseDouble(param);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException(format("'%s' is not a number", param));
}
}

private static void verifyStringIsValidLong(String param) {
try {
Long.parseLong(param);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException(format("'%s' is not a number", param));
}
}

private static long toLong(String param) {
try {
return Long.parseLong(param);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException(format("'%s' is not a number", param));
}
}

private static File saveFileToDisk(String prefix,
@SuppressWarnings("SameParameterValue") String suffix,
String text) {
Expand Down Expand Up @@ -663,7 +715,8 @@ private static void printHelp(OptionParser parser, PrintStream stream) {
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, "sendbsq", "address, amount", "Send BSQ");
stream.format(rowFormat, "sendbsq", "address, amount [,tx fee rate (sats/byte)]", "Send BSQ");
stream.format(rowFormat, "sendbtc", "address, amount [,tx fee rate (sats/byte), \"memo\"]", "Send BTC");
stream.format(rowFormat, "gettxfeerate", "", "Get current tx fee rate in sats/byte");
stream.format(rowFormat, "settxfeerate", "satoshis (per byte)", "Set custom tx fee rate in sats/byte");
stream.format(rowFormat, "unsettxfeerate", "", "Unset custom tx fee rate");
Expand All @@ -679,7 +732,8 @@ private static void printHelp(OptionParser parser, PrintStream stream) {
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");
stream.format(rowFormat, "withdrawfunds", "trade id, bitcoin wallet address", "Withdraw received funds to external wallet address");
stream.format(rowFormat, "withdrawfunds", "trade id, bitcoin wallet address [,\"memo\"]",
"Withdraw received funds to external wallet address");
stream.format(rowFormat, "getpaymentmethods", "", "Get list of supported payment account method ids");
stream.format(rowFormat, "getpaymentacctform", "payment method id", "Get a new payment account form");
stream.format(rowFormat, "createpaymentacct", "path to payment account form", "Create a new payment account");
Expand Down
Loading