/* * This file is part of Bitsquare. * * Bitsquare 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. * * Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>. */ package io.bitsquare.gui.main.overlays.windows; import io.bitsquare.app.DevFlags; import io.bitsquare.btc.Restrictions; import io.bitsquare.btc.WalletService; import io.bitsquare.common.UserThread; import io.bitsquare.common.util.Tuple2; import io.bitsquare.gui.components.InputTextField; import io.bitsquare.gui.main.overlays.Overlay; import io.bitsquare.gui.main.overlays.popups.Popup; import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.Transitions; import io.bitsquare.trade.offer.OpenOfferManager; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.crypto.params.KeyParameter; import javax.inject.Inject; import java.util.concurrent.TimeUnit; import static io.bitsquare.gui.util.FormBuilder.*; public class EmptyWalletWindow extends Overlay<EmptyWalletWindow> { private static final Logger log = LoggerFactory.getLogger(EmptyWalletWindow.class); private final WalletService walletService; private final WalletPasswordWindow walletPasswordWindow; private OpenOfferManager openOfferManager; private final BSFormatter formatter; private Button emptyWalletButton; private InputTextField addressInputTextField; private TextField balanceTextField; /////////////////////////////////////////////////////////////////////////////////////////// // Public API /////////////////////////////////////////////////////////////////////////////////////////// @Inject public EmptyWalletWindow(WalletService walletService, WalletPasswordWindow walletPasswordWindow, OpenOfferManager openOfferManager, BSFormatter formatter) { this.walletService = walletService; this.walletPasswordWindow = walletPasswordWindow; this.openOfferManager = openOfferManager; this.formatter = formatter; type = Type.Instruction; } public void show() { if (headLine == null) headLine = "Empty wallet"; width = 700; createGridPane(); addHeadLine(); addSeparator(); addContent(); applyStyles(); display(); } /////////////////////////////////////////////////////////////////////////////////////////// // Protected /////////////////////////////////////////////////////////////////////////////////////////// @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, "Please use that only in emergency case if you cannot access your fund from the UI.\n\n" + "Please note that all open offers will be closed automatically when using this tool.\n\n" + "Before you use this tool, please backup your data directory. " + "You can do this under \"Account/Backup\".\n\n" + "Please file a bug report on Github so that we can investigate what was causing the problem.", 10); Coin totalBalance = walletService.getAvailableBalance(); balanceTextField = addLabelTextField(gridPane, ++rowIndex, "Your available wallet balance:", formatter.formatCoinWithCode(totalBalance), 10).second; Tuple2<Label, InputTextField> tuple = addLabelInputTextField(gridPane, ++rowIndex, "Your destination address:"); addressInputTextField = tuple.second; if (DevFlags.DEV_MODE) addressInputTextField.setText("mjYhQYSbET2bXJDyCdNqYhqSye5QX2WHPz"); emptyWalletButton = new Button("Empty wallet"); boolean isBalanceSufficient = Restrictions.isAboveDust(totalBalance); emptyWalletButton.setDefaultButton(isBalanceSufficient); emptyWalletButton.setDisable(!isBalanceSufficient && addressInputTextField.getText().length() > 0); emptyWalletButton.setOnAction(e -> { if (addressInputTextField.getText().length() > 0 && isBalanceSufficient) { if (walletService.getWallet().isEncrypted()) { walletPasswordWindow .onAesKey(this::doEmptyWallet) .onClose(this::blurAgain) .show(); } else { doEmptyWallet(null); } } }); closeButton = new Button("Cancel"); closeButton.setOnAction(e -> { hide(); closeHandlerOptional.ifPresent(Runnable::run); }); closeButton.setDefaultButton(!isBalanceSufficient); HBox hBox = new HBox(); hBox.setSpacing(10); GridPane.setRowIndex(hBox, ++rowIndex); GridPane.setColumnIndex(hBox, 1); hBox.getChildren().addAll(emptyWalletButton, closeButton); gridPane.getChildren().add(hBox); GridPane.setMargin(hBox, new Insets(10, 0, 0, 0)); } private void doEmptyWallet(KeyParameter aesKey) { if (!openOfferManager.getOpenOffers().isEmpty()) { UserThread.runAfter(() -> new Popup().warning("You have open offers which will be removed if you empty the wallet.\n" + "Are you sure that you want to empty your wallet?") .actionButtonText("Yes, I am sure") .onAction(() -> { doEmptyWallet2(aesKey); }) .show(), 300, TimeUnit.MILLISECONDS); } else { doEmptyWallet2(aesKey); } } private void doEmptyWallet2(KeyParameter aesKey) { emptyWalletButton.setDisable(true); openOfferManager.removeAllOpenOffers(() -> { try { walletService.emptyWallet(addressInputTextField.getText(), aesKey, () -> { closeButton.setText("Close"); balanceTextField.setText(formatter.formatCoinWithCode(walletService.getAvailableBalance())); emptyWalletButton.setDisable(true); log.debug("wallet empty successful"); onClose(() -> UserThread.runAfter(() -> new Popup() .feedback("The balance of your wallet was successfully transferred.") .show(), Transitions.DEFAULT_DURATION, TimeUnit.MILLISECONDS)); doClose(); }, (errorMessage) -> { emptyWalletButton.setDisable(false); log.debug("wallet empty failed " + errorMessage); }); } catch (InsufficientMoneyException | AddressFormatException e1) { e1.printStackTrace(); log.error(e1.getMessage()); emptyWalletButton.setDisable(false); } }); } }