mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-08-10 23:50:10 -04:00
remove XmrTxProofService
This commit is contained in:
parent
33147e1c7c
commit
37e812dead
38 changed files with 5 additions and 3737 deletions
|
@ -36,7 +36,6 @@ import haveno.core.user.Cookie;
|
|||
import haveno.core.user.CookieKey;
|
||||
import haveno.core.user.Preferences;
|
||||
import haveno.core.user.User;
|
||||
import haveno.core.xmr.wallet.BtcWalletService;
|
||||
import haveno.core.xmr.wallet.WalletsManager;
|
||||
import haveno.desktop.common.view.CachingViewLoader;
|
||||
import haveno.desktop.common.view.View;
|
||||
|
@ -44,9 +43,7 @@ import haveno.desktop.common.view.ViewLoader;
|
|||
import haveno.desktop.main.MainView;
|
||||
import haveno.desktop.main.debug.DebugView;
|
||||
import haveno.desktop.main.overlays.popups.Popup;
|
||||
import haveno.desktop.main.overlays.windows.BtcEmptyWalletWindow;
|
||||
import haveno.desktop.main.overlays.windows.FilterWindow;
|
||||
import haveno.desktop.main.overlays.windows.ManualPayoutTxWindow;
|
||||
import haveno.desktop.main.overlays.windows.SendAlertMessageWindow;
|
||||
import haveno.desktop.main.overlays.windows.ShowWalletDataWindow;
|
||||
import haveno.desktop.util.CssTheme;
|
||||
|
@ -299,9 +296,7 @@ public class HavenoApp extends Application implements UncaughtExceptionHandler {
|
|||
Utilities.isCtrlPressed(KeyCode.Q, keyEvent)) {
|
||||
shutDownByUser();
|
||||
} else {
|
||||
if (Utilities.isAltOrCtrlPressed(KeyCode.E, keyEvent)) {
|
||||
injector.getInstance(BtcEmptyWalletWindow.class).show();
|
||||
} else if (Utilities.isAltOrCtrlPressed(KeyCode.M, keyEvent)) {
|
||||
if (Utilities.isAltOrCtrlPressed(KeyCode.M, keyEvent)) {
|
||||
injector.getInstance(SendAlertMessageWindow.class).show();
|
||||
} else if (Utilities.isAltOrCtrlPressed(KeyCode.F, keyEvent)) {
|
||||
injector.getInstance(FilterWindow.class).show();
|
||||
|
@ -323,11 +318,6 @@ public class HavenoApp extends Application implements UncaughtExceptionHandler {
|
|||
new ShowWalletDataWindow(walletsManager).show();
|
||||
else
|
||||
new Popup().warning(Res.get("popup.warning.walletNotInitialized")).show();
|
||||
} else if (Utilities.isAltOrCtrlPressed(KeyCode.G, keyEvent)) {
|
||||
if (injector.getInstance(BtcWalletService.class).isWalletReady())
|
||||
injector.getInstance(ManualPayoutTxWindow.class).show();
|
||||
else
|
||||
new Popup().warning(Res.get("popup.warning.walletNotInitialized")).show();
|
||||
} else if (DevEnv.isDevMode()) {
|
||||
if (Utilities.isAltOrCtrlPressed(KeyCode.Z, keyEvent))
|
||||
showDebugWindow(scene, injector);
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
package haveno.desktop.main.overlays.windows;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import haveno.common.UserThread;
|
||||
import haveno.core.api.CoreMoneroConnectionsService;
|
||||
import haveno.core.locale.Res;
|
||||
import haveno.core.offer.OpenOfferManager;
|
||||
import haveno.core.util.FormattingUtils;
|
||||
import haveno.core.util.coin.CoinFormatter;
|
||||
import haveno.core.xmr.wallet.BtcWalletService;
|
||||
import haveno.core.xmr.wallet.Restrictions;
|
||||
import haveno.desktop.components.AutoTooltipButton;
|
||||
import haveno.desktop.components.InputTextField;
|
||||
import haveno.desktop.main.overlays.Overlay;
|
||||
import haveno.desktop.main.overlays.popups.Popup;
|
||||
import haveno.desktop.util.GUIUtil;
|
||||
import haveno.desktop.util.Transitions;
|
||||
import haveno.network.p2p.P2PService;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import org.bitcoinj.core.AddressFormatException;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.InsufficientMoneyException;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Named;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static haveno.desktop.util.FormBuilder.addInputTextField;
|
||||
import static haveno.desktop.util.FormBuilder.addMultilineLabel;
|
||||
import static haveno.desktop.util.FormBuilder.addTopLabelTextField;
|
||||
|
||||
public final class BtcEmptyWalletWindow extends Overlay<BtcEmptyWalletWindow> {
|
||||
protected static final Logger log = LoggerFactory.getLogger(BtcEmptyWalletWindow.class);
|
||||
|
||||
private final WalletPasswordWindow walletPasswordWindow;
|
||||
private final OpenOfferManager openOfferManager;
|
||||
private final P2PService p2PService;
|
||||
private final CoreMoneroConnectionsService connectionService;
|
||||
private final BtcWalletService btcWalletService;
|
||||
private final CoinFormatter btcFormatter;
|
||||
|
||||
private Button emptyWalletButton;
|
||||
private InputTextField addressInputTextField;
|
||||
private TextField balanceTextField;
|
||||
|
||||
@Inject
|
||||
public BtcEmptyWalletWindow(WalletPasswordWindow walletPasswordWindow,
|
||||
OpenOfferManager openOfferManager,
|
||||
P2PService p2PService,
|
||||
CoreMoneroConnectionsService connectionService,
|
||||
BtcWalletService btcWalletService,
|
||||
@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter) {
|
||||
headLine(Res.get("emptyWalletWindow.headline", "BTC"));
|
||||
width = 768;
|
||||
type = Type.Instruction;
|
||||
|
||||
this.p2PService = p2PService;
|
||||
this.connectionService = connectionService;
|
||||
this.btcWalletService = btcWalletService;
|
||||
this.btcFormatter = btcFormatter;
|
||||
this.walletPasswordWindow = walletPasswordWindow;
|
||||
this.openOfferManager = openOfferManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
createGridPane();
|
||||
addHeadLine();
|
||||
addContent();
|
||||
applyStyles();
|
||||
display();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupKeyHandler(Scene scene) {
|
||||
if (!hideCloseButton) {
|
||||
scene.setOnKeyPressed(e -> {
|
||||
if (e.getCode() == KeyCode.ESCAPE) {
|
||||
e.consume();
|
||||
doClose();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void addContent() {
|
||||
addMultilineLabel(gridPane, ++rowIndex, Res.get("emptyWalletWindow.info"), 0);
|
||||
|
||||
Coin totalBalance = btcWalletService.getAvailableConfirmedBalance();
|
||||
balanceTextField = addTopLabelTextField(gridPane, ++rowIndex, Res.get("emptyWalletWindow.balance"),
|
||||
btcFormatter.formatCoinWithCode(totalBalance), 10).second;
|
||||
|
||||
addressInputTextField = addInputTextField(gridPane, ++rowIndex, Res.get("emptyWalletWindow.address"));
|
||||
|
||||
closeButton = new AutoTooltipButton(Res.get("shared.cancel"));
|
||||
closeButton.setOnAction(e -> {
|
||||
hide();
|
||||
closeHandlerOptional.ifPresent(Runnable::run);
|
||||
});
|
||||
|
||||
emptyWalletButton = new AutoTooltipButton(Res.get("emptyWalletWindow.button"));
|
||||
boolean isBalanceSufficient = Restrictions.isAboveDust(totalBalance);
|
||||
emptyWalletButton.setDefaultButton(isBalanceSufficient);
|
||||
emptyWalletButton.setDisable(!isBalanceSufficient && addressInputTextField.getText().length() > 0);
|
||||
emptyWalletButton.setOnAction(e -> {
|
||||
if (addressInputTextField.getText().length() > 0 && isBalanceSufficient) {
|
||||
log.warn(getClass().getSimpleName() + ".addContent() needs updated for XMR");
|
||||
}
|
||||
});
|
||||
|
||||
closeButton.setDefaultButton(!isBalanceSufficient);
|
||||
|
||||
HBox hBox = new HBox();
|
||||
hBox.setSpacing(10);
|
||||
GridPane.setRowIndex(hBox, ++rowIndex);
|
||||
hBox.getChildren().addAll(emptyWalletButton, closeButton);
|
||||
gridPane.getChildren().add(hBox);
|
||||
GridPane.setMargin(hBox, new Insets(10, 0, 0, 0));
|
||||
}
|
||||
|
||||
private void doEmptyWallet(KeyParameter aesKey) {
|
||||
if (GUIUtil.isReadyForTxBroadcastOrShowPopup(p2PService, connectionService)) {
|
||||
if (!openOfferManager.getObservableList().isEmpty()) {
|
||||
UserThread.runAfter(() ->
|
||||
new Popup().warning(Res.get("emptyWalletWindow.openOffers.warn"))
|
||||
.actionButtonText(Res.get("emptyWalletWindow.openOffers.yes"))
|
||||
.onAction(() -> doEmptyWallet2(aesKey))
|
||||
.show(), 300, TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
doEmptyWallet2(aesKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doEmptyWallet2(KeyParameter aesKey) {
|
||||
emptyWalletButton.setDisable(true);
|
||||
openOfferManager.removeAllOpenOffers(() -> {
|
||||
try {
|
||||
btcWalletService.emptyBtcWallet(addressInputTextField.getText(),
|
||||
aesKey,
|
||||
() -> {
|
||||
closeButton.updateText(Res.get("shared.close"));
|
||||
balanceTextField.setText(btcFormatter.formatCoinWithCode(btcWalletService.getAvailableConfirmedBalance()));
|
||||
emptyWalletButton.setDisable(true);
|
||||
log.debug("wallet empty successful");
|
||||
onClose(() -> UserThread.runAfter(() -> new Popup()
|
||||
.feedback(Res.get("emptyWalletWindow.sent.success"))
|
||||
.show(), Transitions.DEFAULT_DURATION, TimeUnit.MILLISECONDS));
|
||||
doClose();
|
||||
},
|
||||
(errorMessage) -> {
|
||||
emptyWalletButton.setDisable(false);
|
||||
log.error("wallet empty failed {}", errorMessage);
|
||||
});
|
||||
} catch (InsufficientMoneyException | AddressFormatException e1) {
|
||||
e1.printStackTrace();
|
||||
log.error(e1.getMessage());
|
||||
emptyWalletButton.setDisable(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,821 +0,0 @@
|
|||
/*
|
||||
* This file is part of Haveno.
|
||||
*
|
||||
* Haveno is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Haveno is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package haveno.desktop.main.overlays.windows;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
import haveno.common.UserThread;
|
||||
import haveno.common.config.Config;
|
||||
import haveno.common.util.Base64;
|
||||
import haveno.common.util.Tuple2;
|
||||
import haveno.common.util.Utilities;
|
||||
import haveno.core.api.CoreMoneroConnectionsService;
|
||||
import haveno.core.locale.Res;
|
||||
import haveno.core.payment.validation.LengthValidator;
|
||||
import haveno.core.payment.validation.PercentageNumberValidator;
|
||||
import haveno.core.support.dispute.Dispute;
|
||||
import haveno.core.support.dispute.mediation.MediationManager;
|
||||
import haveno.core.user.BlockChainExplorer;
|
||||
import haveno.core.user.Preferences;
|
||||
import haveno.core.xmr.exceptions.TransactionVerificationException;
|
||||
import haveno.core.xmr.exceptions.TxBroadcastException;
|
||||
import haveno.core.xmr.exceptions.WalletException;
|
||||
import haveno.core.xmr.wallet.TradeWalletService;
|
||||
import haveno.core.xmr.wallet.TxBroadcaster;
|
||||
import haveno.core.xmr.wallet.WalletsManager;
|
||||
import haveno.desktop.components.AutoTooltipButton;
|
||||
import haveno.desktop.components.HavenoTextArea;
|
||||
import haveno.desktop.components.InputTextField;
|
||||
import haveno.desktop.main.overlays.Overlay;
|
||||
import haveno.desktop.main.overlays.popups.Popup;
|
||||
import haveno.desktop.util.GUIUtil;
|
||||
import haveno.network.p2p.P2PService;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Separator;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.layout.ColumnConstraints;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.bitcoinj.core.Address;
|
||||
import org.bitcoinj.core.AddressFormatException;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.core.SignatureDecodeException;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.Utils;
|
||||
import org.bitcoinj.core.VerificationException;
|
||||
import org.bitcoinj.script.Script;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.SignatureException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static haveno.desktop.util.FormBuilder.addCheckBox;
|
||||
import static haveno.desktop.util.FormBuilder.addInputTextField;
|
||||
import static haveno.desktop.util.FormBuilder.addTopLabelComboBox;
|
||||
|
||||
// We don't translate here as it is for dev only purpose
|
||||
public class ManualPayoutTxWindow extends Overlay<ManualPayoutTxWindow> {
|
||||
private static final int HEX_HASH_LENGTH = 32 * 2;
|
||||
private static final int HEX_PUBKEY_LENGTH = 33 * 2;
|
||||
private static final Logger log = LoggerFactory.getLogger(ManualPayoutTxWindow.class);
|
||||
private final TradeWalletService tradeWalletService;
|
||||
private final P2PService p2PService;
|
||||
private final MediationManager mediationManager;
|
||||
private final Preferences preferences;
|
||||
private final CoreMoneroConnectionsService connectionService;
|
||||
private final WalletsManager walletsManager;
|
||||
GridPane inputsGridPane;
|
||||
GridPane importTxGridPane;
|
||||
GridPane exportTxGridPane;
|
||||
GridPane signTxGridPane;
|
||||
GridPane buildTxGridPane;
|
||||
GridPane signVerifyMsgGridPane;
|
||||
CheckBox depositTxLegacy, recentTickets;
|
||||
ComboBox<String> mediationDropDown;
|
||||
ObservableList<Dispute> disputeObservableList;
|
||||
InputTextField depositTxHex;
|
||||
InputTextField amountInMultisig;
|
||||
InputTextField buyerPayoutAmount;
|
||||
InputTextField sellerPayoutAmount;
|
||||
InputTextField txFee;
|
||||
InputTextField txFeePct;
|
||||
InputTextField buyerAddressString;
|
||||
InputTextField sellerAddressString;
|
||||
InputTextField buyerPubKeyAsHex;
|
||||
InputTextField sellerPubKeyAsHex;
|
||||
InputTextField buyerSignatureAsHex;
|
||||
InputTextField sellerSignatureAsHex;
|
||||
InputTextField privateKeyHex;
|
||||
InputTextField signatureHex;
|
||||
TextArea importHex;
|
||||
TextArea exportHex;
|
||||
TextArea finalSignedTxHex;
|
||||
private ChangeListener<Boolean> txFeeListener, amountInMultisigListener, buyerPayoutAmountListener, sellerPayoutAmountListener;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public ManualPayoutTxWindow(TradeWalletService tradeWalletService,
|
||||
P2PService p2PService,
|
||||
MediationManager mediationManager,
|
||||
Preferences preferences,
|
||||
CoreMoneroConnectionsService connectionService,
|
||||
WalletsManager walletsManager) {
|
||||
this.tradeWalletService = tradeWalletService;
|
||||
this.p2PService = p2PService;
|
||||
this.mediationManager = mediationManager;
|
||||
this.preferences = preferences;
|
||||
this.connectionService = connectionService;
|
||||
this.walletsManager = walletsManager;
|
||||
type = Type.Attention;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
if (headLine == null)
|
||||
headLine = "Emergency MultiSig payout tool"; // We dont translate here as it is for dev only purpose
|
||||
|
||||
width = 1068;
|
||||
createGridPane();
|
||||
addHeadLine();
|
||||
addContent();
|
||||
addButtons();
|
||||
applyStyles();
|
||||
txFeeListener = (observable, oldValue, newValue) -> {
|
||||
calculateTxFee();
|
||||
};
|
||||
buyerPayoutAmountListener = (observable, oldValue, newValue) -> {
|
||||
calculateTxFee();
|
||||
};
|
||||
sellerPayoutAmountListener = (observable, oldValue, newValue) -> {
|
||||
calculateTxFee();
|
||||
};
|
||||
amountInMultisigListener = (observable, oldValue, newValue) -> {
|
||||
calculateTxFee();
|
||||
};
|
||||
txFee.focusedProperty().addListener(txFeeListener);
|
||||
buyerPayoutAmount.focusedProperty().addListener(buyerPayoutAmountListener);
|
||||
sellerPayoutAmount.focusedProperty().addListener(sellerPayoutAmountListener);
|
||||
amountInMultisig.focusedProperty().addListener(amountInMultisigListener);
|
||||
display();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void setupKeyHandler(Scene scene) {
|
||||
if (!hideCloseButton) {
|
||||
scene.setOnKeyPressed(e -> {
|
||||
if (e.getCode() == KeyCode.ESCAPE) {
|
||||
e.consume();
|
||||
doClose();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createGridPane() {
|
||||
gridPane = new GridPane();
|
||||
gridPane.setHgap(15);
|
||||
gridPane.setVgap(15);
|
||||
gridPane.setPadding(new Insets(64, 64, 64, 64));
|
||||
gridPane.setPrefWidth(width);
|
||||
ColumnConstraints columnConstraints1 = new ColumnConstraints();
|
||||
ColumnConstraints columnConstraints2 = new ColumnConstraints();
|
||||
columnConstraints1.setPercentWidth(25);
|
||||
columnConstraints2.setPercentWidth(75);
|
||||
gridPane.getColumnConstraints().addAll(columnConstraints1, columnConstraints2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanup() {
|
||||
txFee.focusedProperty().removeListener(txFeeListener);
|
||||
buyerPayoutAmount.focusedProperty().removeListener(buyerPayoutAmountListener);
|
||||
sellerPayoutAmount.focusedProperty().removeListener(sellerPayoutAmountListener);
|
||||
amountInMultisig.focusedProperty().removeListener(amountInMultisigListener);
|
||||
super.cleanup();
|
||||
}
|
||||
|
||||
private void addContent() {
|
||||
rowIndex = 1;
|
||||
this.disableActionButton = true;
|
||||
addLeftPanelButtons();
|
||||
addInputsPane();
|
||||
addImportPane();
|
||||
addExportPane();
|
||||
addSignPane();
|
||||
addBuildPane();
|
||||
signVerifyMsgGridPane = addSignVerifyMsgPane(new GridPane());
|
||||
hideAllPanes();
|
||||
inputsGridPane.setVisible(true);
|
||||
|
||||
// Notes:
|
||||
// Open with alt+g
|
||||
// Priv key is only visible if pw protection is removed (wallet details data (alt+j))
|
||||
// Take missing buyerPubKeyAsHex and sellerPubKeyAsHex from contract data!
|
||||
// Lookup sellerPrivateKeyAsHex associated with sellerPubKeyAsHex (or buyers) in wallet details data
|
||||
// sellerPubKeys/buyerPubKeys are auto generated if used the fields below
|
||||
}
|
||||
|
||||
private void addLeftPanelButtons() {
|
||||
Button buttonInputs = new AutoTooltipButton("Inputs");
|
||||
Button buttonImport = new AutoTooltipButton("Import");
|
||||
Button buttonExport = new AutoTooltipButton("Export");
|
||||
Button buttonSign = new AutoTooltipButton("Sign");
|
||||
Button buttonBuild = new AutoTooltipButton("Build");
|
||||
Button buttonSignVerifyMsg = new AutoTooltipButton("Sign/Verify Msg");
|
||||
VBox vBox = new VBox(12, buttonInputs, buttonImport, buttonExport, buttonSign, buttonBuild, buttonSignVerifyMsg);
|
||||
vBox.getChildren().forEach(button -> ((Button) button).setPrefWidth(500));
|
||||
gridPane.add(vBox, 0, rowIndex);
|
||||
buttonInputs.getStyleClass().add("action-button");
|
||||
buttonInputs.setOnAction(e -> { // just show the inputs pane
|
||||
hideAllPanes();
|
||||
vBox.getChildren().forEach(button -> button.getStyleClass().remove("action-button"));
|
||||
buttonInputs.getStyleClass().add("action-button");
|
||||
inputsGridPane.setVisible(true);
|
||||
});
|
||||
buttonImport.setOnAction(e -> { // just show the import pane
|
||||
hideAllPanes();
|
||||
vBox.getChildren().forEach(button -> button.getStyleClass().remove("action-button"));
|
||||
buttonImport.getStyleClass().add("action-button");
|
||||
importTxGridPane.setVisible(true);
|
||||
importHex.setText("");
|
||||
});
|
||||
buttonExport.setOnAction(e -> { // show export pane and fill in the data
|
||||
hideAllPanes();
|
||||
vBox.getChildren().forEach(button -> button.getStyleClass().remove("action-button"));
|
||||
buttonExport.getStyleClass().add("action-button");
|
||||
exportTxGridPane.setVisible(true);
|
||||
exportHex.setText(generateExportText());
|
||||
});
|
||||
buttonSign.setOnAction(e -> { // just show the sign pane
|
||||
hideAllPanes();
|
||||
vBox.getChildren().forEach(button -> button.getStyleClass().remove("action-button"));
|
||||
buttonSign.getStyleClass().add("action-button");
|
||||
signTxGridPane.setVisible(true);
|
||||
privateKeyHex.setText("");
|
||||
signatureHex.setText("");
|
||||
});
|
||||
buttonBuild.setOnAction(e -> { // just show the build pane
|
||||
hideAllPanes();
|
||||
vBox.getChildren().forEach(button -> button.getStyleClass().remove("action-button"));
|
||||
buttonBuild.getStyleClass().add("action-button");
|
||||
buildTxGridPane.setVisible(true);
|
||||
finalSignedTxHex.setText("");
|
||||
});
|
||||
buttonSignVerifyMsg.setOnAction(e -> { // just show the sign msg pane
|
||||
hideAllPanes();
|
||||
vBox.getChildren().forEach(button -> button.getStyleClass().remove("action-button"));
|
||||
buttonSignVerifyMsg.getStyleClass().add("action-button");
|
||||
signVerifyMsgGridPane.setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
private void addInputsPane() {
|
||||
inputsGridPane = new GridPane();
|
||||
gridPane.add(inputsGridPane, 1, rowIndex);
|
||||
int rowIndexA = 0;
|
||||
|
||||
depositTxLegacy = addCheckBox(inputsGridPane, rowIndexA, "depositTxLegacy");
|
||||
|
||||
Tooltip tooltip = new Tooltip(Res.get("txIdTextField.blockExplorerIcon.tooltip"));
|
||||
Label blockExplorerIcon = new Label();
|
||||
blockExplorerIcon.getStyleClass().addAll("icon", "highlight");
|
||||
blockExplorerIcon.setTooltip(tooltip);
|
||||
AwesomeDude.setIcon(blockExplorerIcon, AwesomeIcon.EXTERNAL_LINK);
|
||||
blockExplorerIcon.setMinWidth(20);
|
||||
blockExplorerIcon.setOnMouseClicked(mouseEvent -> openBlockExplorer(depositTxHex.getText()));
|
||||
depositTxHex = addInputTextField(inputsGridPane, rowIndexA, "depositTxId");
|
||||
HBox hBoxTx = new HBox(12, depositTxHex, blockExplorerIcon);
|
||||
hBoxTx.setAlignment(Pos.BASELINE_LEFT);
|
||||
hBoxTx.setPrefWidth(800);
|
||||
inputsGridPane.add(new Label(""), 0, ++rowIndexA); // spacer
|
||||
inputsGridPane.add(hBoxTx, 0, ++rowIndexA);
|
||||
|
||||
amountInMultisig = addInputTextField(inputsGridPane, ++rowIndexA, "amountInMultisig");
|
||||
inputsGridPane.add(new Label(""), 0, ++rowIndexA); // spacer
|
||||
buyerPayoutAmount = addInputTextField(inputsGridPane, rowIndexA, "buyerPayoutAmount");
|
||||
sellerPayoutAmount = addInputTextField(inputsGridPane, rowIndexA, "sellerPayoutAmount");
|
||||
txFee = addInputTextField(inputsGridPane, rowIndexA, "Tx fee");
|
||||
txFee.setEditable(false);
|
||||
txFeePct = addInputTextField(inputsGridPane, rowIndexA, "Tx fee %");
|
||||
txFeePct.setEditable(false);
|
||||
PercentageNumberValidator validator = new PercentageNumberValidator();
|
||||
validator.setMaxValue(10D);
|
||||
txFeePct.setValidator(validator);
|
||||
|
||||
HBox hBox = new HBox(12, buyerPayoutAmount, sellerPayoutAmount, txFee, txFeePct);
|
||||
hBox.setAlignment(Pos.BASELINE_LEFT);
|
||||
hBox.setPrefWidth(800);
|
||||
inputsGridPane.add(hBox, 0, ++rowIndexA);
|
||||
buyerAddressString = addInputTextField(inputsGridPane, ++rowIndexA, "buyerPayoutAddress");
|
||||
sellerAddressString = addInputTextField(inputsGridPane, ++rowIndexA, "sellerPayoutAddress");
|
||||
buyerPubKeyAsHex = addInputTextField(inputsGridPane, ++rowIndexA, "buyerPubKeyAsHex");
|
||||
sellerPubKeyAsHex = addInputTextField(inputsGridPane, ++rowIndexA, "sellerPubKeyAsHex");
|
||||
depositTxHex.setPrefWidth(800);
|
||||
depositTxLegacy.setAllowIndeterminate(false);
|
||||
depositTxLegacy.setSelected(false);
|
||||
depositTxHex.setValidator(new LengthValidator(HEX_HASH_LENGTH, HEX_HASH_LENGTH));
|
||||
buyerAddressString.setValidator(new LengthValidator(20, 80));
|
||||
sellerAddressString.setValidator(new LengthValidator(20, 80));
|
||||
buyerPubKeyAsHex.setValidator(new LengthValidator(HEX_PUBKEY_LENGTH, HEX_PUBKEY_LENGTH));
|
||||
sellerPubKeyAsHex.setValidator(new LengthValidator(HEX_PUBKEY_LENGTH, HEX_PUBKEY_LENGTH));
|
||||
}
|
||||
|
||||
private void addImportPane() {
|
||||
int rowIndexB = 0;
|
||||
importTxGridPane = new GridPane();
|
||||
gridPane.add(importTxGridPane, 1, rowIndex);
|
||||
importHex = new HavenoTextArea();
|
||||
importHex.setEditable(true);
|
||||
importHex.setWrapText(true);
|
||||
importHex.setPrefSize(800, 150);
|
||||
importTxGridPane.add(importHex, 0, ++rowIndexB);
|
||||
importTxGridPane.add(new Label(""), 0, ++rowIndexB); // spacer
|
||||
Button buttonImport = new AutoTooltipButton("Import From String");
|
||||
buttonImport.setOnAction(e -> {
|
||||
// here we need to populate the "inputs" fields from the data contained in the TextArea
|
||||
if (doImport(importHex.getText())) {
|
||||
// switch back to the inputs pane
|
||||
hideAllPanes();
|
||||
inputsGridPane.setVisible(true);
|
||||
}
|
||||
});
|
||||
HBox hBox = new HBox(12, buttonImport);
|
||||
hBox.setAlignment(Pos.BASELINE_CENTER);
|
||||
hBox.setPrefWidth(800);
|
||||
importTxGridPane.add(hBox, 0, ++rowIndexB);
|
||||
importTxGridPane.add(new Label(""), 0, ++rowIndexB); // spacer
|
||||
|
||||
final Separator separator = new Separator(Orientation.HORIZONTAL);
|
||||
separator.setPadding(new Insets(10, 10, 10, 10));
|
||||
importTxGridPane.add(separator, 0, ++rowIndexB);
|
||||
|
||||
importTxGridPane.add(new Label(""), 0, ++rowIndexB); // spacer
|
||||
final Tuple2<Label, ComboBox<String>> xTuple = addTopLabelComboBox(importTxGridPane, rowIndexB, "Mediation Ticket", "", 0);
|
||||
mediationDropDown = xTuple.second;
|
||||
recentTickets = addCheckBox(importTxGridPane, rowIndexB, "Recent Tickets");
|
||||
recentTickets.setSelected(true);
|
||||
HBox hBox2 = new HBox(12, mediationDropDown, recentTickets);
|
||||
hBox2.setAlignment(Pos.BASELINE_CENTER);
|
||||
hBox2.setPrefWidth(800);
|
||||
importTxGridPane.add(hBox2, 0, ++rowIndexB);
|
||||
populateMediationTicketCombo(recentTickets.isSelected());
|
||||
recentTickets.setOnAction(e -> {
|
||||
populateMediationTicketCombo(recentTickets.isSelected());
|
||||
});
|
||||
importTxGridPane.add(new Label(""), 0, ++rowIndexB); // spacer
|
||||
Button buttonImportTicket = new AutoTooltipButton("Import From Mediation Ticket");
|
||||
buttonImportTicket.setOnAction(e -> {
|
||||
// here we need to populate the "inputs" fields from the chosen mediator ticket
|
||||
importFromMediationTicket(mediationDropDown.getValue());
|
||||
});
|
||||
HBox hBox3 = new HBox(12, buttonImportTicket);
|
||||
hBox3.setAlignment(Pos.BASELINE_CENTER);
|
||||
hBox3.setPrefWidth(800);
|
||||
importTxGridPane.add(hBox3, 0, ++rowIndexB);
|
||||
}
|
||||
|
||||
private void addExportPane() {
|
||||
exportTxGridPane = new GridPane();
|
||||
gridPane.add(exportTxGridPane, 1, rowIndex);
|
||||
exportHex = new HavenoTextArea();
|
||||
exportHex.setEditable(false);
|
||||
exportHex.setWrapText(true);
|
||||
exportHex.setPrefSize(800, 250);
|
||||
exportTxGridPane.add(exportHex, 0, 1);
|
||||
}
|
||||
|
||||
private void addSignPane() {
|
||||
int rowIndexB = 0;
|
||||
signTxGridPane = new GridPane();
|
||||
gridPane.add(signTxGridPane, 1, rowIndex);
|
||||
privateKeyHex = addInputTextField(inputsGridPane, ++rowIndexB, "privateKeyHex");
|
||||
signTxGridPane.add(privateKeyHex, 0, ++rowIndexB);
|
||||
signatureHex = addInputTextField(signTxGridPane, ++rowIndexB, "signatureHex");
|
||||
signatureHex.setPrefWidth(800);
|
||||
signatureHex.setEditable(false);
|
||||
Label copyIcon = new Label();
|
||||
copyIcon.setTooltip(new Tooltip(Res.get("txIdTextField.copyIcon.tooltip")));
|
||||
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
|
||||
copyIcon.getStyleClass().addAll("icon", "highlight");
|
||||
copyIcon.setMinWidth(20);
|
||||
copyIcon.setOnMouseClicked(mouseEvent -> Utilities.copyToClipboard(signatureHex.getText()));
|
||||
HBox hBoxSig = new HBox(12, signatureHex, copyIcon);
|
||||
hBoxSig.setAlignment(Pos.BASELINE_LEFT);
|
||||
hBoxSig.setPrefWidth(800);
|
||||
signTxGridPane.add(new Label(""), 0, ++rowIndexB); // spacer
|
||||
signTxGridPane.add(hBoxSig, 0, ++rowIndexB);
|
||||
signTxGridPane.add(new Label(""), 0, ++rowIndexB); // spacer
|
||||
Button buttonLocate = new AutoTooltipButton("Locate key in wallet");
|
||||
Button buttonSign = new AutoTooltipButton("Generate Signature");
|
||||
HBox hBox = new HBox(12, buttonLocate, buttonSign);
|
||||
hBox.setAlignment(Pos.BASELINE_CENTER);
|
||||
hBox.setPrefWidth(800);
|
||||
signTxGridPane.add(hBox, 0, ++rowIndexB);
|
||||
buttonLocate.setOnAction(e -> {
|
||||
if (!validateInputFields()) {
|
||||
signatureHex.setText("You need to fill in the inputs tab first");
|
||||
return;
|
||||
}
|
||||
String walletInfo = walletsManager.getWalletsAsString(true);
|
||||
String privateKeyText = findPrivForPubOrAddress(walletInfo, buyerPubKeyAsHex.getText());
|
||||
if (privateKeyText == null) {
|
||||
privateKeyText = findPrivForPubOrAddress(walletInfo, sellerPubKeyAsHex.getText());
|
||||
}
|
||||
if (privateKeyText == null) {
|
||||
privateKeyText = "Not found in wallet";
|
||||
}
|
||||
privateKeyHex.setText(privateKeyText);
|
||||
});
|
||||
buttonSign.setOnAction(e -> {
|
||||
signatureHex.setText(generateSignature());
|
||||
});
|
||||
}
|
||||
|
||||
private void addBuildPane() {
|
||||
buildTxGridPane = new GridPane();
|
||||
gridPane.add(buildTxGridPane, 1, rowIndex);
|
||||
int rowIndexA = 0;
|
||||
buyerSignatureAsHex = addInputTextField(buildTxGridPane, ++rowIndexA, "buyerSignatureAsHex");
|
||||
sellerSignatureAsHex = addInputTextField(buildTxGridPane, ++rowIndexA, "sellerSignatureAsHex");
|
||||
buildTxGridPane.add(new Label(""), 0, ++rowIndexA); // spacer
|
||||
finalSignedTxHex = new HavenoTextArea();
|
||||
finalSignedTxHex.setEditable(false);
|
||||
finalSignedTxHex.setWrapText(true);
|
||||
finalSignedTxHex.setPrefSize(800, 250);
|
||||
buildTxGridPane.add(finalSignedTxHex, 0, ++rowIndexA);
|
||||
buildTxGridPane.add(new Label(""), 0, ++rowIndexA); // spacer
|
||||
Button buttonBuild = new AutoTooltipButton("Build");
|
||||
Button buttonBroadcast = new AutoTooltipButton("Broadcast");
|
||||
HBox hBox = new HBox(12, buttonBuild, buttonBroadcast);
|
||||
hBox.setAlignment(Pos.BASELINE_CENTER);
|
||||
hBox.setPrefWidth(800);
|
||||
buildTxGridPane.add(hBox, 0, ++rowIndexA);
|
||||
buttonBuild.setOnAction(e -> {
|
||||
finalSignedTxHex.setText(buildFinalTx(false));
|
||||
});
|
||||
buttonBroadcast.setOnAction(e -> {
|
||||
finalSignedTxHex.setText(buildFinalTx(true));
|
||||
});
|
||||
}
|
||||
|
||||
private GridPane addSignVerifyMsgPane(GridPane myGridPane) {
|
||||
int rowIndexB = 0;
|
||||
gridPane.add(myGridPane, 1, rowIndex);
|
||||
TextArea messageText = new HavenoTextArea();
|
||||
messageText.setPromptText("Message");
|
||||
messageText.setEditable(true);
|
||||
messageText.setWrapText(true);
|
||||
messageText.setPrefSize(800, 150);
|
||||
myGridPane.add(messageText, 0, ++rowIndexB);
|
||||
myGridPane.add(new Label(""), 0, ++rowIndexB); // spacer
|
||||
InputTextField address = addInputTextField(myGridPane, ++rowIndexB, "Address");
|
||||
myGridPane.add(new Label(""), 0, ++rowIndexB); // spacer
|
||||
TextArea messageSig = new HavenoTextArea();
|
||||
messageSig.setPromptText("Signature");
|
||||
messageSig.setEditable(true);
|
||||
messageSig.setWrapText(true);
|
||||
messageSig.setPrefSize(800, 65);
|
||||
myGridPane.add(messageSig, 0, ++rowIndexB);
|
||||
myGridPane.add(new Label(""), 0, ++rowIndexB); // spacer
|
||||
Button buttonSign = new AutoTooltipButton("Sign");
|
||||
Button buttonVerify = new AutoTooltipButton("Verify");
|
||||
HBox buttonBox = new HBox(12, buttonSign, buttonVerify);
|
||||
buttonBox.setAlignment(Pos.BASELINE_CENTER);
|
||||
buttonBox.setPrefWidth(800);
|
||||
myGridPane.add(buttonBox, 0, ++rowIndexB);
|
||||
|
||||
buttonSign.setOnAction(e -> {
|
||||
String walletInfo = walletsManager.getWalletsAsString(true);
|
||||
String privKeyHex = findPrivForPubOrAddress(walletInfo, address.getText());
|
||||
if (privKeyHex == null) {
|
||||
messageSig.setText("");
|
||||
new Popup().information("Key not found in wallet").show();
|
||||
} else {
|
||||
ECKey myPrivateKey = ECKey.fromPrivate(Utils.HEX.decode(privKeyHex));
|
||||
String signatureBase64 = myPrivateKey.signMessage(messageText.getText());
|
||||
messageSig.setText(signatureBase64);
|
||||
}
|
||||
});
|
||||
buttonVerify.setOnAction(e -> {
|
||||
try {
|
||||
ECKey key = ECKey.signedMessageToKey(messageText.getText(), messageSig.getText());
|
||||
Address address1 = Address.fromKey(Config.baseCurrencyNetworkParameters(), key, Script.ScriptType.P2PKH);
|
||||
Address address2 = Address.fromKey(Config.baseCurrencyNetworkParameters(), key, Script.ScriptType.P2WPKH);
|
||||
if (address.getText().equalsIgnoreCase(address1.toString()) ||
|
||||
address.getText().equalsIgnoreCase(address2.toString())) {
|
||||
new Popup().information("Signature verified").show();
|
||||
} else {
|
||||
new Popup().warning("Wrong signature").show();
|
||||
}
|
||||
} catch (SignatureException ex) {
|
||||
log.warn(ex.toString());
|
||||
new Popup().warning("Wrong signature").show();
|
||||
}
|
||||
});
|
||||
return myGridPane;
|
||||
}
|
||||
|
||||
private void hideAllPanes() {
|
||||
inputsGridPane.setVisible(false);
|
||||
importTxGridPane.setVisible(false);
|
||||
exportTxGridPane.setVisible(false);
|
||||
signTxGridPane.setVisible(false);
|
||||
buildTxGridPane.setVisible(false);
|
||||
signVerifyMsgGridPane.setVisible(false);
|
||||
}
|
||||
|
||||
private void populateMediationTicketCombo(boolean recentTicketsOnly) {
|
||||
Instant twoWeeksAgo = Instant.ofEpochSecond(Instant.now().getEpochSecond() - TimeUnit.DAYS.toSeconds(14));
|
||||
disputeObservableList = mediationManager.getDisputesAsObservableList();
|
||||
ObservableList<String> disputeIds = FXCollections.observableArrayList();
|
||||
for (Dispute dispute :disputeObservableList) {
|
||||
if (dispute.getDisputePayoutTxId() != null) // only show disputes not paid out
|
||||
continue;
|
||||
if (recentTicketsOnly && dispute.getOpeningDate().toInstant().isBefore(twoWeeksAgo))
|
||||
continue;
|
||||
if (!disputeIds.contains(dispute.getTradeId()))
|
||||
disputeIds.add(dispute.getTradeId());
|
||||
}
|
||||
disputeIds.sort((a, b) -> a.compareTo(b));
|
||||
mediationDropDown.setItems(disputeIds);
|
||||
}
|
||||
|
||||
private void clearInputFields() {
|
||||
depositTxHex.setText("");
|
||||
amountInMultisig.setText("");
|
||||
buyerPayoutAmount.setText("");
|
||||
sellerPayoutAmount.setText("");
|
||||
buyerAddressString.setText("");
|
||||
sellerAddressString.setText("");
|
||||
buyerPubKeyAsHex.setText("");
|
||||
sellerPubKeyAsHex.setText("");
|
||||
}
|
||||
|
||||
private boolean validateInputFields() {
|
||||
return (depositTxHex.getText().length() == HEX_HASH_LENGTH &&
|
||||
amountInMultisig.getText().length() > 0 &&
|
||||
buyerPayoutAmount.getText().length() > 0 &&
|
||||
sellerPayoutAmount.getText().length() > 0 &&
|
||||
txFee.getText().length() > 0 &&
|
||||
buyerAddressString.getText().length() > 0 &&
|
||||
sellerAddressString.getText().length() > 0 &&
|
||||
buyerPubKeyAsHex.getText().length() == HEX_PUBKEY_LENGTH &&
|
||||
sellerPubKeyAsHex.getText().length() == HEX_PUBKEY_LENGTH &&
|
||||
txFeePct.getValidator().validate(txFeePct.getText()).isValid);
|
||||
}
|
||||
|
||||
private boolean validateInputFieldsAndSignatures() {
|
||||
return (validateInputFields() &&
|
||||
buyerSignatureAsHex.getText().length() > 0 &&
|
||||
sellerSignatureAsHex.getText().length() > 0);
|
||||
}
|
||||
|
||||
private Coin getInputFieldAsCoin(InputTextField inputTextField) {
|
||||
try {
|
||||
return Coin.parseCoin(inputTextField.getText().trim());
|
||||
} catch (RuntimeException ignore) {
|
||||
}
|
||||
return Coin.ZERO;
|
||||
}
|
||||
|
||||
private void calculateTxFee() {
|
||||
if (buyerPayoutAmount.getText().length() > 0 &&
|
||||
sellerPayoutAmount.getText().length() > 0 &&
|
||||
amountInMultisig.getText().length() > 0) {
|
||||
Coin txFeeValue = getInputFieldAsCoin(amountInMultisig)
|
||||
.subtract(getInputFieldAsCoin(buyerPayoutAmount))
|
||||
.subtract(getInputFieldAsCoin(sellerPayoutAmount));
|
||||
txFee.setText(txFeeValue.toPlainString());
|
||||
double feePercent = (double) txFeeValue.value / getInputFieldAsCoin(amountInMultisig).value;
|
||||
txFeePct.setText(String.format("%.2f", feePercent * 100));
|
||||
}
|
||||
}
|
||||
|
||||
private void openBlockExplorer(String txId) {
|
||||
if (txId.length() != HEX_HASH_LENGTH)
|
||||
return;
|
||||
if (preferences != null) {
|
||||
BlockChainExplorer blockChainExplorer = preferences.getBlockChainExplorer();
|
||||
GUIUtil.openWebPage(blockChainExplorer.txUrl + txId, false);
|
||||
}
|
||||
}
|
||||
|
||||
private String findPrivForPubOrAddress(String walletInfo, String searchKey) {
|
||||
// split the walletInfo into lines, strip whitespace
|
||||
// look for lines beginning " addr:" followed by "DeterministicKey{pub HEX=" .... ", priv HEX="
|
||||
int lineIndex = 0;
|
||||
while (lineIndex < walletInfo.length() && lineIndex != -1) {
|
||||
lineIndex = walletInfo.indexOf(" addr:", lineIndex);
|
||||
if (lineIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
int toIndex = walletInfo.indexOf("}", lineIndex);
|
||||
if (toIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
String candidate1 = walletInfo.substring(lineIndex, toIndex);
|
||||
lineIndex = toIndex;
|
||||
// do we have the search key?
|
||||
if (candidate1.indexOf(searchKey, 0) > -1) {
|
||||
int startOfPriv = candidate1.indexOf("priv HEX=", 0);
|
||||
if (startOfPriv > -1) {
|
||||
return candidate1.substring(startOfPriv + 9, startOfPriv + 9 + HEX_HASH_LENGTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String generateExportText() {
|
||||
// check that all input fields have been entered, except signatures
|
||||
ArrayList<String> fieldList = new ArrayList<>();
|
||||
fieldList.add(depositTxLegacy.isSelected() ? "legacy" : "segwit");
|
||||
fieldList.add(depositTxHex.getText());
|
||||
fieldList.add(amountInMultisig.getText());
|
||||
fieldList.add(buyerPayoutAmount.getText());
|
||||
fieldList.add(sellerPayoutAmount.getText());
|
||||
fieldList.add(buyerAddressString.getText());
|
||||
fieldList.add(sellerAddressString.getText());
|
||||
fieldList.add(buyerPubKeyAsHex.getText());
|
||||
fieldList.add(sellerPubKeyAsHex.getText());
|
||||
for (String item : fieldList) {
|
||||
if (item.length() < 1) {
|
||||
return "You need to fill in the inputs first";
|
||||
}
|
||||
}
|
||||
String listString = String.join(":", fieldList);
|
||||
String base64encoded = Base64.encode(listString.getBytes());
|
||||
return base64encoded;
|
||||
}
|
||||
|
||||
private boolean doImport(String importedText) {
|
||||
try {
|
||||
clearInputFields();
|
||||
String decoded = new String(Base64.decode(importedText.replaceAll("\\s+", "")), Charset.forName("UTF-8"));
|
||||
String splitArray[] = decoded.split(":");
|
||||
if (splitArray.length < 9) {
|
||||
importHex.setText("Import failed - data format incorrect");
|
||||
return false;
|
||||
}
|
||||
int fieldIndex = 0;
|
||||
depositTxLegacy.setSelected(splitArray[fieldIndex++].equalsIgnoreCase("legacy"));
|
||||
depositTxHex.setText(splitArray[fieldIndex++]);
|
||||
amountInMultisig.setText(splitArray[fieldIndex++]);
|
||||
buyerPayoutAmount.setText(splitArray[fieldIndex++]);
|
||||
sellerPayoutAmount.setText(splitArray[fieldIndex++]);
|
||||
buyerAddressString.setText(splitArray[fieldIndex++]);
|
||||
sellerAddressString.setText(splitArray[fieldIndex++]);
|
||||
buyerPubKeyAsHex.setText(splitArray[fieldIndex++]);
|
||||
sellerPubKeyAsHex.setText(splitArray[fieldIndex++]);
|
||||
calculateTxFee();
|
||||
} catch (IllegalArgumentException e) {
|
||||
importHex.setText("Import failed - base64 string incorrect");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void importFromMediationTicket(String tradeId) {
|
||||
throw new RuntimeException("ManualPayoutTxWindow.importFromMediationTicket() not adapted to XMR");
|
||||
// clearInputFields();
|
||||
// Optional<Dispute> optionalDispute = mediationManager.findDispute(tradeId);
|
||||
// if (optionalDispute.isPresent()) {
|
||||
// Dispute dispute = optionalDispute.get();
|
||||
// depositTxHex.setText(dispute.getDepositTxId());
|
||||
// if (dispute.disputeResultProperty().get() != null) {
|
||||
// buyerPayoutAmount.setText(dispute.disputeResultProperty().get().getBuyerPayoutAmount().toPlainString());
|
||||
// sellerPayoutAmount.setText(dispute.disputeResultProperty().get().getSellerPayoutAmount().toPlainString());
|
||||
// }
|
||||
// buyerAddressString.setText(dispute.getContract().getBuyerPayoutAddressString());
|
||||
// sellerAddressString.setText(dispute.getContract().getSellerPayoutAddressString());
|
||||
// buyerPubKeyAsHex.setText(Utils.HEX.encode(dispute.getContract().getBuyerMultiSigPubKey()));
|
||||
// sellerPubKeyAsHex.setText(Utils.HEX.encode(dispute.getContract().getSellerMultiSigPubKey()));
|
||||
// // switch back to the inputs pane
|
||||
// hideAllPanes();
|
||||
// inputsGridPane.setVisible(true);
|
||||
// UserThread.execute(() -> new Popup().warning("Ticket imported. You still need to enter the multisig amount and specify if it is a legacy Tx").show());
|
||||
// }
|
||||
}
|
||||
|
||||
private String generateSignature() {
|
||||
calculateTxFee();
|
||||
// check that all input fields have been entered, except signatures
|
||||
if (!validateInputFields() || privateKeyHex.getText().length() < 1) {
|
||||
return "You need to fill in the inputs first";
|
||||
}
|
||||
|
||||
String retVal = "";
|
||||
try {
|
||||
Tuple2<String, String> combined = tradeWalletService.emergencyBuildPayoutTxFrom2of2MultiSig(depositTxHex.getText(),
|
||||
getInputFieldAsCoin(buyerPayoutAmount),
|
||||
getInputFieldAsCoin(sellerPayoutAmount),
|
||||
getInputFieldAsCoin(txFee),
|
||||
buyerAddressString.getText(),
|
||||
sellerAddressString.getText(),
|
||||
buyerPubKeyAsHex.getText(),
|
||||
sellerPubKeyAsHex.getText(),
|
||||
depositTxLegacy.isSelected());
|
||||
String redeemScriptHex = combined.first;
|
||||
String unsignedTxHex = combined.second;
|
||||
retVal = tradeWalletService.emergencyGenerateSignature(
|
||||
unsignedTxHex,
|
||||
redeemScriptHex,
|
||||
getInputFieldAsCoin(amountInMultisig),
|
||||
privateKeyHex.getText());
|
||||
} catch (IllegalArgumentException ee) {
|
||||
log.error(ee.toString());
|
||||
ee.printStackTrace();
|
||||
UserThread.execute(() -> new Popup().warning(ee.toString()).show());
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private String buildFinalTx(boolean broadcastIt) {
|
||||
String retVal = "";
|
||||
calculateTxFee();
|
||||
// check that all input fields have been entered, including signatures
|
||||
if (!validateInputFieldsAndSignatures()) {
|
||||
retVal = "You need to fill in the inputs first";
|
||||
} else {
|
||||
try {
|
||||
// grab data from the inputs pane, build an unsigned tx and write it to the TextArea
|
||||
Tuple2<String, String> combined = tradeWalletService.emergencyBuildPayoutTxFrom2of2MultiSig(depositTxHex.getText(),
|
||||
getInputFieldAsCoin(buyerPayoutAmount),
|
||||
getInputFieldAsCoin(sellerPayoutAmount),
|
||||
getInputFieldAsCoin(txFee),
|
||||
buyerAddressString.getText(),
|
||||
sellerAddressString.getText(),
|
||||
buyerPubKeyAsHex.getText(),
|
||||
sellerPubKeyAsHex.getText(),
|
||||
depositTxLegacy.isSelected());
|
||||
String redeemScriptHex = combined.first;
|
||||
String unsignedTxHex = combined.second;
|
||||
Tuple2<String, String> txIdAndHex = tradeWalletService.emergencyApplySignatureToPayoutTxFrom2of2MultiSig(
|
||||
unsignedTxHex,
|
||||
redeemScriptHex,
|
||||
buyerSignatureAsHex.getText(),
|
||||
sellerSignatureAsHex.getText(),
|
||||
depositTxLegacy.isSelected());
|
||||
retVal = "txId:{" + txIdAndHex.first + "}\r\ntxHex:{" + txIdAndHex.second + "}";
|
||||
|
||||
if (broadcastIt) {
|
||||
TxBroadcaster.Callback callback = new TxBroadcaster.Callback() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable Transaction result) {
|
||||
log.info("onSuccess");
|
||||
UserThread.execute(() -> {
|
||||
String txId = result != null ? result.getTxId().toString() : "null";
|
||||
new Popup().information("Transaction successfully published. Transaction ID: " + txId).show();
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public void onFailure(TxBroadcastException exception) {
|
||||
log.error(exception.toString());
|
||||
UserThread.execute(() -> new Popup().warning(exception.toString()).show());
|
||||
}
|
||||
};
|
||||
|
||||
if (GUIUtil.isReadyForTxBroadcastOrShowPopup(p2PService, connectionService)) {
|
||||
try {
|
||||
tradeWalletService.emergencyPublishPayoutTxFrom2of2MultiSig(
|
||||
txIdAndHex.second,
|
||||
callback);
|
||||
} catch (AddressFormatException | WalletException | TransactionVerificationException ee) {
|
||||
log.error(ee.toString());
|
||||
ee.printStackTrace();
|
||||
UserThread.execute(() -> new Popup().warning(ee.toString()).show());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException | SignatureDecodeException | VerificationException ee) {
|
||||
log.error(ee.toString());
|
||||
ee.printStackTrace();
|
||||
retVal = ee.toString();
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* This file is part of Haveno.
|
||||
*
|
||||
* Haveno is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Haveno is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package haveno.desktop.main.overlays.windows;
|
||||
|
||||
import haveno.core.locale.Res;
|
||||
import haveno.core.trade.txproof.xmr.XmrTxProofModel;
|
||||
import haveno.core.util.validation.RegexValidator;
|
||||
import haveno.desktop.components.InputTextField;
|
||||
import haveno.desktop.main.overlays.Overlay;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.layout.ColumnConstraints;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import lombok.Getter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static haveno.common.app.DevEnv.isDevMode;
|
||||
import static haveno.desktop.util.FormBuilder.addInputTextField;
|
||||
import static haveno.desktop.util.FormBuilder.addMultilineLabel;
|
||||
import static javafx.beans.binding.Bindings.createBooleanBinding;
|
||||
|
||||
public class SetXmrTxKeyWindow extends Overlay<SetXmrTxKeyWindow> {
|
||||
|
||||
private InputTextField txHashInputTextField, txKeyInputTextField;
|
||||
@Getter
|
||||
private RegexValidator regexValidator;
|
||||
|
||||
public SetXmrTxKeyWindow() {
|
||||
type = Type.Attention;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (headLine == null)
|
||||
headLine = Res.get("setXMRTxKeyWindow.headline");
|
||||
|
||||
width = 868;
|
||||
createGridPane();
|
||||
addHeadLine();
|
||||
addContent();
|
||||
addButtons();
|
||||
|
||||
regexValidator = new RegexValidator();
|
||||
regexValidator.setPattern("[a-fA-F0-9]{64}|^$");
|
||||
regexValidator.setErrorMessage(Res.get("portfolio.pending.step2_buyer.confirmStart.proof.invalidInput"));
|
||||
txHashInputTextField.setValidator(regexValidator);
|
||||
txKeyInputTextField.setValidator(regexValidator);
|
||||
if (isDevMode()) {
|
||||
// pre-populate the fields with test data when in dev mode
|
||||
txHashInputTextField.setText(XmrTxProofModel.DEV_TX_HASH);
|
||||
txKeyInputTextField.setText(XmrTxProofModel.DEV_TX_KEY);
|
||||
}
|
||||
|
||||
actionButton.disableProperty().bind(createBooleanBinding(() -> {
|
||||
String txHash = txHashInputTextField.getText();
|
||||
String txKey = txKeyInputTextField.getText();
|
||||
|
||||
// If a field is empty we allow to continue. We do not enforce that users send the data.
|
||||
if (txHash.isEmpty() || txKey.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise we require that input is valid
|
||||
return !txHashInputTextField.getValidator().validate(txHash).isValid ||
|
||||
!txKeyInputTextField.getValidator().validate(txKey).isValid;
|
||||
},
|
||||
txHashInputTextField.textProperty(), txKeyInputTextField.textProperty()));
|
||||
|
||||
applyStyles();
|
||||
display();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createGridPane() {
|
||||
gridPane = new GridPane();
|
||||
gridPane.setHgap(5);
|
||||
gridPane.setVgap(5);
|
||||
gridPane.setPadding(new Insets(64, 64, 64, 64));
|
||||
gridPane.setPrefWidth(width);
|
||||
|
||||
ColumnConstraints columnConstraints1 = new ColumnConstraints();
|
||||
columnConstraints1.setHalignment(HPos.RIGHT);
|
||||
columnConstraints1.setHgrow(Priority.SOMETIMES);
|
||||
gridPane.getColumnConstraints().addAll(columnConstraints1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTxHash() {
|
||||
return txHashInputTextField != null ? txHashInputTextField.getText() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTxKey() {
|
||||
return txKeyInputTextField != null ? txKeyInputTextField.getText() : null;
|
||||
}
|
||||
|
||||
private void addContent() {
|
||||
addMultilineLabel(gridPane, ++rowIndex, Res.get("setXMRTxKeyWindow.note"), 0);
|
||||
txHashInputTextField = addInputTextField(gridPane, ++rowIndex, Res.get("setXMRTxKeyWindow.txHash"), 10);
|
||||
txKeyInputTextField = addInputTextField(gridPane, ++rowIndex, Res.get("setXMRTxKeyWindow.txKey"));
|
||||
}
|
||||
}
|
|
@ -29,7 +29,6 @@ import haveno.core.trade.Contract;
|
|||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.TradeManager;
|
||||
import haveno.core.trade.txproof.AssetTxProofResult;
|
||||
import haveno.core.util.FormattingUtils;
|
||||
import haveno.core.util.VolumeUtil;
|
||||
import haveno.core.util.coin.CoinFormatter;
|
||||
|
@ -38,7 +37,6 @@ import haveno.desktop.components.HavenoTextArea;
|
|||
import haveno.desktop.main.MainView;
|
||||
import haveno.desktop.main.overlays.Overlay;
|
||||
import haveno.desktop.util.DisplayUtils;
|
||||
import haveno.desktop.util.GUIUtil;
|
||||
import haveno.desktop.util.Layout;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
|
@ -64,7 +62,6 @@ import org.slf4j.LoggerFactory;
|
|||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static haveno.desktop.util.DisplayUtils.getAccountWitnessDescription;
|
||||
import static haveno.desktop.util.FormBuilder.add2ButtonsWithBox;
|
||||
import static haveno.desktop.util.FormBuilder.addConfirmationLabelTextArea;
|
||||
|
@ -188,10 +185,6 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
|||
rows++;
|
||||
}
|
||||
|
||||
boolean showXmrProofResult = checkNotNull(trade.getOffer()).getCurrencyCode().equals("XMR") &&
|
||||
trade.getAssetTxProofResult() != null &&
|
||||
trade.getAssetTxProofResult() != AssetTxProofResult.UNDEFINED;
|
||||
|
||||
if (trade.getPayoutTxId() != null)
|
||||
rows++;
|
||||
boolean showDisputedTx = arbitrationManager.findOwnDispute(trade.getId()).isPresent() &&
|
||||
|
@ -202,8 +195,6 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
|||
rows += 2;
|
||||
if (trade.getTradePeerNodeAddress() != null)
|
||||
rows++;
|
||||
if (showXmrProofResult)
|
||||
rows++;
|
||||
|
||||
addTitledGroupBg(gridPane, ++rowIndex, rows, Res.get("shared.details"), Layout.GROUP_DISTANCE);
|
||||
addConfirmationLabelTextField(gridPane, rowIndex, Res.get("shared.tradeId"),
|
||||
|
@ -230,14 +221,6 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
|||
addConfirmationLabelTextField(gridPane, ++rowIndex, Res.get("tradeDetailsWindow.tradePeersOnion"),
|
||||
trade.getTradePeerNodeAddress().getFullAddress());
|
||||
|
||||
if (showXmrProofResult) {
|
||||
// As the window is already overloaded we replace the tradePeersPubKeyHash field with the auto-conf state
|
||||
// if XMR is the currency
|
||||
addConfirmationLabelTextField(gridPane, ++rowIndex,
|
||||
Res.get("portfolio.pending.step3_seller.autoConf.status.label"),
|
||||
GUIUtil.getProofResultAsString(trade.getAssetTxProofResult()));
|
||||
}
|
||||
|
||||
if (contract != null) {
|
||||
buyersAccountAge = getAccountWitnessDescription(accountAgeWitnessService, offer.getPaymentMethod(), buyerPaymentAccountPayload, contract.getBuyerPubKeyRing());
|
||||
sellersAccountAge = getAccountWitnessDescription(accountAgeWitnessService, offer.getPaymentMethod(), sellerPaymentAccountPayload, contract.getSellerPubKeyRing());
|
||||
|
|
|
@ -96,11 +96,9 @@ import haveno.desktop.components.paymentmethods.VerseForm;
|
|||
import haveno.desktop.components.paymentmethods.WeChatPayForm;
|
||||
import haveno.desktop.components.paymentmethods.WesternUnionForm;
|
||||
import haveno.desktop.main.overlays.popups.Popup;
|
||||
import haveno.desktop.main.overlays.windows.SetXmrTxKeyWindow;
|
||||
import haveno.desktop.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import haveno.desktop.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
import haveno.desktop.util.Layout;
|
||||
import haveno.desktop.util.Transitions;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
|
@ -110,7 +108,6 @@ import org.fxmisc.easybind.EasyBind;
|
|||
import org.fxmisc.easybind.Subscription;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static haveno.desktop.util.FormBuilder.addButtonBusyAnimationLabel;
|
||||
|
@ -543,44 +540,11 @@ public class BuyerStep2View extends TradeStepView {
|
|||
} else {
|
||||
showConfirmPaymentSentPopup();
|
||||
}
|
||||
} else if (sellersPaymentAccountPayload instanceof AssetAccountPayload && isXmrTrade()) {
|
||||
SetXmrTxKeyWindow setXmrTxKeyWindow = new SetXmrTxKeyWindow();
|
||||
setXmrTxKeyWindow
|
||||
.actionButtonText(Res.get("portfolio.pending.step2_buyer.confirmStart.headline"))
|
||||
.onAction(() -> {
|
||||
String txKey = setXmrTxKeyWindow.getTxKey();
|
||||
String txHash = setXmrTxKeyWindow.getTxHash();
|
||||
if (txKey == null || txHash == null || txKey.isEmpty() || txHash.isEmpty()) {
|
||||
UserThread.runAfter(this::showProofWarningPopup, Transitions.DEFAULT_DURATION, TimeUnit.MILLISECONDS);
|
||||
return;
|
||||
}
|
||||
|
||||
trade.setCounterCurrencyExtraData(txKey);
|
||||
trade.setCounterCurrencyTxId(txHash);
|
||||
|
||||
model.dataModel.getTradeManager().requestPersistence();
|
||||
showConfirmPaymentSentPopup();
|
||||
})
|
||||
.closeButtonText(Res.get("shared.cancel"))
|
||||
.onClose(setXmrTxKeyWindow::hide)
|
||||
.show();
|
||||
} else {
|
||||
showConfirmPaymentSentPopup();
|
||||
}
|
||||
}
|
||||
|
||||
private void showProofWarningPopup() {
|
||||
Popup popup = new Popup();
|
||||
popup.headLine(Res.get("portfolio.pending.step2_buyer.confirmStart.proof.warningTitle"))
|
||||
.confirmation(Res.get("portfolio.pending.step2_buyer.confirmStart.proof.noneProvided"))
|
||||
.width(700)
|
||||
.actionButtonText(Res.get("portfolio.pending.step2_buyer.confirmStart.warningButton"))
|
||||
.onAction(this::showConfirmPaymentSentPopup)
|
||||
.closeButtonText(Res.get("shared.cancel"))
|
||||
.onClose(popup::hide)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showConfirmPaymentSentPopup() {
|
||||
String key = "confirmPaymentSent";
|
||||
if (!DevEnv.isDevMode() && DontShowAgainLookup.showAgain(key)) {
|
||||
|
|
|
@ -21,7 +21,6 @@ import com.jfoenix.controls.JFXBadge;
|
|||
import haveno.common.UserThread;
|
||||
import haveno.common.app.DevEnv;
|
||||
import haveno.core.locale.Res;
|
||||
import haveno.core.trade.txproof.AssetTxProofResult;
|
||||
import haveno.core.user.DontShowAgainLookup;
|
||||
import haveno.core.xmr.model.XmrAddressEntry;
|
||||
import haveno.desktop.components.AutoTooltipButton;
|
||||
|
@ -88,15 +87,11 @@ public class BuyerStep4View extends TradeStepView {
|
|||
} 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");
|
||||
|
||||
HBox hBox2 = new HBox(1, completedTradeLabel, autoConfBadge);
|
||||
HBox hBox2 = new HBox(1, completedTradeLabel);
|
||||
GridPane.setMargin(hBox2, new Insets(18, -10, -12, -10));
|
||||
gridPane.getChildren().add(hBox2);
|
||||
GridPane.setRowSpan(hBox2, 5);
|
||||
autoConfBadge.setVisible(AssetTxProofResult.COMPLETED == trade.getAssetTxProofResult());
|
||||
|
||||
if (trade.getDisputeState().isNotDisputed()) {
|
||||
addCompactTopLabelTextField(gridPane, gridRow, getBtcTradeAmountLabel(), model.getTradeVolume(), Layout.TWICE_FIRST_ROW_DISTANCE);
|
||||
|
|
|
@ -40,7 +40,6 @@ import haveno.core.payment.payload.USPostalMoneyOrderAccountPayload;
|
|||
import haveno.core.payment.payload.WesternUnionAccountPayload;
|
||||
import haveno.core.trade.Contract;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.txproof.AssetTxProofResult;
|
||||
import haveno.core.user.DontShowAgainLookup;
|
||||
import haveno.core.util.VolumeUtil;
|
||||
import haveno.desktop.components.BusyAnimation;
|
||||
|
@ -50,7 +49,6 @@ import haveno.desktop.components.indicator.TxConfidenceIndicator;
|
|||
import haveno.desktop.main.overlays.popups.Popup;
|
||||
import haveno.desktop.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import haveno.desktop.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
import haveno.desktop.util.GUIUtil;
|
||||
import haveno.desktop.util.Layout;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.geometry.Insets;
|
||||
|
@ -67,7 +65,6 @@ import org.fxmisc.easybind.Subscription;
|
|||
import javax.annotation.Nullable;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static haveno.desktop.util.FormBuilder.addButtonBusyAnimationLabelAfterGroup;
|
||||
import static haveno.desktop.util.FormBuilder.addCompactTopLabelTextFieldWithCopyIcon;
|
||||
import static haveno.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
|
@ -154,15 +151,6 @@ public class SellerStep3View extends TradeStepView {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (isXmrTrade()) {
|
||||
proofResultListener = (observable, oldValue, newValue) -> {
|
||||
applyAssetTxProofResult(trade.getAssetTxProofResult());
|
||||
};
|
||||
trade.getAssetTxProofResultUpdateProperty().addListener(proofResultListener);
|
||||
|
||||
applyAssetTxProofResult(trade.getAssetTxProofResult());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -179,10 +167,6 @@ public class SellerStep3View extends TradeStepView {
|
|||
if (timeoutTimer != null) {
|
||||
timeoutTimer.stop();
|
||||
}
|
||||
|
||||
if (isXmrTrade()) {
|
||||
trade.getAssetTxProofResultUpdateProperty().removeListener(proofResultListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -488,42 +472,6 @@ public class SellerStep3View extends TradeStepView {
|
|||
}
|
||||
}
|
||||
|
||||
private void applyAssetTxProofResult(@Nullable AssetTxProofResult result) {
|
||||
checkNotNull(assetTxProofResultField);
|
||||
checkNotNull(assetTxConfidenceIndicator);
|
||||
|
||||
String txt = GUIUtil.getProofResultAsString(result);
|
||||
assetTxProofResultField.setText(txt);
|
||||
|
||||
if (result == null) {
|
||||
assetTxConfidenceIndicator.setProgress(0);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (result) {
|
||||
case PENDING:
|
||||
case COMPLETED:
|
||||
if (result.getNumRequiredConfirmations() > 0) {
|
||||
int numRequiredConfirmations = result.getNumRequiredConfirmations();
|
||||
int numConfirmations = result.getNumConfirmations();
|
||||
if (numConfirmations == 0) {
|
||||
assetTxConfidenceIndicator.setProgress(-1);
|
||||
} else {
|
||||
double progress = Math.min(1, (double) numConfirmations / (double) numRequiredConfirmations);
|
||||
assetTxConfidenceIndicator.setProgress(progress);
|
||||
assetTxConfidenceIndicator.getTooltip().setText(
|
||||
Res.get("portfolio.pending.autoConf.blocks",
|
||||
numConfirmations, numRequiredConfirmations));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Set invisible by default
|
||||
assetTxConfidenceIndicator.setProgress(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private Label createPopoverLabel(String text) {
|
||||
Label label = new Label(text);
|
||||
label.setPrefWidth(600);
|
||||
|
|
|
@ -49,7 +49,6 @@ import haveno.core.payment.PaymentAccount;
|
|||
import haveno.core.payment.PaymentAccountList;
|
||||
import haveno.core.payment.payload.PaymentMethod;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.trade.txproof.AssetTxProofResult;
|
||||
import haveno.core.user.DontShowAgainLookup;
|
||||
import haveno.core.user.Preferences;
|
||||
import haveno.core.user.User;
|
||||
|
@ -104,7 +103,6 @@ import org.bitcoinj.core.Coin;
|
|||
import org.bitcoinj.uri.BitcoinURI;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -1018,35 +1016,6 @@ public class GUIUtil {
|
|||
MaterialDesignIcon.APPROVAL : MaterialDesignIcon.ALERT_CIRCLE_OUTLINE;
|
||||
}
|
||||
|
||||
public static String getProofResultAsString(@Nullable AssetTxProofResult result) {
|
||||
if (result == null) {
|
||||
return "";
|
||||
}
|
||||
String key = "portfolio.pending.autoConf.state." + result.name();
|
||||
switch (result) {
|
||||
case UNDEFINED:
|
||||
return "";
|
||||
case FEATURE_DISABLED:
|
||||
return Res.get(key, result.getDetails());
|
||||
case TRADE_LIMIT_EXCEEDED:
|
||||
return Res.get(key);
|
||||
case INVALID_DATA:
|
||||
return Res.get(key, result.getDetails());
|
||||
case PAYOUT_TX_ALREADY_PUBLISHED:
|
||||
case DISPUTE_OPENED:
|
||||
case REQUESTS_STARTED:
|
||||
return Res.get(key);
|
||||
case PENDING:
|
||||
return Res.get(key, result.getNumSuccessResults(), result.getNumRequiredSuccessResults(), result.getDetails());
|
||||
case COMPLETED:
|
||||
case ERROR:
|
||||
case FAILED:
|
||||
return Res.get(key);
|
||||
default:
|
||||
return result.name();
|
||||
}
|
||||
}
|
||||
|
||||
public static ScrollPane createScrollPane() {
|
||||
ScrollPane scrollPane = new ScrollPane();
|
||||
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue