Simplify the trade complete summary dialog

This commit is contained in:
jmacxx 2021-12-24 14:22:59 -06:00
parent 670c5418ee
commit 1162060e28
No known key found for this signature in database
GPG key ID: 155297BABFE94A1B
2 changed files with 28 additions and 190 deletions

View file

@ -898,6 +898,8 @@ portfolio.pending.step3_seller.onPaymentReceived.signer=IMPORTANT: By confirming
you should delay confirmation of the payment as long as possible to reduce the risk of a chargeback.
portfolio.pending.step5_buyer.groupTitle=Summary of completed trade
portfolio.pending.step5_buyer.groupTitle.mediated=This trade was resolved by mediation
portfolio.pending.step5_buyer.groupTitle.arbitrated=This trade was resolved by arbitration
portfolio.pending.step5_buyer.tradeFee=Trade fee
portfolio.pending.step5_buyer.makersMiningFee=Mining fee
portfolio.pending.step5_buyer.takersMiningFee=Total mining fees

View file

@ -18,8 +18,6 @@
package bisq.desktop.main.portfolio.pendingtrades.steps.buyer;
import bisq.desktop.components.AutoTooltipButton;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.InputTextField;
import bisq.desktop.components.TitledGroupBg;
import bisq.desktop.main.MainView;
import bisq.desktop.main.overlays.notifications.Notification;
@ -31,26 +29,13 @@ import bisq.desktop.main.portfolio.pendingtrades.PendingTradesViewModel;
import bisq.desktop.main.portfolio.pendingtrades.steps.TradeStepView;
import bisq.desktop.util.Layout;
import bisq.core.btc.exceptions.AddressEntryException;
import bisq.core.btc.exceptions.InsufficientFundsException;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.locale.Res;
import bisq.core.trade.txproof.AssetTxProofResult;
import bisq.core.user.DontShowAgainLookup;
import bisq.core.util.coin.CoinFormatter;
import bisq.core.util.coin.CoinUtil;
import bisq.core.util.validation.BtcAddressValidator;
import bisq.common.UserThread;
import bisq.common.app.DevEnv;
import bisq.common.handlers.FaultHandler;
import bisq.common.handlers.ResultHandler;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
import com.jfoenix.controls.JFXBadge;
@ -63,20 +48,13 @@ import javafx.scene.layout.Priority;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import org.bouncycastle.crypto.params.KeyParameter;
import java.util.concurrent.TimeUnit;
import static bisq.desktop.util.FormBuilder.addCompactTopLabelTextField;
import static bisq.desktop.util.FormBuilder.addInputTextField;
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
public class BuyerStep4View extends TradeStepView {
// private final ChangeListener<Boolean> focusedPropertyListener;
private InputTextField withdrawAddressTextField, withdrawMemoTextField;
private Button withdrawToExternalWalletButton, useSavingsWalletButton;
private TitledGroupBg withdrawTitledGroupBg;
private Button closeButton;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
@ -108,8 +86,13 @@ public class BuyerStep4View extends TradeStepView {
gridPane.getColumnConstraints().get(1).setHgrow(Priority.SOMETIMES);
TitledGroupBg completedTradeLabel = new TitledGroupBg();
completedTradeLabel.setText(Res.get("portfolio.pending.step5_buyer.groupTitle"));
if (trade.getDisputeState().isMediated()) {
completedTradeLabel.setText(Res.get("portfolio.pending.step5_buyer.groupTitle.mediated"));
} else if (trade.getDisputeState().isArbitrated()) {
completedTradeLabel.setText(Res.get("portfolio.pending.step5_buyer.groupTitle.arbitrated"));
} else {
completedTradeLabel.setText(Res.get("portfolio.pending.step5_buyer.groupTitle"));
}
JFXBadge autoConfBadge = new JFXBadge(new Label(""), Pos.BASELINE_RIGHT);
autoConfBadge.setText(Res.get("portfolio.pending.autoConf"));
autoConfBadge.getStyleClass().add("auto-conf");
@ -120,49 +103,28 @@ public class BuyerStep4View extends TradeStepView {
GridPane.setRowSpan(hBox2, 5);
autoConfBadge.setVisible(AssetTxProofResult.COMPLETED == trade.getAssetTxProofResult());
addCompactTopLabelTextField(gridPane, gridRow, getBtcTradeAmountLabel(), model.getTradeVolume(), Layout.TWICE_FIRST_ROW_DISTANCE);
addCompactTopLabelTextField(gridPane, ++gridRow, getFiatTradeAmountLabel(), model.getFiatVolume());
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("portfolio.pending.step5_buyer.refunded"), model.getSecurityDeposit());
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("portfolio.pending.step5_buyer.tradeFee"), model.getTradeFee());
final String miningFee = model.dataModel.isMaker() ?
Res.get("portfolio.pending.step5_buyer.makersMiningFee") :
Res.get("portfolio.pending.step5_buyer.takersMiningFee");
addCompactTopLabelTextField(gridPane, ++gridRow, miningFee, model.getTxFee());
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);
if (trade.getDisputeState().isNotDisputed()) {
addCompactTopLabelTextField(gridPane, gridRow, getBtcTradeAmountLabel(), model.getTradeVolume(), Layout.TWICE_FIRST_ROW_DISTANCE);
addCompactTopLabelTextField(gridPane, ++gridRow, getFiatTradeAmountLabel(), model.getFiatVolume());
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("portfolio.pending.step5_buyer.refunded"), model.getSecurityDeposit());
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("portfolio.pending.step5_buyer.tradeFee"), model.getTradeFee());
final String miningFee = model.dataModel.isMaker() ?
Res.get("portfolio.pending.step5_buyer.makersMiningFee") :
Res.get("portfolio.pending.step5_buyer.takersMiningFee");
addCompactTopLabelTextField(gridPane, ++gridRow, miningFee, model.getTxFee());
}
withdrawAddressTextField = addInputTextField(gridPane, ++gridRow, Res.get("portfolio.pending.step5_buyer.withdrawToAddress"));
withdrawAddressTextField.setManaged(false);
withdrawAddressTextField.setVisible(false);
closeButton = new AutoTooltipButton(Res.get("shared.close"));
closeButton.setDefaultButton(true);
closeButton.getStyleClass().add("action-button");
GridPane.setRowIndex(closeButton, ++gridRow);
GridPane.setMargin(closeButton, new Insets(Layout.GROUP_DISTANCE, 10, 0, 0));
gridPane.getChildren().add(closeButton);
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"));
useSavingsWalletButton.setDefaultButton(true);
useSavingsWalletButton.getStyleClass().add("action-button");
Label label = new AutoTooltipLabel(Res.get("shared.OR"));
label.setPadding(new Insets(5, 0, 0, 0));
withdrawToExternalWalletButton = new AutoTooltipButton(Res.get("portfolio.pending.step5_buyer.withdrawExternal"));
withdrawToExternalWalletButton.setDefaultButton(false);
hBox.getChildren().addAll(useSavingsWalletButton, label, withdrawToExternalWalletButton);
GridPane.setRowIndex(hBox, ++gridRow);
GridPane.setMargin(hBox, new Insets(5, 10, 0, 0));
gridPane.getChildren().add(hBox);
useSavingsWalletButton.setOnAction(e -> {
closeButton.setOnAction(e -> {
handleTradeCompleted();
model.dataModel.tradeManager.onTradeCompleted(trade);
});
withdrawToExternalWalletButton.setOnAction(e -> {
onWithdrawal();
});
String key = "tradeCompleted" + trade.getId();
if (!DevEnv.isDevMode() && DontShowAgainLookup.showAgain(key)) {
@ -174,128 +136,8 @@ public class BuyerStep4View extends TradeStepView {
}
}
private void onWithdrawal() {
withdrawAddressTextField.setManaged(true);
withdrawAddressTextField.setVisible(true);
withdrawMemoTextField.setManaged(true);
withdrawMemoTextField.setVisible(true);
GridPane.setRowSpan(withdrawTitledGroupBg, 3);
withdrawToExternalWalletButton.setDefaultButton(true);
useSavingsWalletButton.setDefaultButton(false);
withdrawToExternalWalletButton.getStyleClass().add("action-button");
useSavingsWalletButton.getStyleClass().remove("action-button");
withdrawToExternalWalletButton.setOnAction(e -> {
if (model.dataModel.isReadyForTxBroadcast()) {
reviewWithdrawal();
}
});
}
private void reviewWithdrawal() {
Coin amount = trade.getPayoutAmount();
BtcWalletService walletService = model.dataModel.btcWalletService;
AddressEntry fromAddressesEntry = walletService.getOrCreateAddressEntry(trade.getId(), AddressEntry.Context.TRADE_PAYOUT);
String fromAddresses = fromAddressesEntry.getAddressString();
String toAddresses = withdrawAddressTextField.getText();
if (new BtcAddressValidator().validate(toAddresses).isValid) {
Coin balance = walletService.getBalanceForAddress(fromAddressesEntry.getAddress());
try {
Transaction feeEstimationTransaction = walletService.getFeeEstimationTransaction(fromAddresses, toAddresses, amount, AddressEntry.Context.TRADE_PAYOUT);
Coin fee = feeEstimationTransaction.getFee();
Coin receiverAmount = amount.subtract(fee);
if (balance.isZero()) {
new Popup().warning(Res.get("portfolio.pending.step5_buyer.alreadyWithdrawn")).show();
model.dataModel.tradeManager.onTradeCompleted(trade);
} else {
if (toAddresses.isEmpty()) {
validateWithdrawAddress();
} else if (Restrictions.isAboveDust(receiverAmount)) {
CoinFormatter formatter = model.btcFormatter;
int txVsize = feeEstimationTransaction.getVsize();
double feePerVbyte = CoinUtil.getFeePerVbyte(fee, txVsize);
double vkb = txVsize / 1000d;
String recAmount = formatter.formatCoinWithCode(receiverAmount);
new Popup().headLine(Res.get("portfolio.pending.step5_buyer.confirmWithdrawal"))
.confirmation(Res.get("shared.sendFundsDetailsWithFee",
formatter.formatCoinWithCode(amount),
fromAddresses,
toAddresses,
formatter.formatCoinWithCode(fee),
feePerVbyte,
vkb,
recAmount))
.actionButtonText(Res.get("shared.yes"))
.onAction(() -> doWithdrawal(amount, fee))
.closeButtonText(Res.get("shared.cancel"))
.onClose(() -> {
useSavingsWalletButton.setDisable(false);
withdrawToExternalWalletButton.setDisable(false);
})
.show();
} else {
new Popup().warning(Res.get("portfolio.pending.step5_buyer.amountTooLow")).show();
}
}
} catch (AddressFormatException e) {
validateWithdrawAddress();
} catch (AddressEntryException e) {
log.error(e.getMessage());
} catch (InsufficientFundsException e) {
log.error(e.getMessage());
e.printStackTrace();
new Popup().warning(e.getMessage()).show();
}
} else {
new Popup().warning(Res.get("validation.btc.invalidAddress")).show();
}
}
private void doWithdrawal(Coin amount, Coin fee) {
String toAddress = withdrawAddressTextField.getText();
ResultHandler resultHandler = this::handleTradeCompleted;
FaultHandler faultHandler = (errorMessage, throwable) -> {
useSavingsWalletButton.setDisable(false);
withdrawToExternalWalletButton.setDisable(false);
if (throwable != null && throwable.getMessage() != null)
new Popup().error(errorMessage + "\n\n" + throwable.getMessage()).show();
else
new Popup().error(errorMessage).show();
};
if (model.dataModel.btcWalletService.isEncrypted()) {
UserThread.runAfter(() -> model.dataModel.walletPasswordWindow.onAesKey(aesKey ->
doWithdrawRequest(toAddress, amount, fee, aesKey, resultHandler, faultHandler))
.show(), 300, TimeUnit.MILLISECONDS);
} else
doWithdrawRequest(toAddress, amount, fee, null, resultHandler, faultHandler);
}
private void doWithdrawRequest(String toAddress,
Coin amount,
Coin fee,
KeyParameter aesKey,
ResultHandler resultHandler,
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);
}
private void handleTradeCompleted() {
useSavingsWalletButton.setDisable(true);
withdrawToExternalWalletButton.setDisable(true);
closeButton.setDisable(true);
model.dataModel.btcWalletService.swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.TRADE_PAYOUT);
openTradeFeedbackWindow();
@ -328,12 +170,6 @@ public class BuyerStep4View extends TradeStepView {
}
}
private void validateWithdrawAddress() {
withdrawAddressTextField.setValidator(model.btcAddressValidator);
withdrawAddressTextField.requestFocus();
useSavingsWalletButton.requestFocus();
}
protected String getBtcTradeAmountLabel() {
return Res.get("portfolio.pending.step5_buyer.bought");
}