mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-28 09:24:15 -04:00
fixes from congestion testing
- refactor main wallet polling - restart main wallet if connection changes before initial sync - use cached wallet state throughout app - avoid rescanning spent outputs until payout tx expected - allow payment sent/received buttons to be clicked until arrived - apply timeout to payment sent/received buttons - load DepositView asynchronously - remove separate timeout from OpenOffer - tolerate error importing multisig hex until necessary
This commit is contained in:
parent
9cbf042da2
commit
ca2d7704ab
22 changed files with 802 additions and 680 deletions
|
@ -33,7 +33,6 @@ import haveno.core.trade.protocol.tasks.ProcessPaymentReceivedMessage;
|
|||
import haveno.core.trade.protocol.tasks.ProcessPaymentSentMessage;
|
||||
import haveno.core.trade.protocol.tasks.RemoveOffer;
|
||||
import haveno.core.trade.protocol.tasks.SellerPreparePaymentReceivedMessage;
|
||||
import haveno.core.trade.protocol.tasks.SellerPublishDepositTx;
|
||||
import haveno.core.trade.protocol.tasks.SellerPublishTradeStatistics;
|
||||
import haveno.core.trade.protocol.tasks.SellerSendPaymentReceivedMessageToBuyer;
|
||||
import haveno.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
|
||||
|
@ -87,7 +86,6 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
|||
VerifyPeersAccountAgeWitness.class,
|
||||
|
||||
//SellerSendsDepositTxAndDelayedPayoutTxMessage.class,
|
||||
SellerPublishDepositTx.class,
|
||||
SellerPublishTradeStatistics.class,
|
||||
|
||||
ProcessPaymentSentMessage.class,
|
||||
|
@ -140,7 +138,6 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
|||
RemoveOffer.class,
|
||||
|
||||
//SellerSendsDepositTxAndDelayedPayoutTxMessage.class,
|
||||
SellerPublishDepositTx.class,
|
||||
SellerPublishTradeStatistics.class,
|
||||
|
||||
ProcessPaymentSentMessage.class,
|
||||
|
|
|
@ -36,6 +36,8 @@ package haveno.desktop.main.funds.deposit;
|
|||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
import haveno.common.ThreadUtils;
|
||||
import haveno.common.UserThread;
|
||||
import haveno.common.app.DevEnv;
|
||||
import haveno.common.util.Tuple3;
|
||||
|
@ -78,6 +80,7 @@ import javafx.fxml.FXML;
|
|||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
|
@ -111,6 +114,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
|||
private Button generateNewAddressButton;
|
||||
private TitledGroupBg titledGroupBg;
|
||||
private InputTextField amountTextField;
|
||||
private static final String THREAD_ID = DepositView.class.getName();
|
||||
|
||||
private final XmrWalletService xmrWalletService;
|
||||
private final Preferences preferences;
|
||||
|
@ -146,142 +150,155 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
|||
confirmationsColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.confirmations")));
|
||||
usageColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.usage")));
|
||||
|
||||
// trigger creation of at least 1 address
|
||||
try {
|
||||
xmrWalletService.getFreshAddressEntry();
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to get wallet txs to initialize DepositView");
|
||||
e.printStackTrace();
|
||||
}
|
||||
// set loading placeholder
|
||||
Label placeholderLabel = new Label("Loading...");
|
||||
tableView.setPlaceholder(placeholderLabel);
|
||||
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
tableView.setPlaceholder(new AutoTooltipLabel(Res.get("funds.deposit.noAddresses")));
|
||||
tableViewSelectionListener = (observableValue, oldValue, newValue) -> {
|
||||
if (newValue != null) {
|
||||
fillForm(newValue.getAddressString());
|
||||
GUIUtil.requestFocus(amountTextField);
|
||||
ThreadUtils.execute(() -> {
|
||||
|
||||
// trigger creation of at least 1 address
|
||||
try {
|
||||
xmrWalletService.getFreshAddressEntry();
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to create fresh address entry to initialize DepositView");
|
||||
e.printStackTrace();
|
||||
}
|
||||
};
|
||||
|
||||
setAddressColumnCellFactory();
|
||||
setBalanceColumnCellFactory();
|
||||
setUsageColumnCellFactory();
|
||||
setConfidenceColumnCellFactory();
|
||||
|
||||
addressColumn.setComparator(Comparator.comparing(DepositListItem::getAddressString));
|
||||
balanceColumn.setComparator(Comparator.comparing(DepositListItem::getBalanceAsBI));
|
||||
confirmationsColumn.setComparator(Comparator.comparingLong(o -> o.getNumConfirmationsSinceFirstUsed()));
|
||||
usageColumn.setComparator(Comparator.comparing(DepositListItem::getUsage));
|
||||
tableView.getSortOrder().add(usageColumn);
|
||||
tableView.setItems(sortedList);
|
||||
|
||||
titledGroupBg = addTitledGroupBg(gridPane, gridRow, 4, Res.get("funds.deposit.fundWallet"));
|
||||
titledGroupBg.getStyleClass().add("last");
|
||||
|
||||
qrCodeImageView = new ImageView();
|
||||
qrCodeImageView.setFitHeight(150);
|
||||
qrCodeImageView.setFitWidth(150);
|
||||
qrCodeImageView.getStyleClass().add("qr-code");
|
||||
Tooltip.install(qrCodeImageView, new Tooltip(Res.get("shared.openLargeQRWindow")));
|
||||
qrCodeImageView.setOnMouseClicked(e -> UserThread.runAfter(
|
||||
() -> new QRCodeWindow(getPaymentUri()).show(),
|
||||
200, TimeUnit.MILLISECONDS));
|
||||
GridPane.setRowIndex(qrCodeImageView, gridRow);
|
||||
GridPane.setRowSpan(qrCodeImageView, 4);
|
||||
GridPane.setColumnIndex(qrCodeImageView, 1);
|
||||
GridPane.setMargin(qrCodeImageView, new Insets(Layout.FIRST_ROW_DISTANCE, 0, 0, 10));
|
||||
gridPane.getChildren().add(qrCodeImageView);
|
||||
|
||||
addressTextField = addAddressTextField(gridPane, ++gridRow, Res.get("shared.address"), Layout.FIRST_ROW_DISTANCE);
|
||||
addressTextField.setPaymentLabel(paymentLabelString);
|
||||
|
||||
|
||||
amountTextField = addInputTextField(gridPane, ++gridRow, Res.get("funds.deposit.amount"));
|
||||
amountTextField.setMaxWidth(380);
|
||||
if (DevEnv.isDevMode())
|
||||
amountTextField.setText("10");
|
||||
|
||||
titledGroupBg.setVisible(false);
|
||||
titledGroupBg.setManaged(false);
|
||||
qrCodeImageView.setVisible(false);
|
||||
qrCodeImageView.setManaged(false);
|
||||
addressTextField.setVisible(false);
|
||||
addressTextField.setManaged(false);
|
||||
amountTextField.setManaged(false);
|
||||
|
||||
Tuple3<Button, CheckBox, HBox> buttonCheckBoxHBox = addButtonCheckBoxWithBox(gridPane, ++gridRow,
|
||||
Res.get("funds.deposit.generateAddress"),
|
||||
null,
|
||||
15);
|
||||
buttonCheckBoxHBox.third.setSpacing(25);
|
||||
generateNewAddressButton = buttonCheckBoxHBox.first;
|
||||
|
||||
generateNewAddressButton.setOnAction(event -> {
|
||||
boolean hasUnusedAddress = !xmrWalletService.getUnusedAddressEntries().isEmpty();
|
||||
if (hasUnusedAddress) {
|
||||
new Popup().warning(Res.get("funds.deposit.selectUnused")).show();
|
||||
} else {
|
||||
XmrAddressEntry newSavingsAddressEntry = xmrWalletService.getNewAddressEntry();
|
||||
updateList();
|
||||
UserThread.execute(() -> {
|
||||
observableList.stream()
|
||||
.filter(depositListItem -> depositListItem.getAddressString().equals(newSavingsAddressEntry.getAddressString()))
|
||||
.findAny()
|
||||
.ifPresent(depositListItem -> tableView.getSelectionModel().select(depositListItem));
|
||||
UserThread.execute(() -> {
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
tableView.setPlaceholder(new AutoTooltipLabel(Res.get("funds.deposit.noAddresses")));
|
||||
tableViewSelectionListener = (observableValue, oldValue, newValue) -> {
|
||||
if (newValue != null) {
|
||||
fillForm(newValue.getAddressString());
|
||||
GUIUtil.requestFocus(amountTextField);
|
||||
}
|
||||
};
|
||||
|
||||
setAddressColumnCellFactory();
|
||||
setBalanceColumnCellFactory();
|
||||
setUsageColumnCellFactory();
|
||||
setConfidenceColumnCellFactory();
|
||||
|
||||
addressColumn.setComparator(Comparator.comparing(DepositListItem::getAddressString));
|
||||
balanceColumn.setComparator(Comparator.comparing(DepositListItem::getBalanceAsBI));
|
||||
confirmationsColumn.setComparator(Comparator.comparingLong(o -> o.getNumConfirmationsSinceFirstUsed()));
|
||||
usageColumn.setComparator(Comparator.comparing(DepositListItem::getUsage));
|
||||
tableView.getSortOrder().add(usageColumn);
|
||||
tableView.setItems(sortedList);
|
||||
|
||||
titledGroupBg = addTitledGroupBg(gridPane, gridRow, 4, Res.get("funds.deposit.fundWallet"));
|
||||
titledGroupBg.getStyleClass().add("last");
|
||||
|
||||
qrCodeImageView = new ImageView();
|
||||
qrCodeImageView.setFitHeight(150);
|
||||
qrCodeImageView.setFitWidth(150);
|
||||
qrCodeImageView.getStyleClass().add("qr-code");
|
||||
Tooltip.install(qrCodeImageView, new Tooltip(Res.get("shared.openLargeQRWindow")));
|
||||
qrCodeImageView.setOnMouseClicked(e -> UserThread.runAfter(
|
||||
() -> new QRCodeWindow(getPaymentUri()).show(),
|
||||
200, TimeUnit.MILLISECONDS));
|
||||
GridPane.setRowIndex(qrCodeImageView, gridRow);
|
||||
GridPane.setRowSpan(qrCodeImageView, 4);
|
||||
GridPane.setColumnIndex(qrCodeImageView, 1);
|
||||
GridPane.setMargin(qrCodeImageView, new Insets(Layout.FIRST_ROW_DISTANCE, 0, 0, 10));
|
||||
gridPane.getChildren().add(qrCodeImageView);
|
||||
|
||||
addressTextField = addAddressTextField(gridPane, ++gridRow, Res.get("shared.address"), Layout.FIRST_ROW_DISTANCE);
|
||||
addressTextField.setPaymentLabel(paymentLabelString);
|
||||
amountTextField = addInputTextField(gridPane, ++gridRow, Res.get("funds.deposit.amount"));
|
||||
amountTextField.setMaxWidth(380);
|
||||
if (DevEnv.isDevMode())
|
||||
amountTextField.setText("10");
|
||||
|
||||
titledGroupBg.setVisible(false);
|
||||
titledGroupBg.setManaged(false);
|
||||
qrCodeImageView.setVisible(false);
|
||||
qrCodeImageView.setManaged(false);
|
||||
addressTextField.setVisible(false);
|
||||
addressTextField.setManaged(false);
|
||||
amountTextField.setManaged(false);
|
||||
|
||||
Tuple3<Button, CheckBox, HBox> buttonCheckBoxHBox = addButtonCheckBoxWithBox(gridPane, ++gridRow,
|
||||
Res.get("funds.deposit.generateAddress"),
|
||||
null,
|
||||
15);
|
||||
buttonCheckBoxHBox.third.setSpacing(25);
|
||||
generateNewAddressButton = buttonCheckBoxHBox.first;
|
||||
|
||||
generateNewAddressButton.setOnAction(event -> {
|
||||
boolean hasUnusedAddress = !xmrWalletService.getUnusedAddressEntries().isEmpty();
|
||||
if (hasUnusedAddress) {
|
||||
new Popup().warning(Res.get("funds.deposit.selectUnused")).show();
|
||||
} else {
|
||||
XmrAddressEntry newSavingsAddressEntry = xmrWalletService.getNewAddressEntry();
|
||||
updateList();
|
||||
UserThread.execute(() -> {
|
||||
observableList.stream()
|
||||
.filter(depositListItem -> depositListItem.getAddressString().equals(newSavingsAddressEntry.getAddressString()))
|
||||
.findAny()
|
||||
.ifPresent(depositListItem -> tableView.getSelectionModel().select(depositListItem));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
balanceListener = new XmrBalanceListener() {
|
||||
@Override
|
||||
public void onBalanceChanged(BigInteger balance) {
|
||||
updateList();
|
||||
}
|
||||
};
|
||||
|
||||
walletListener = new MoneroWalletListener() {
|
||||
@Override
|
||||
public void onNewBlock(long height) {
|
||||
updateList();
|
||||
}
|
||||
};
|
||||
|
||||
GUIUtil.focusWhenAddedToScene(amountTextField);
|
||||
|
||||
balanceListener = new XmrBalanceListener() {
|
||||
@Override
|
||||
public void onBalanceChanged(BigInteger balance) {
|
||||
updateList();
|
||||
}
|
||||
};
|
||||
|
||||
walletListener = new MoneroWalletListener() {
|
||||
@Override
|
||||
public void onNewBlock(long height) {
|
||||
updateList();
|
||||
}
|
||||
};
|
||||
|
||||
GUIUtil.focusWhenAddedToScene(amountTextField);
|
||||
});
|
||||
}, THREAD_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
tableView.getSelectionModel().selectedItemProperty().addListener(tableViewSelectionListener);
|
||||
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
|
||||
|
||||
// try to update deposits list
|
||||
try {
|
||||
updateList();
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not update deposits list");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
xmrWalletService.addBalanceListener(balanceListener);
|
||||
xmrWalletService.addWalletListener(walletListener);
|
||||
|
||||
amountTextFieldSubscription = EasyBind.subscribe(amountTextField.textProperty(), t -> {
|
||||
addressTextField.setAmount(HavenoUtils.parseXmr(t));
|
||||
updateQRCode();
|
||||
});
|
||||
|
||||
if (tableView.getSelectionModel().getSelectedItem() == null && !sortedList.isEmpty())
|
||||
tableView.getSelectionModel().select(0);
|
||||
ThreadUtils.execute(() -> {
|
||||
UserThread.execute(() -> {
|
||||
tableView.getSelectionModel().selectedItemProperty().addListener(tableViewSelectionListener);
|
||||
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
|
||||
|
||||
// try to update deposits list
|
||||
try {
|
||||
updateList();
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not update deposits list");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
xmrWalletService.addBalanceListener(balanceListener);
|
||||
xmrWalletService.addWalletListener(walletListener);
|
||||
|
||||
amountTextFieldSubscription = EasyBind.subscribe(amountTextField.textProperty(), t -> {
|
||||
addressTextField.setAmount(HavenoUtils.parseXmr(t));
|
||||
updateQRCode();
|
||||
});
|
||||
|
||||
if (tableView.getSelectionModel().getSelectedItem() == null && !sortedList.isEmpty())
|
||||
tableView.getSelectionModel().select(0);
|
||||
});
|
||||
}, THREAD_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
tableView.getSelectionModel().selectedItemProperty().removeListener(tableViewSelectionListener);
|
||||
sortedList.comparatorProperty().unbind();
|
||||
observableList.forEach(DepositListItem::cleanup);
|
||||
xmrWalletService.removeBalanceListener(balanceListener);
|
||||
xmrWalletService.removeWalletListener(walletListener);
|
||||
amountTextFieldSubscription.unsubscribe();
|
||||
ThreadUtils.execute(() -> {
|
||||
tableView.getSelectionModel().selectedItemProperty().removeListener(tableViewSelectionListener);
|
||||
sortedList.comparatorProperty().unbind();
|
||||
observableList.forEach(DepositListItem::cleanup);
|
||||
xmrWalletService.removeBalanceListener(balanceListener);
|
||||
xmrWalletService.removeWalletListener(walletListener);
|
||||
amountTextFieldSubscription.unsubscribe();
|
||||
}, THREAD_ID);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -156,7 +156,6 @@ public class BuyerStep2View extends TradeStepView {
|
|||
statusLabel.setText(Res.get("shared.preparingConfirmation"));
|
||||
break;
|
||||
case BUYER_SENT_PAYMENT_SENT_MSG:
|
||||
case BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG:
|
||||
busyAnimation.play();
|
||||
statusLabel.setText(Res.get("shared.sendingConfirmation"));
|
||||
timeoutTimer = UserThread.runAfter(() -> {
|
||||
|
@ -168,6 +167,7 @@ public class BuyerStep2View extends TradeStepView {
|
|||
busyAnimation.stop();
|
||||
statusLabel.setText(Res.get("shared.messageStoredInMailbox"));
|
||||
break;
|
||||
case BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG:
|
||||
case SELLER_RECEIVED_PAYMENT_SENT_MSG:
|
||||
busyAnimation.stop();
|
||||
statusLabel.setText(Res.get("shared.messageArrived"));
|
||||
|
@ -442,7 +442,8 @@ public class BuyerStep2View extends TradeStepView {
|
|||
|
||||
private boolean confirmPaymentSentPermitted() {
|
||||
if (!trade.confirmPermitted()) return false;
|
||||
return trade.isDepositsUnlocked() && trade.getState().ordinal() < Trade.State.BUYER_SENT_PAYMENT_SENT_MSG.ordinal();
|
||||
if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG) return false;
|
||||
return trade.isDepositsUnlocked() && trade.getState().ordinal() < Trade.State.SELLER_RECEIVED_PAYMENT_SENT_MSG.ordinal();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -123,20 +123,19 @@ public class SellerStep3View extends TradeStepView {
|
|||
case SELLER_SENT_PAYMENT_RECEIVED_MSG:
|
||||
busyAnimation.play();
|
||||
statusLabel.setText(Res.get("shared.sendingConfirmation"));
|
||||
|
||||
timeoutTimer = UserThread.runAfter(() -> {
|
||||
busyAnimation.stop();
|
||||
statusLabel.setText(Res.get("shared.sendingConfirmationAgain"));
|
||||
}, 30);
|
||||
break;
|
||||
case SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG:
|
||||
busyAnimation.stop();
|
||||
statusLabel.setText(Res.get("shared.messageArrived"));
|
||||
break;
|
||||
case SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG:
|
||||
busyAnimation.stop();
|
||||
statusLabel.setText(Res.get("shared.messageStoredInMailbox"));
|
||||
break;
|
||||
case SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG:
|
||||
busyAnimation.stop();
|
||||
statusLabel.setText(Res.get("shared.messageArrived"));
|
||||
break;
|
||||
case SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG:
|
||||
// We get a popup and the trade closed, so we dont need to show anything here
|
||||
busyAnimation.stop();
|
||||
|
@ -290,7 +289,8 @@ public class SellerStep3View extends TradeStepView {
|
|||
|
||||
private boolean confirmPaymentReceivedPermitted() {
|
||||
if (!trade.confirmPermitted()) return false;
|
||||
return trade.getState().ordinal() >= Trade.State.BUYER_SENT_PAYMENT_SENT_MSG.ordinal() && trade.getState().ordinal() < Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG.ordinal();
|
||||
if (trade.getState() == Trade.State.SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG) return false;
|
||||
return trade.getState().ordinal() >= Trade.State.BUYER_SENT_PAYMENT_SENT_MSG.ordinal() && trade.getState().ordinal() <= Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG.ordinal();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue