Merge pull request #4908 from chimp1984/add-memo-field-at-step4

Add memo field at step4
This commit is contained in:
Christoph Atteneder 2020-12-08 16:35:16 +01:00 committed by GitHub
commit 6431d639ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 65 additions and 25 deletions

View file

@ -45,6 +45,8 @@ import java.util.function.Consumer;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
/**
* Provides high level interface to functionality of core Bisq features.
* E.g. useful for different APIs to access data of different domains of Bisq.
@ -208,8 +210,8 @@ public class CoreApi {
coreTradesService.keepFunds(tradeId);
}
public void withdrawFunds(String tradeId, String address) {
coreTradesService.withdrawFunds(tradeId, address);
public void withdrawFunds(String tradeId, String address, @Nullable String memo) {
coreTradesService.withdrawFunds(tradeId, address, memo);
}
public Trade getTrade(String tradeId) {

View file

@ -41,6 +41,8 @@ import java.util.function.Consumer;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import static bisq.core.btc.model.AddressEntry.Context.TRADE_PAYOUT;
import static java.lang.String.format;
@ -154,7 +156,7 @@ class CoreTradesService {
tradeManager.onTradeCompleted(trade);
}
void withdrawFunds(String tradeId, String toAddress) {
void withdrawFunds(String tradeId, String toAddress, @Nullable String memo) {
// An encrypted wallet must be unlocked for this operation.
verifyTradeIsNotClosed(tradeId);
var trade = getOpenTrade(tradeId).orElseThrow(() ->
@ -184,6 +186,7 @@ class CoreTradesService {
fee,
coreWalletsService.getKey(),
trade,
memo,
() -> {
},
(errorMessage, throwable) -> {

View file

@ -254,8 +254,8 @@ public class BtcWalletService extends WalletService {
sendRequest.signInputs = false;
sendRequest.fee = txFeePerVbyte.multiply(txVsizeWithUnsignedInputs +
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4);
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4);
sendRequest.feePerKb = Coin.ZERO;
sendRequest.ensureMinRequiredFee = false;
@ -274,8 +274,8 @@ public class BtcWalletService extends WalletService {
numSegwitInputs = numInputs.second;
txVsizeWithUnsignedInputs = resultTx.getVsize();
long estimatedFeeAsLong = txFeePerVbyte.multiply(txVsizeWithUnsignedInputs +
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4).value;
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4).value;
// calculated fee must be inside of a tolerance range with tx fee
isFeeOutsideTolerance = Math.abs(resultTx.getFee().value - estimatedFeeAsLong) > 1000;
@ -374,8 +374,8 @@ public class BtcWalletService extends WalletService {
sendRequest.signInputs = false;
sendRequest.fee = txFeePerVbyte.multiply(txVsizeWithUnsignedInputs +
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4);
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4);
sendRequest.feePerKb = Coin.ZERO;
sendRequest.ensureMinRequiredFee = false;
@ -393,8 +393,8 @@ public class BtcWalletService extends WalletService {
numSegwitInputs = numInputs.second;
txVsizeWithUnsignedInputs = resultTx.getVsize();
final long estimatedFeeAsLong = txFeePerVbyte.multiply(txVsizeWithUnsignedInputs +
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4).value;
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4).value;
// calculated fee must be inside of a tolerance range with tx fee
isFeeOutsideTolerance = Math.abs(resultTx.getFee().value - estimatedFeeAsLong) > 1000;
}
@ -532,8 +532,8 @@ public class BtcWalletService extends WalletService {
sendRequest.signInputs = false;
sendRequest.fee = txFeePerVbyte.multiply(txVsizeWithUnsignedInputs +
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4);
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4);
sendRequest.feePerKb = Coin.ZERO;
sendRequest.ensureMinRequiredFee = false;
@ -558,8 +558,8 @@ public class BtcWalletService extends WalletService {
numSegwitInputs = numInputs.second;
txVsizeWithUnsignedInputs = resultTx.getVsize();
final long estimatedFeeAsLong = txFeePerVbyte.multiply(txVsizeWithUnsignedInputs +
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4).value;
sigSizePerInput * numLegacyInputs +
sigSizePerInput * numSegwitInputs / 4).value;
// calculated fee must be inside of a tolerance range with tx fee
isFeeOutsideTolerance = Math.abs(resultTx.getFee().value - estimatedFeeAsLong) > 1000;
}
@ -583,7 +583,7 @@ public class BtcWalletService extends WalletService {
for (TransactionInput input : tx.getInputs()) {
TransactionOutput connectedOutput = input.getConnectedOutput();
if (connectedOutput == null || ScriptPattern.isP2PKH(connectedOutput.getScriptPubKey()) ||
ScriptPattern.isP2PK(connectedOutput.getScriptPubKey())) {
ScriptPattern.isP2PK(connectedOutput.getScriptPubKey())) {
// If connectedOutput is null, we don't know here the input type. To avoid underpaying fees,
// we treat it as a legacy input which will result in a higher fee estimation.
numLegacyInputs++;
@ -1100,12 +1100,15 @@ public class BtcWalletService extends WalletService {
Coin fee,
@Nullable KeyParameter aesKey,
@SuppressWarnings("SameParameterValue") AddressEntry.Context context,
@Nullable String memo,
FutureCallback<Transaction> callback) throws AddressFormatException,
AddressEntryException, InsufficientMoneyException {
SendRequest sendRequest = getSendRequest(fromAddress, toAddress, receiverAmount, fee, aesKey, context);
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
Futures.addCallback(sendResult.broadcastComplete, callback, MoreExecutors.directExecutor());
if (memo != null) {
sendResult.tx.setMemo(memo);
}
printTx("sendFunds", sendResult.tx);
return sendResult.tx.getTxId().toString();
}
@ -1116,13 +1119,16 @@ public class BtcWalletService extends WalletService {
Coin fee,
@Nullable String changeAddress,
@Nullable KeyParameter aesKey,
@Nullable String memo,
FutureCallback<Transaction> callback) throws AddressFormatException,
AddressEntryException, InsufficientMoneyException {
SendRequest request = getSendRequestForMultipleAddresses(fromAddresses, toAddress, receiverAmount, fee, changeAddress, aesKey);
Wallet.SendResult sendResult = wallet.sendCoins(request);
Futures.addCallback(sendResult.broadcastComplete, callback, MoreExecutors.directExecutor());
if (memo != null) {
sendResult.tx.setMemo(memo);
}
printTx("sendFunds", sendResult.tx);
return sendResult.tx;
}

View file

@ -462,8 +462,14 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
// Complete trade
///////////////////////////////////////////////////////////////////////////////////////////
public void onWithdrawRequest(String toAddress, Coin amount, Coin fee, KeyParameter aesKey,
Trade trade, ResultHandler resultHandler, FaultHandler faultHandler) {
public void onWithdrawRequest(String toAddress,
Coin amount,
Coin fee,
KeyParameter aesKey,
Trade trade,
@Nullable String memo,
ResultHandler resultHandler,
FaultHandler faultHandler) {
String fromAddress = btcWalletService.getOrCreateAddressEntry(trade.getId(),
AddressEntry.Context.TRADE_PAYOUT).getAddressString();
FutureCallback<Transaction> callback = new FutureCallback<>() {
@ -487,7 +493,8 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
}
};
try {
btcWalletService.sendFunds(fromAddress, toAddress, amount, fee, aesKey, AddressEntry.Context.TRADE_PAYOUT, callback);
btcWalletService.sendFunds(fromAddress, toAddress, amount, fee, aesKey,
AddressEntry.Context.TRADE_PAYOUT, memo, callback);
} catch (AddressFormatException | InsufficientMoneyException | AddressEntryException e) {
e.printStackTrace();
log.error(e.getMessage());

View file

@ -144,7 +144,8 @@ class GrpcTradesService extends TradesGrpc.TradesImplBase {
public void withdrawFunds(WithdrawFundsRequest req,
StreamObserver<WithdrawFundsReply> responseObserver) {
try {
coreApi.withdrawFunds(req.getTradeId(), req.getAddress());
//TODO @ghubstan Feel free to add a memo param for withdrawal requests (was just added in UI)
coreApi.withdrawFunds(req.getTradeId(), req.getAddress(), null);
var reply = WithdrawFundsReply.newBuilder().build();
responseObserver.onNext(reply);
responseObserver.onCompleted();

View file

@ -494,14 +494,19 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
private void sendFunds(Coin amount, Coin fee, KeyParameter aesKey, FutureCallback<Transaction> callback) {
try {
String memo = withdrawMemoTextField.getText();
if (memo.isEmpty()) {
memo = null;
}
Transaction transaction = btcWalletService.sendFundsForMultipleAddresses(fromAddresses,
withdrawToTextField.getText(),
amount,
fee,
null,
aesKey,
memo,
callback);
transaction.setMemo(withdrawMemoTextField.getText());
reset();
updateList();
} catch (AddressFormatException e) {

View file

@ -209,6 +209,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
Coin amount,
Coin fee,
KeyParameter aesKey,
@Nullable String memo,
ResultHandler resultHandler,
FaultHandler faultHandler) {
checkNotNull(getTrade(), "trade must not be null");
@ -220,6 +221,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
fee,
aesKey,
getTrade(),
memo,
() -> {
resultHandler.handleResult();
selectBestItem();

View file

@ -74,7 +74,7 @@ import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
public class BuyerStep4View extends TradeStepView {
// private final ChangeListener<Boolean> focusedPropertyListener;
private InputTextField withdrawAddressTextField;
private InputTextField withdrawAddressTextField, withdrawMemoTextField;
private Button withdrawToExternalWalletButton, useSavingsWalletButton;
private TitledGroupBg withdrawTitledGroupBg;
@ -131,10 +131,17 @@ public class BuyerStep4View extends TradeStepView {
withdrawTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, Res.get("portfolio.pending.step5_buyer.withdrawBTC"), Layout.COMPACT_GROUP_DISTANCE);
withdrawTitledGroupBg.getStyleClass().add("last");
addCompactTopLabelTextField(gridPane, gridRow, Res.get("portfolio.pending.step5_buyer.amount"), model.getPayoutAmount(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
withdrawAddressTextField = addInputTextField(gridPane, ++gridRow, Res.get("portfolio.pending.step5_buyer.withdrawToAddress"));
withdrawAddressTextField.setManaged(false);
withdrawAddressTextField.setVisible(false);
withdrawMemoTextField = addInputTextField(gridPane, ++gridRow,
Res.get("funds.withdrawal.memoLabel", Res.getBaseCurrencyCode()));
withdrawMemoTextField.setPromptText(Res.get("funds.withdrawal.memo"));
withdrawMemoTextField.setManaged(false);
withdrawMemoTextField.setVisible(false);
HBox hBox = new HBox();
hBox.setSpacing(10);
useSavingsWalletButton = new AutoTooltipButton(Res.get("portfolio.pending.step5_buyer.moveToBisqWallet"));
@ -170,7 +177,9 @@ public class BuyerStep4View extends TradeStepView {
private void onWithdrawal() {
withdrawAddressTextField.setManaged(true);
withdrawAddressTextField.setVisible(true);
GridPane.setRowSpan(withdrawTitledGroupBg, 2);
withdrawMemoTextField.setManaged(true);
withdrawMemoTextField.setVisible(true);
GridPane.setRowSpan(withdrawTitledGroupBg, 3);
withdrawToExternalWalletButton.setDefaultButton(true);
useSavingsWalletButton.setDefaultButton(false);
withdrawToExternalWalletButton.getStyleClass().add("action-button");
@ -271,10 +280,15 @@ public class BuyerStep4View extends TradeStepView {
FaultHandler faultHandler) {
useSavingsWalletButton.setDisable(true);
withdrawToExternalWalletButton.setDisable(true);
String memo = withdrawMemoTextField.getText();
if (memo.isEmpty()) {
memo = null;
}
model.dataModel.onWithdrawRequest(toAddress,
amount,
fee,
aesKey,
memo,
resultHandler,
faultHandler);
}