diff --git a/application/src/main/java/bisq/application/ApplicationService.java b/application/src/main/java/bisq/application/ApplicationService.java index 432b80642b..e30a648460 100644 --- a/application/src/main/java/bisq/application/ApplicationService.java +++ b/application/src/main/java/bisq/application/ApplicationService.java @@ -63,7 +63,6 @@ private static Config from(com.typesafe.config.Config config, String[] args) { } boolean devMode = config.getBoolean("devMode"); - boolean isWalletEnabled = config.getBoolean("wallet.enabled"); String dataDir = null; for (String arg : args) { @@ -81,25 +80,22 @@ private static Config from(com.typesafe.config.Config config, String[] args) { String version = config.getString("version"); - return new Config(appDir, appName, version, devMode, isWalletEnabled); + return new Config(appDir, appName, version, devMode); } private final String baseDir; private final String appName; private final String version; private final boolean devMode; - private final boolean isWalletEnabled; public Config(String baseDir, String appName, String version, - boolean devMode, - boolean isWalletEnabled) { + boolean devMode) { this.baseDir = baseDir; this.appName = appName; this.version = version; this.devMode = devMode; - this.isWalletEnabled = isWalletEnabled; } } diff --git a/application/src/main/java/bisq/application/DefaultApplicationService.java b/application/src/main/java/bisq/application/DefaultApplicationService.java index a69d461492..291daf3958 100644 --- a/application/src/main/java/bisq/application/DefaultApplicationService.java +++ b/application/src/main/java/bisq/application/DefaultApplicationService.java @@ -66,7 +66,7 @@ public enum State { } private final SecurityService securityService; - private final ElectrumWalletService walletService; + private final ElectrumWalletService electrumWalletService; private final NetworkService networkService; private final IdentityService identityService; private final OracleService oracleService; @@ -83,7 +83,8 @@ public enum State { public DefaultApplicationService(String[] args) { super("default", args); securityService = new SecurityService(persistenceService); - walletService = new ElectrumWalletService(config.isWalletEnabled(), Path.of(config.getBaseDir())); + electrumWalletService = new ElectrumWalletService(ElectrumWalletService.Config.from(getConfig("electrumWallet")), + Path.of(config.getBaseDir())); networkService = new NetworkService(NetworkServiceConfig.from(config.getBaseDir(), getConfig("network")), persistenceService, @@ -128,7 +129,7 @@ public CompletableFuture initialize() { setState(State.INITIALIZE_NETWORK); CompletableFuture networkFuture = networkService.initialize(); - CompletableFuture walletFuture = walletService.initialize(); + CompletableFuture walletFuture = electrumWalletService.initialize(); networkFuture.whenComplete((r, throwable) -> { if (throwable != null) { @@ -188,7 +189,7 @@ public CompletableFuture shutdown() { .thenCompose(result -> oracleService.shutdown()) .thenCompose(result -> identityService.shutdown()) .thenCompose(result -> networkService.shutdown()) - .thenCompose(result -> walletService.shutdown()) + .thenCompose(result -> electrumWalletService.shutdown()) .thenCompose(result -> securityService.shutdown()) .orTimeout(10, TimeUnit.SECONDS) .handle((result, throwable) -> throwable == null) diff --git a/application/src/main/resources/default.conf b/application/src/main/resources/default.conf index 5262f2d4c2..cc60eec796 100644 --- a/application/src/main/resources/default.conf +++ b/application/src/main/resources/default.conf @@ -122,7 +122,7 @@ application { } } - wallet = { + electrumWallet = { enabled = true } } \ No newline at end of file diff --git a/common/src/main/java/bisq/common/monetary/Coin.java b/common/src/main/java/bisq/common/monetary/Coin.java index 739a5ae51a..82f55191ab 100644 --- a/common/src/main/java/bisq/common/monetary/Coin.java +++ b/common/src/main/java/bisq/common/monetary/Coin.java @@ -110,7 +110,7 @@ public static Coin of(long value, String code, int precision) { } private Coin(double value, String code, int precision) { - super(code + " [crypto]", value, code, precision, precision); + super(code + " [crypto]", value, code, precision, code.equals("BSQ") ? 2 : 4); } private Coin(String id, long value, String code, int precision, int minPrecision) { diff --git a/desktop/src/main/java/bisq/desktop/common/view/NavigationTarget.java b/desktop/src/main/java/bisq/desktop/common/view/NavigationTarget.java index e9addddbe9..7ce3ccf8cc 100644 --- a/desktop/src/main/java/bisq/desktop/common/view/NavigationTarget.java +++ b/desktop/src/main/java/bisq/desktop/common/view/NavigationTarget.java @@ -144,7 +144,12 @@ public enum NavigationTarget { REGISTER_MODERATOR(ROLES_TABS, false), REGISTER_ORACLE(ROLES_TABS, false), - WALLET(CONTENT); + WALLET(CONTENT), + WALLET_DASHBOARD(WALLET), + WALLET_SEND(WALLET), + WALLET_RECEIVE(WALLET), + WALLET_TXS(WALLET), + WALLET_SETTINGS(WALLET); @Getter private final Optional parent; diff --git a/desktop/src/main/java/bisq/desktop/components/controls/MaterialPasswordField.java b/desktop/src/main/java/bisq/desktop/components/controls/MaterialPasswordField.java new file mode 100644 index 0000000000..71377551e6 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/components/controls/MaterialPasswordField.java @@ -0,0 +1,87 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.components.controls; + +import bisq.desktop.common.threading.UIThread; +import de.jensd.fx.fontawesome.AwesomeIcon; +import javafx.scene.control.PasswordField; +import javafx.scene.control.TextInputControl; +import javafx.scene.control.skin.TextFieldSkin; + +import javax.annotation.Nullable; + +public class MaterialPasswordField extends MaterialTextField { + public MaterialPasswordField() { + this(null, null, null); + } + + public MaterialPasswordField(String description) { + this(description, null, null); + } + + public MaterialPasswordField(String description, String prompt) { + this(description, prompt, null); + } + + public MaterialPasswordField(@Nullable String description, @Nullable String prompt, @Nullable String help) { + super(description, prompt, help); + } + + @Override + protected TextInputControl createTextInputControl() { + PasswordField passwordField = new PasswordField(); + passwordField.setSkin(new VisiblePasswordFieldSkin(passwordField, this)); + + return passwordField; + } + + static class VisiblePasswordFieldSkin extends TextFieldSkin { + private boolean isMasked = true; + + public VisiblePasswordFieldSkin(PasswordField textField, MaterialPasswordField materialPasswordField) { + super(textField); + + // iconButton is not created when we get called, so we delay it to next render frame + UIThread.runOnNextRenderFrame(() -> { + BisqIconButton iconButton = materialPasswordField.getIconButton(); + materialPasswordField.setIcon(AwesomeIcon.EYE_OPEN); + iconButton.setOnAction(e -> { + iconButton.setIcon(isMasked ? AwesomeIcon.EYE_CLOSE : AwesomeIcon.EYE_OPEN); + isMasked = !isMasked; + + // TODO if binding is used we don't get the text updated. With bi-dir binding it works + textField.setText(textField.getText()); + textField.end(); + /* if(!textField.textProperty().isBound()){ + textField.setText(textField.getText()); + textField.end(); + }*/ + }); + }); + } + + @Override + protected String maskText(String txt) { + if (getSkinnable() instanceof PasswordField && isMasked) { + return "•".repeat(txt.length()); + } else { + return txt; + } + } + } +} \ No newline at end of file diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/ContentController.java b/desktop/src/main/java/bisq/desktop/primary/main/content/ContentController.java index effcc1a9ff..0a4c327dcf 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/ContentController.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/ContentController.java @@ -36,10 +36,8 @@ import bisq.desktop.primary.main.content.trade.TradeController; import bisq.desktop.primary.main.content.trade.bisqEasy.BisqEasyController; import bisq.desktop.primary.main.content.trade.bsqSwap.BsqSwapController; -import bisq.desktop.primary.main.content.trade.lightning.LightningController; import bisq.desktop.primary.main.content.trade.liquidSwap.LiquidSwapController; import bisq.desktop.primary.main.content.trade.multiSig.MultiSigController; -import bisq.desktop.primary.main.content.trade.xmrSwap.XmrSwapController; import bisq.desktop.primary.main.content.wallet.WalletController; import lombok.Getter; import lombok.extern.slf4j.Slf4j; diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/components/ChatMessagesListView.java b/desktop/src/main/java/bisq/desktop/primary/main/content/components/ChatMessagesListView.java index cca5b5a078..184fe81b3e 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/components/ChatMessagesListView.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/components/ChatMessagesListView.java @@ -81,6 +81,7 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import java.text.DateFormat; import java.util.*; import java.util.function.Consumer; import java.util.function.Predicate; @@ -1026,7 +1027,7 @@ public ChatMessageListItem(T chatMessage, UserProfileService userProfileService, String editPostFix = chatMessage.isWasEdited() ? EDITED_POST_FIX : ""; message = chatMessage.getText() + editPostFix; quotedMessage = chatMessage.getQuotation(); - date = DateFormatter.formatDateTimeV2(new Date(chatMessage.getDate())); + date = DateFormatter.formatDateTime(new Date(chatMessage.getDate()), DateFormat.MEDIUM, DateFormat.SHORT, true, " " + Res.get("at") + " "); nym = senderUserProfile.map(UserProfile::getNym).orElse(""); nickName = senderUserProfile.map(UserProfile::getNickName).orElse(""); diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationController.java b/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationController.java index 05fbc6f756..de01ce7762 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationController.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationController.java @@ -88,8 +88,6 @@ public void onActivate() { } updateRegistrationState(); - - model.getPrivateKeyDisplay().set("•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••"); }); } @@ -148,8 +146,4 @@ void onRemoveRegistration() { void onCopy() { ClipboardUtil.copyToClipboard(model.getPublicKey().get()); } - - void onShowPrivateKey() { - model.getPrivateKeyDisplay().set(model.getPrivateKey().get()); - } } diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationModel.java b/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationModel.java index e6cbab901f..04bdb309e2 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationModel.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationModel.java @@ -36,7 +36,6 @@ public class RoleRegistrationModel implements Model { private final StringProperty selectedProfileUserName = new SimpleStringProperty(); private final StringProperty privateKey = new SimpleStringProperty(); private final StringProperty publicKey = new SimpleStringProperty(); - private final StringProperty privateKeyDisplay = new SimpleStringProperty(); private final BooleanProperty registrationDisabled = new SimpleBooleanProperty(); private final BooleanProperty removeRegistrationVisible = new SimpleBooleanProperty(); private final RoleType roleType; diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationView.java b/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationView.java index 8a66f812e9..d85d0d9798 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationView.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/settings/roles/registration/RoleRegistrationView.java @@ -19,11 +19,10 @@ import bisq.desktop.common.view.View; import bisq.desktop.components.containers.Spacer; -import bisq.desktop.components.controls.BisqIconButton; +import bisq.desktop.components.controls.MaterialPasswordField; import bisq.desktop.components.controls.MaterialTextField; import bisq.desktop.components.controls.MultiLineLabel; import bisq.i18n.Res; -import de.jensd.fx.fontawesome.AwesomeIcon; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.Button; @@ -38,8 +37,9 @@ public class RoleRegistrationView extends View controller.onRemoveRegistration()); learnMore.setOnAction(e -> controller.onLearnMore()); copyButton.setOnAction(e -> controller.onCopy()); - showPrivateKeyIcon.setOnAction(e -> { - controller.onShowPrivateKey(); - showPrivateKeyIcon.setVisible(false); - }); - showPrivateKeyIcon.setVisible(true); } @Override protected void onViewDetached() { selectedProfile.textProperty().unbind(); - privateKey.textProperty().unbind(); - publicKey.textProperty().unbind(); + privateKey.textProperty().unbindBidirectional(model.getPrivateKey()); + publicKey.textProperty().unbindBidirectional(model.getPublicKey()); registrationButton.disableProperty().unbind(); removeRegistrationButton.managedProperty().unbind(); removeRegistrationButton.visibleProperty().unbind(); @@ -111,6 +104,5 @@ protected void onViewDetached() { removeRegistrationButton.setOnAction(null); learnMore.setOnAction(null); copyButton.setOnAction(null); - showPrivateKeyIcon.setOnAction(null); } } diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/settings/userProfile/UserProfileView.java b/desktop/src/main/java/bisq/desktop/primary/main/content/settings/userProfile/UserProfileView.java index a728985f6e..524bc78469 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/settings/userProfile/UserProfileView.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/settings/userProfile/UserProfileView.java @@ -52,9 +52,8 @@ public class UserProfileView extends View. - */ - -package bisq.desktop.primary.main.content.wallet; - -import bisq.common.monetary.Coin; -import bisq.common.observable.Pin; -import bisq.desktop.common.observable.FxBindings; -import bisq.i18n.Res; -import bisq.presentation.formatters.AmountFormatter; -import bisq.wallets.bitcoind.BitcoinWalletService; -import javafx.beans.binding.Bindings; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.value.ObservableValue; -import javafx.geometry.Insets; -import javafx.scene.control.Label; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Pane; -import lombok.Getter; - -public class WalletBalanceComponent { - private final Controller controller; - - public WalletBalanceComponent(BitcoinWalletService bitcoinWalletService) { - controller = new Controller(bitcoinWalletService); - } - - public Pane getRootPane() { - return controller.getView().getRoot(); - } - - private static class Controller implements bisq.desktop.common.view.Controller { - private final Model model; - @Getter - private final View view; - private final BitcoinWalletService bitcoinWalletService; - private Pin balancePin; - - private Controller(BitcoinWalletService bitcoinWalletService) { - this.bitcoinWalletService = bitcoinWalletService; - model = new Model(); - view = new View(model, this); - } - - @Override - public void onActivate() { - balancePin = FxBindings.bind(model.balanceAsCoinProperty).to(bitcoinWalletService.getObservableBalanceAsCoin()); - } - - @Override - public void onDeactivate() { - balancePin.unbind(); - } - } - - private static class Model implements bisq.desktop.common.view.Model { - private final ObjectProperty balanceAsCoinProperty = new SimpleObjectProperty<>(Coin.of(0, "BTC")); - private final ObservableValue formattedBalanceProperty = Bindings.createStringBinding( - () -> AmountFormatter.formatAmountWithCode(balanceAsCoinProperty.get()), - balanceAsCoinProperty); - } - - public static class View extends bisq.desktop.common.view.View { - private final Label balance; - - private View(Model model, Controller controller) { - super(new HBox(), model, controller); - - // root.setAlignment(Pos.BASELINE_CENTER); - root.setSpacing(8); - - Label label = new Label(Res.get("wallet.availableBalance").toUpperCase()); - label.setStyle("-fx-text-fill: -bisq-grey-dimmed; -fx-font-family: \"IBM Plex Sans Light\"; -fx-font-size: 0.8em"); - label.setPadding(new Insets(3, 0, 0, 0)); - - balance = new Label(); - balance.setStyle("-fx-text-fill: -fx-light-text-color; -fx-font-family: \"IBM Plex Sans Light\"; -fx-font-size: 1.05em"); - - root.getChildren().addAll(label, balance); - } - - @Override - protected void onViewAttached() { - balance.textProperty().bind(model.formattedBalanceProperty); - } - - @Override - protected void onViewDetached() { - balance.textProperty().unbind(); - } - } -} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletController.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletController.java index a73ea9048e..3f001ec998 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletController.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletController.java @@ -18,47 +18,61 @@ package bisq.desktop.primary.main.content.wallet; import bisq.application.DefaultApplicationService; -import bisq.common.observable.Pin; -import bisq.desktop.common.observable.FxBindings; -import bisq.desktop.common.threading.UIThread; import bisq.desktop.common.view.Controller; -import bisq.wallets.electrum.ElectrumWalletService; +import bisq.desktop.common.view.NavigationTarget; +import bisq.desktop.common.view.TabController; +import bisq.desktop.primary.main.content.wallet.dashboard.WalletDashboardController; +import bisq.desktop.primary.main.content.wallet.receive.WalletReceiveController; +import bisq.desktop.primary.main.content.wallet.send.WalletSendController; +import bisq.desktop.primary.main.content.wallet.settings.WalletSettingsController; +import bisq.desktop.primary.main.content.wallet.txs.WalletTxsController; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; -public class WalletController implements Controller { - private final ElectrumWalletService walletService; - private final WalletModel model = new WalletModel(); - @Getter - private final WalletView view = new WalletView(model, this); - private final WalletWithdrawFundsPopup walletWithdrawFundsPopup; +import java.util.Optional; - private Pin balancePin; +@Slf4j +public class WalletController extends TabController { + private final DefaultApplicationService applicationService; + @Getter + private final WalletView view; public WalletController(DefaultApplicationService applicationService) { - walletService = applicationService.getWalletService(); - walletWithdrawFundsPopup = new WalletWithdrawFundsPopup(walletService); + super(new WalletModel(), NavigationTarget.WALLET); + + this.applicationService = applicationService; + + view = new WalletView(model, this); } @Override public void onActivate() { - balancePin = FxBindings.bind(model.getBalanceAsCoinProperty()) - .to(walletService.getObservableBalanceAsCoin()); - - walletService.listTransactions() - .thenAccept(txs -> UIThread.run(() -> model.addTransactions(txs))); - - walletService.getNewAddress(). - thenAccept(receiveAddress -> - UIThread.run(() -> model.getReceiveAddressProperty().setValue(receiveAddress)) - ); } @Override public void onDeactivate() { - balancePin.unbind(); } - public void onWithdrawButtonClicked() { - walletWithdrawFundsPopup.show(); + protected Optional createController(NavigationTarget navigationTarget) { + switch (navigationTarget) { + case WALLET_DASHBOARD: { + return Optional.of(new WalletDashboardController(applicationService)); + } + case WALLET_SEND: { + return Optional.of(new WalletSendController(applicationService)); + } + case WALLET_RECEIVE: { + return Optional.of(new WalletReceiveController(applicationService)); + } + case WALLET_TXS: { + return Optional.of(new WalletTxsController(applicationService)); + } + case WALLET_SETTINGS: { + return Optional.of(new WalletSettingsController(applicationService)); + } + default: { + return Optional.empty(); + } + } } } diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletModel.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletModel.java index 7514bea94c..da5e0daffd 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletModel.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletModel.java @@ -17,48 +17,16 @@ package bisq.desktop.primary.main.content.wallet; -import bisq.common.monetary.Coin; -import bisq.desktop.common.view.Model; -import bisq.presentation.formatters.AmountFormatter; -import bisq.wallets.core.model.Transaction; -import javafx.beans.binding.Bindings; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; -import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; +import bisq.desktop.common.view.NavigationTarget; +import bisq.desktop.common.view.TabModel; -import java.util.List; - -@Slf4j -@Getter -public class WalletModel implements Model { - - private final ObjectProperty balanceAsCoinProperty = new SimpleObjectProperty<>(Coin.of(0, "BTC")); - private final ObservableValue formattedBalanceProperty = Bindings.createStringBinding( - () -> AmountFormatter.formatAmount(balanceAsCoinProperty.get()), - balanceAsCoinProperty - ); - - @Getter - private final ObservableList transactionHistoryList = FXCollections.observableArrayList(); - - private final StringProperty receiveAddressProperty = new SimpleStringProperty(this, "receiveAddress"); +public class WalletModel extends TabModel { public WalletModel() { } - public void addTransactions(List transactions) { - transactions.stream() - .map(WalletTransactionListItem::new) - .forEach(transactionHistoryList::add); - } - - public String getReceiveAddress() { - return receiveAddressProperty.get(); + @Override + public NavigationTarget getDefaultNavigationTarget() { + return NavigationTarget.WALLET_DASHBOARD; } } diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletView.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletView.java index 74a77a0d1f..a71eec16ec 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletView.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletView.java @@ -17,116 +17,29 @@ package bisq.desktop.primary.main.content.wallet; -import bisq.common.data.Triple; -import bisq.desktop.common.utils.ClipboardUtil; -import bisq.desktop.common.view.View; -import bisq.desktop.components.table.BisqTableColumn; -import bisq.desktop.components.table.BisqTableView; +import bisq.desktop.common.view.NavigationTarget; +import bisq.desktop.common.view.TabView; import bisq.i18n.Res; -import javafx.collections.transformation.SortedList; -import javafx.geometry.Pos; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.TextField; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Pane; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; -import lombok.extern.slf4j.Slf4j; -@Slf4j -public class WalletView extends View { - - private final Label balanceLabel; - private final BisqTableView tableView; - private final TextField receiveAddressTextField = new TextField(); +public class WalletView extends TabView { public WalletView(WalletModel model, WalletController controller) { - super(new VBox(20), model, controller); - - Triple balanceTriple = createBalanceBox(Res.get("wallet.balance")); - VBox balanceBox = balanceTriple.getFirst(); - balanceLabel = balanceTriple.getSecond(); - - HBox topHBox = new HBox(100); - Pane receiveAddressBox = createReceiveAddressBox(); - topHBox.getChildren().addAll(balanceBox, receiveAddressBox); - - Button withdrawButton = new Button(Res.get("wallet.withdrawFromWallet")); - withdrawButton.setOnMouseClicked(event -> controller.onWithdrawButtonClicked()); - - Label tableHeader = new Label(Res.get("wallet.transaction.history")); - tableHeader.getStyleClass().add("bisq-text-headline-2"); + super(model, controller); - tableView = new BisqTableView<>(new SortedList<>(model.getTransactionHistoryList())); - VBox.setVgrow(tableView, Priority.ALWAYS); - addColumns(); + addTab(Res.get("wallet.dashboard"), NavigationTarget.WALLET_DASHBOARD); + addTab(Res.get("wallet.send"), NavigationTarget.WALLET_SEND); + addTab(Res.get("wallet.receive"), NavigationTarget.WALLET_RECEIVE); + addTab(Res.get("wallet.txs"), NavigationTarget.WALLET_TXS); + addTab(Res.get("wallet.settings"), NavigationTarget.WALLET_SETTINGS); - root.getChildren().addAll(topHBox, withdrawButton, tableHeader, tableView); + headLine.setText(Res.get("wallet")); } @Override protected void onViewAttached() { - balanceLabel.textProperty().bind(model.getFormattedBalanceProperty()); - receiveAddressTextField.textProperty().bind(model.getReceiveAddressProperty()); } @Override protected void onViewDetached() { - balanceLabel.textProperty().unbind(); - receiveAddressTextField.textProperty().unbind(); - } - - private Triple createBalanceBox(String title) { - Label titleLabel = new Label(title); - titleLabel.getStyleClass().addAll("bisq-text-7", "bisq-text-grey-9"); - - Label valueLabel = new Label(); - valueLabel.getStyleClass().add("bisq-text-headline-3"); - - Label codeLabel = new Label(Res.get("wallet.btc")); - codeLabel.getStyleClass().addAll("bisq-text-12"); - - HBox hBox = new HBox(9, valueLabel, codeLabel); - hBox.setAlignment(Pos.BASELINE_RIGHT); - VBox box = new VBox(titleLabel, hBox); - box.setAlignment(Pos.TOP_CENTER); - HBox.setHgrow(box, Priority.ALWAYS); - return new Triple<>(box, valueLabel, codeLabel); - } - - private Pane createReceiveAddressBox() { - VBox rootVBox = new VBox(); - Label receiveAddressLabel = new Label(Res.get("wallet.receive.address")); - - receiveAddressTextField.setEditable(false); - receiveAddressTextField.setMinWidth(311); - - Button receiveAddressCopyButton = new Button(Res.get("wallet.receive.copy")); - receiveAddressCopyButton.setOnMouseClicked(event -> ClipboardUtil.copyToClipboard(model.getReceiveAddress())); - - HBox receiveAddressHBox = new HBox(receiveAddressTextField, receiveAddressCopyButton); - receiveAddressHBox.setAlignment(Pos.CENTER_LEFT); - - rootVBox.getChildren().addAll(receiveAddressLabel, receiveAddressHBox); - return rootVBox; - } - - private void addColumns() { - tableView.getColumns().add(new BisqTableColumn.Builder() - .title(Res.get("wallet.transaction.history.description")) - .minWidth(150) - .valuePropertySupplier(WalletTransactionListItem::descriptionProperty) - .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() - .title(Res.get("amount")) - .minWidth(120) - .valuePropertySupplier(WalletTransactionListItem::amountProperty) - .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() - .title(Res.get("wallet.column.confirmations")) - .minWidth(80) - .valuePropertySupplier(WalletTransactionListItem::confirmationsProperty) - .build()); } } diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletWithdrawFundsPopup.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletWithdrawFundsPopup.java deleted file mode 100644 index 4ba980e338..0000000000 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletWithdrawFundsPopup.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq 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. - * - * Bisq 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 Bisq. If not, see . - */ - -package bisq.desktop.primary.main.content.wallet; - -import bisq.desktop.components.containers.BisqGridPane; -import bisq.desktop.components.overlay.Popup; -import bisq.i18n.Res; -import bisq.wallets.electrum.ElectrumWalletService; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; -import javafx.scene.layout.Pane; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; - -import java.util.Optional; - -public class WalletWithdrawFundsPopup extends Popup { - private final Controller controller; - - public WalletWithdrawFundsPopup(ElectrumWalletService walletService) { - super(); - controller = new Controller(walletService, this); - } - - @Override - public void addContent() { - super.addContent(); - controller.addContent(); - } - - @Slf4j - private static class Controller implements bisq.desktop.common.view.Controller { - private final ElectrumWalletService walletService; - - private final Model model; - @Getter - private final View view; - - private Controller(ElectrumWalletService walletService, Popup popup) { - this.walletService = walletService; - - model = new Model(); - view = new View(model, this, popup); - } - - @Override - public void onActivate() { - } - - @Override - public void onDeactivate() { - } - - public void onWithdraw() { - String passphraseString = model.passphraseProperty.get(); - Optional passphrase = Optional.ofNullable(passphraseString); - walletService.sendToAddress( - passphrase, model.addressProperty.get(), Double.parseDouble(model.amountProperty.get()) - ); - } - - private void addContent() { - view.addContent(); - } - } - - private static class Model implements bisq.desktop.common.view.Model { - private final StringProperty addressProperty = new SimpleStringProperty(this, "address"); - private final StringProperty amountProperty = new SimpleStringProperty(this, "amount"); - private final StringProperty passphraseProperty = new SimpleStringProperty(this, "passphrase"); - } - - private static class View extends bisq.desktop.common.view.View { - private final Popup popup; - - private View(Model model, Controller controller, Popup popup) { - super(new Pane(), model, controller); - this.popup = popup; - - popup.headLine(Res.get("wallet.withdrawFromWallet")); - popup.message(Res.get("wallet.withdrawToExternalWalletMessage")); - popup.actionButtonText(Res.get("wallet.withdraw")); - popup.onAction(controller::onWithdraw); - popup.doCloseOnAction(true); - } - - @Override - protected void onViewAttached() { - } - - @Override - protected void onViewDetached() { - } - - private void addContent() { - BisqGridPane gridPane = popup.getGridPane(); - gridPane.addTextField(Res.get("address"), model.addressProperty); - gridPane.addTextField(Res.get("amount"), model.amountProperty); - gridPane.addPasswordField(Res.get("passphrase"), model.passphraseProperty); - } - } -} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/dashboard/WalletDashboardController.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/dashboard/WalletDashboardController.java new file mode 100644 index 0000000000..9510d8ff2a --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/dashboard/WalletDashboardController.java @@ -0,0 +1,69 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.dashboard; + +import bisq.application.DefaultApplicationService; +import bisq.common.observable.Pin; +import bisq.desktop.common.observable.FxBindings; +import bisq.desktop.common.threading.UIThread; +import bisq.desktop.common.view.Controller; +import bisq.desktop.common.view.Navigation; +import bisq.desktop.common.view.NavigationTarget; +import bisq.wallets.electrum.ElectrumWalletService; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WalletDashboardController implements Controller { + @Getter + private final WalletDashboardView view; + private final WalletDashboardModel model; + private final ElectrumWalletService electrumWalletService; + private Pin balancePin; + + public WalletDashboardController(DefaultApplicationService applicationService) { + electrumWalletService = applicationService.getElectrumWalletService(); + model = new WalletDashboardModel(); + view = new WalletDashboardView(model, this); + } + + @Override + public void onActivate() { + balancePin = FxBindings.bind(model.getBalanceAsCoinProperty()) + .to(electrumWalletService.getObservableBalanceAsCoin()); + + electrumWalletService.getBalance().whenComplete((balance, throwable) -> { + if (throwable == null) { + UIThread.run(() -> model.getBalanceAsCoinProperty().set(balance)); + } + }); + } + + @Override + public void onDeactivate() { + balancePin.unbind(); + } + + void onSend() { + Navigation.navigateTo(NavigationTarget.WALLET_SEND); + } + + void onReceive() { + Navigation.navigateTo(NavigationTarget.WALLET_RECEIVE); + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/dashboard/WalletDashboardModel.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/dashboard/WalletDashboardModel.java new file mode 100644 index 0000000000..97475b3c40 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/dashboard/WalletDashboardModel.java @@ -0,0 +1,41 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.dashboard; + +import bisq.common.monetary.Coin; +import bisq.desktop.common.view.Model; +import bisq.presentation.formatters.AmountFormatter; +import javafx.beans.binding.Bindings; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.value.ObservableValue; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +public class WalletDashboardModel implements Model { + private final ObjectProperty balanceAsCoinProperty = new SimpleObjectProperty<>(Coin.of(0, "BTC")); + private final ObservableValue formattedBalanceProperty = Bindings.createStringBinding( + () -> AmountFormatter.formatAmount(balanceAsCoinProperty.get(), true), + balanceAsCoinProperty + ); + + public WalletDashboardModel() { + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/dashboard/WalletDashboardView.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/dashboard/WalletDashboardView.java new file mode 100644 index 0000000000..e2de56481d --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/dashboard/WalletDashboardView.java @@ -0,0 +1,103 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.dashboard; + +import bisq.common.data.Triple; +import bisq.desktop.common.view.View; +import bisq.i18n.Res; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WalletDashboardView extends View { + private final Button send, receive; + private final Label balanceLabel; + + public WalletDashboardView(WalletDashboardModel model, WalletDashboardController controller) { + super(new VBox(20), model, controller); + + root.setSpacing(20); + + Triple balanceTriple = createBalanceBox(); + VBox balanceBox = balanceTriple.getFirst(); + balanceLabel = balanceTriple.getSecond(); + VBox.setMargin(balanceBox, new Insets(40, 0, 0, 0)); + + send = getCardButton(Res.get("wallet.sendBtc"), "green-card-button"); + receive = getCardButton(Res.get("wallet.receiveBtc"), "grey-card-button"); + + HBox boxes = new HBox(25, send, receive); + boxes.setAlignment(Pos.CENTER); + HBox.setHgrow(send, Priority.ALWAYS); + HBox.setHgrow(receive, Priority.ALWAYS); + + root.setAlignment(Pos.CENTER); + root.getChildren().addAll(balanceBox, boxes); + } + + @Override + protected void onViewAttached() { + balanceLabel.textProperty().bind(model.getFormattedBalanceProperty()); + send.setOnAction(e -> controller.onSend()); + receive.setOnAction(e -> controller.onReceive()); + } + + @Override + protected void onViewDetached() { + balanceLabel.textProperty().unbind(); + send.setOnAction(null); + receive.setOnAction(null); + } + + private Triple createBalanceBox() { + Label titleLabel = new Label(Res.get("wallet.yourBalance")); + titleLabel.getStyleClass().add("bisq-text-headline-2"); + + Label valueLabel = new Label(); + valueLabel.getStyleClass().add("bisq-text-headline-3"); + + Label codeLabel = new Label("BTC"); + codeLabel.getStyleClass().addAll("bisq-text-12"); + + HBox hBox = new HBox(9, valueLabel, codeLabel); + hBox.setAlignment(Pos.BASELINE_CENTER); + + VBox vBox = new VBox(0, titleLabel, hBox); + vBox.setAlignment(Pos.CENTER); + vBox.getStyleClass().add("bisq-box-1"); + vBox.setPadding(new Insets(30, 0, 30, 0)); + return new Triple<>(vBox, valueLabel, codeLabel); + } + + private Button getCardButton(String title, String styleClass) { + Button button = new Button(title); + button.getStyleClass().add("bisq-text-headline-2"); + button.getStyleClass().setAll(styleClass); + button.setAlignment(Pos.CENTER); + int width = 235; + button.setPrefWidth(width); + button.setMinHeight(112); + return button; + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/receive/WalletReceiveController.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/receive/WalletReceiveController.java new file mode 100644 index 0000000000..9e13280da3 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/receive/WalletReceiveController.java @@ -0,0 +1,54 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.receive; + +import bisq.application.DefaultApplicationService; +import bisq.desktop.common.threading.UIThread; +import bisq.desktop.common.utils.ClipboardUtil; +import bisq.desktop.common.view.Controller; +import bisq.wallets.electrum.ElectrumWalletService; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WalletReceiveController implements Controller { + @Getter + private final WalletReceiveView view; + private final WalletReceiveModel model; + private final ElectrumWalletService electrumWalletService; + + public WalletReceiveController(DefaultApplicationService applicationService) { + electrumWalletService = applicationService.getElectrumWalletService(); + model = new WalletReceiveModel(); + view = new WalletReceiveView(model, this); + } + + @Override + public void onActivate() { + electrumWalletService.getNewAddress(). + thenAccept(receiveAddress -> UIThread.run(() -> model.getReceiveAddress().setValue(receiveAddress))); + } + + @Override + public void onDeactivate() { + } + + void onCopyToClipboard() { + ClipboardUtil.copyToClipboard(model.getReceiveAddress().get()); + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/receive/WalletReceiveModel.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/receive/WalletReceiveModel.java new file mode 100644 index 0000000000..cceac6523c --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/receive/WalletReceiveModel.java @@ -0,0 +1,32 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.receive; + +import bisq.desktop.common.view.Model; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +public class WalletReceiveModel implements Model { + private final StringProperty receiveAddress = new SimpleStringProperty(); + public WalletReceiveModel() { + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/receive/WalletReceiveView.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/receive/WalletReceiveView.java new file mode 100644 index 0000000000..1ab385f5d8 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/receive/WalletReceiveView.java @@ -0,0 +1,62 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.receive; + +import bisq.desktop.common.view.View; +import bisq.desktop.components.controls.MaterialTextField; +import bisq.i18n.Res; +import de.jensd.fx.fontawesome.AwesomeIcon; +import javafx.geometry.Insets; +import javafx.scene.control.Button; +import javafx.scene.layout.VBox; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WalletReceiveView extends View { + + private final MaterialTextField address; + private final Button copyButton; + + public WalletReceiveView(WalletReceiveModel model, WalletReceiveController controller) { + super(new VBox(20), model, controller); + + root.setPadding(new Insets(40, 0, 0, 0)); + + address = new MaterialTextField(Res.get("wallet.receive.address")); + address.setEditable(false); + address.setIcon(AwesomeIcon.COPY); + + copyButton = new Button(Res.get("wallet.receive.copy")); + copyButton.setDefaultButton(true); + + root.getChildren().addAll(address, copyButton); + } + + @Override + protected void onViewAttached() { + address.textProperty().bind(model.getReceiveAddress()); + copyButton.setOnAction(e -> controller.onCopyToClipboard()); + address.getIconButton().setOnAction(e -> controller.onCopyToClipboard()); + } + + @Override + protected void onViewDetached() { + address.textProperty().unbind(); + copyButton.setOnAction(null); + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/send/WalletSendController.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/send/WalletSendController.java new file mode 100644 index 0000000000..1d681253d5 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/send/WalletSendController.java @@ -0,0 +1,80 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.send; + +import bisq.application.DefaultApplicationService; +import bisq.desktop.common.threading.UIThread; +import bisq.desktop.common.utils.validation.MonetaryValidator; +import bisq.desktop.common.view.Controller; +import bisq.desktop.components.overlay.Popup; +import bisq.wallets.electrum.ElectrumWalletService; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.fxmisc.easybind.EasyBind; +import org.fxmisc.easybind.Subscription; + +import java.util.Optional; + +@Slf4j +public class WalletSendController implements Controller { + @Getter + private final WalletSendView view; + private final WalletSendModel model; + private final ElectrumWalletService electrumWalletService; + private final MonetaryValidator amountValidator = new MonetaryValidator(); + private Subscription addressPin; + private Subscription amountPin; + + public WalletSendController(DefaultApplicationService applicationService) { + electrumWalletService = applicationService.getElectrumWalletService(); + model = new WalletSendModel(); + view = new WalletSendView(model, this, amountValidator); + } + + @Override + public void onActivate() { + addressPin = EasyBind.subscribe(model.getAddress(), customMethod -> { + + }); + amountPin = EasyBind.subscribe(model.getAmount(), customMethod -> { + + }); + + //todo check if wallet is encrypted + electrumWalletService.isWalletEncrypted() + .thenAccept(isWalletEncrypted -> UIThread.run(() -> model.getIsPasswordVisible().set(isWalletEncrypted))); + } + + @Override + public void onDeactivate() { + addressPin.unsubscribe(); + amountPin.unsubscribe(); + } + + void onSend() { + //todo + double amount = Double.parseDouble(model.getAmount().get()); + String address = model.getAddress().get(); + electrumWalletService.sendToAddress(Optional.ofNullable(model.getPassword().get()), address, amount) + .whenComplete((response, throwable) -> { + if (throwable != null) { + UIThread.run(() -> new Popup().error(throwable.getMessage()).show()); + } + }); + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/send/WalletSendModel.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/send/WalletSendModel.java new file mode 100644 index 0000000000..7d3519d0a5 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/send/WalletSendModel.java @@ -0,0 +1,38 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.send; + +import bisq.desktop.common.view.Model; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +public class WalletSendModel implements Model { + private final StringProperty address = new SimpleStringProperty(); + private final StringProperty amount = new SimpleStringProperty(); + private final StringProperty password = new SimpleStringProperty(); + private final BooleanProperty isPasswordVisible = new SimpleBooleanProperty(); + + public WalletSendModel() { + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/send/WalletSendView.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/send/WalletSendView.java new file mode 100644 index 0000000000..f18a7eba1e --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/send/WalletSendView.java @@ -0,0 +1,70 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.send; + +import bisq.desktop.common.utils.validation.MonetaryValidator; +import bisq.desktop.common.view.View; +import bisq.desktop.components.controls.MaterialPasswordField; +import bisq.desktop.components.controls.MaterialTextField; +import bisq.i18n.Res; +import javafx.geometry.Insets; +import javafx.scene.control.Button; +import javafx.scene.layout.VBox; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WalletSendView extends View { + private final MaterialTextField address, amount; + private final MaterialPasswordField password; + private final Button sendButton; + + public WalletSendView(WalletSendModel model, WalletSendController controller, MonetaryValidator amountValidator) { + super(new VBox(20), model, controller); + + root.setPadding(new Insets(40, 0, 0, 0)); + + address = new MaterialTextField(Res.get("wallet.send.address"), null, null); + amount = new MaterialTextField(Res.get("wallet.send.amount"), null, null); + amount.setValidator(amountValidator); + password = new MaterialPasswordField(Res.get("wallet.send.password"), null, null); + sendButton = new Button(Res.get("wallet.send.sendBtc")); + sendButton.setDefaultButton(true); + + root.getChildren().addAll(address, amount, password, sendButton); + } + + @Override + protected void onViewAttached() { + address.textProperty().bindBidirectional(model.getAddress()); + amount.textProperty().bindBidirectional(model.getAmount()); + password.textProperty().bindBidirectional(model.getPassword()); + password.visibleProperty().bind(model.getIsPasswordVisible()); + password.managedProperty().bind(model.getIsPasswordVisible()); + sendButton.setOnAction(e -> controller.onSend()); + } + + @Override + protected void onViewDetached() { + address.textProperty().unbindBidirectional(model.getAddress()); + amount.textProperty().unbindBidirectional(model.getAmount()); + password.textProperty().unbindBidirectional(model.getPassword()); + password.visibleProperty().unbind(); + password.managedProperty().unbind(); + sendButton.setOnAction(null); + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/settings/WalletSettingsController.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/settings/WalletSettingsController.java new file mode 100644 index 0000000000..671c8b9952 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/settings/WalletSettingsController.java @@ -0,0 +1,46 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.settings; + +import bisq.application.DefaultApplicationService; +import bisq.desktop.common.view.Controller; +import bisq.wallets.electrum.ElectrumWalletService; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WalletSettingsController implements Controller { + @Getter + private final WalletSettingsView view; + private final WalletSettingsModel model; + private final ElectrumWalletService electrumWalletService; + + public WalletSettingsController(DefaultApplicationService applicationService) { + electrumWalletService = applicationService.getElectrumWalletService(); + model = new WalletSettingsModel(); + view = new WalletSettingsView(model, this); + } + + @Override + public void onActivate() { + } + + @Override + public void onDeactivate() { + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/settings/WalletSettingsModel.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/settings/WalletSettingsModel.java new file mode 100644 index 0000000000..c7b1f43fb8 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/settings/WalletSettingsModel.java @@ -0,0 +1,29 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.settings; + +import bisq.desktop.common.view.Model; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +public class WalletSettingsModel implements Model { + public WalletSettingsModel() { + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/settings/WalletSettingsView.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/settings/WalletSettingsView.java new file mode 100644 index 0000000000..3361f29961 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/settings/WalletSettingsView.java @@ -0,0 +1,38 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.settings; + +import bisq.desktop.common.view.View; +import javafx.scene.layout.VBox; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WalletSettingsView extends View { + + public WalletSettingsView(WalletSettingsModel model, WalletSettingsController controller) { + super(new VBox(20), model, controller); + } + + @Override + protected void onViewAttached() { + } + + @Override + protected void onViewDetached() { + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletTransactionListItem.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTransactionListItem.java similarity index 50% rename from desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletTransactionListItem.java rename to desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTransactionListItem.java index 8b1fda3da4..d0319696e7 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/WalletTransactionListItem.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTransactionListItem.java @@ -15,33 +15,28 @@ * along with Bisq. If not, see . */ -package bisq.desktop.primary.main.content.wallet; +package bisq.desktop.primary.main.content.wallet.txs; import bisq.desktop.components.table.TableItem; +import bisq.presentation.formatters.AmountFormatter; +import bisq.presentation.formatters.DateFormatter; import bisq.wallets.core.model.Transaction; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +@Slf4j +@Getter public class WalletTransactionListItem implements TableItem { - private final StringProperty description = new SimpleStringProperty(this, "wallet.transaction.history.description"); - private final StringProperty amount = new SimpleStringProperty(this, "amount"); - private final StringProperty confirmations = new SimpleStringProperty(this, "wallet.column.confirmations"); + private final String date; + private final String txId; + private final String amount; + private final String confirmations; public WalletTransactionListItem(Transaction transaction) { - description.set(transaction.getTxId()); - amount.set(String.valueOf(transaction.getAmount())); - confirmations.set(String.valueOf(transaction.getConfirmations())); + date = DateFormatter.formatDateTime(transaction.getDate()); + txId = transaction.getTxId(); + amount = AmountFormatter.formatAmount(transaction.getAmount()); + confirmations = String.valueOf(transaction.getConfirmations()); } - public StringProperty descriptionProperty() { - return description; - } - - public StringProperty amountProperty() { - return amount; - } - - public StringProperty confirmationsProperty() { - return confirmations; - } } diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTxsController.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTxsController.java new file mode 100644 index 0000000000..7111b86388 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTxsController.java @@ -0,0 +1,55 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.txs; + +import bisq.application.DefaultApplicationService; +import bisq.desktop.common.threading.UIThread; +import bisq.desktop.common.view.Controller; +import bisq.wallets.electrum.ElectrumWalletService; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import java.util.stream.Collectors; + +@Slf4j +public class WalletTxsController implements Controller { + @Getter + private final WalletTxsView view; + private final WalletTxsModel model; + private final ElectrumWalletService electrumWalletService; + + public WalletTxsController(DefaultApplicationService applicationService) { + electrumWalletService = applicationService.getElectrumWalletService(); + model = new WalletTxsModel(); + view = new WalletTxsView(model, this); + } + + @Override + public void onActivate() { + electrumWalletService.listTransactions() + .thenAccept(transactions -> UIThread.run(() -> { + model.getListItems().setAll(transactions.stream() + .map(WalletTransactionListItem::new) + .collect(Collectors.toList())); + })); + } + + @Override + public void onDeactivate() { + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTxsModel.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTxsModel.java new file mode 100644 index 0000000000..de2dd5743a --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTxsModel.java @@ -0,0 +1,35 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.txs; + +import bisq.desktop.common.view.Model; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.collections.transformation.SortedList; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +public class WalletTxsModel implements Model { + private final ObservableList listItems = FXCollections.observableArrayList(); + private final SortedList sortedList = new SortedList<>(listItems); + + public WalletTxsModel() { + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTxsView.java b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTxsView.java new file mode 100644 index 0000000000..d6d0be814a --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/primary/main/content/wallet/txs/WalletTxsView.java @@ -0,0 +1,82 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.primary.main.content.wallet.txs; + +import bisq.desktop.common.view.View; +import bisq.desktop.components.table.BisqTableColumn; +import bisq.desktop.components.table.BisqTableView; +import bisq.i18n.Res; +import javafx.geometry.Insets; +import javafx.scene.layout.VBox; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WalletTxsView extends View { + private final BisqTableView tableView; + + public WalletTxsView(WalletTxsModel model, WalletTxsController controller) { + super(new VBox(20), model, controller); + + root.setPadding(new Insets(40, 0, 0, 0)); + + tableView = new BisqTableView<>(model.getSortedList()); + tableView.setMinHeight(300); + // Triggers to fill the available height + tableView.setPrefHeight(2000); + configTableView(); + + root.getChildren().add(tableView); + } + + @Override + protected void onViewAttached() { + } + + @Override + protected void onViewDetached() { + } + + private void configTableView() { + tableView.getColumns().add(new BisqTableColumn.Builder() + .title(Res.get("date")) + .minWidth(200) + .valueSupplier(WalletTransactionListItem::getDate) + .isSortable(true) + .isFirst() + .build()); + tableView.getColumns().add(new BisqTableColumn.Builder() + .title(Res.get("wallet.txs.txId")) + .minWidth(200) + .valueSupplier(WalletTransactionListItem::getTxId) + .isSortable(true) + .build()); + tableView.getColumns().add(new BisqTableColumn.Builder() + .title(Res.get("wallet.txs.amount")) + .minWidth(120) + .valueSupplier(WalletTransactionListItem::getAmount) + .isSortable(true) + .build()); + tableView.getColumns().add(new BisqTableColumn.Builder() + .title(Res.get("wallet.txs.confirmations")) + .minWidth(120) + .valueSupplier(WalletTransactionListItem::getConfirmations) + .isSortable(true) + .isLast() + .build()); + } +} diff --git a/desktop/src/main/java/bisq/desktop/primary/main/top/MarketSelection.java b/desktop/src/main/java/bisq/desktop/primary/main/top/MarketSelection.java index 48787d58ec..bd56ab8ded 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/top/MarketSelection.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/top/MarketSelection.java @@ -171,14 +171,20 @@ protected void onViewDetached() { protected ListCell getListCell() { return new ListCell<>() { private final Label price, codes; + private final HBox hBox; { codes = new Label(); codes.setMouseTransparent(true); codes.getStyleClass().add("bisq-text-18"); + HBox.setMargin(codes, new Insets(0, 0, 0, -10)); + price = new Label(); price.setMouseTransparent(true); price.setId("bisq-text-20"); + + hBox = new HBox(12, codes, price); + hBox.setAlignment(Pos.CENTER_LEFT); } @Override @@ -188,9 +194,7 @@ protected void updateItem(ListItem item, boolean empty) { if (item != null && !empty) { price.setText(item.price); codes.setText(item.codes); - HBox.setMargin(codes, new Insets(0, 0, 0, -10)); - HBox hBox = new HBox(12, codes, price); - hBox.setAlignment(Pos.CENTER_LEFT); + setGraphic(hBox); } else { setGraphic(null); diff --git a/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelController.java b/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelController.java index 2fa487d508..c4be4786b7 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelController.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelController.java @@ -18,26 +18,38 @@ package bisq.desktop.primary.main.top; import bisq.application.DefaultApplicationService; +import bisq.common.observable.Pin; +import bisq.desktop.common.observable.FxBindings; import bisq.desktop.common.view.Controller; import bisq.desktop.primary.main.content.components.UserProfileSelection; +import bisq.wallets.electrum.ElectrumWalletService; import lombok.Getter; public class TopPanelController implements Controller { + private final ElectrumWalletService electrumWalletService; @Getter private final TopPanelView view; + private final TopPanelModel model; + private Pin balancePin; public TopPanelController(DefaultApplicationService applicationService) { - TopPanelModel model = new TopPanelModel(); + electrumWalletService = applicationService.getElectrumWalletService(); + + model = new TopPanelModel(); UserProfileSelection userProfileSelection = new UserProfileSelection(applicationService.getUserService().getUserIdentityService()); MarketSelection marketSelection = new MarketSelection(applicationService.getOracleService().getMarketPriceService()); view = new TopPanelView(model, this, userProfileSelection, marketSelection.getRoot()); + } @Override public void onActivate() { + balancePin = FxBindings.bind(model.getBalanceAsCoinProperty()) + .to(electrumWalletService.getObservableBalanceAsCoin()); } @Override public void onDeactivate() { + balancePin.unbind(); } } diff --git a/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelModel.java b/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelModel.java index 98114e779a..eea34ac446 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelModel.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelModel.java @@ -18,9 +18,20 @@ package bisq.desktop.primary.main.top; +import bisq.common.monetary.Coin; import bisq.desktop.common.view.Model; +import bisq.presentation.formatters.AmountFormatter; +import javafx.beans.binding.Bindings; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.value.ObservableValue; import lombok.Getter; @Getter public class TopPanelModel implements Model { + private final ObjectProperty balanceAsCoinProperty = new SimpleObjectProperty<>(Coin.of(0, "BTC")); + private final ObservableValue formattedBalanceProperty = Bindings.createStringBinding( + () -> AmountFormatter.formatAmount(balanceAsCoinProperty.get(), true), + balanceAsCoinProperty + ); } diff --git a/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelView.java b/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelView.java index 315724c6d7..b017f1e9c8 100644 --- a/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelView.java +++ b/desktop/src/main/java/bisq/desktop/primary/main/top/TopPanelView.java @@ -17,15 +17,20 @@ package bisq.desktop.primary.main.top; +import bisq.common.data.Triple; import bisq.desktop.common.view.View; import bisq.desktop.components.containers.Spacer; import bisq.desktop.primary.main.content.components.UserProfileSelection; +import bisq.i18n.Res; import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.Label; import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; public class TopPanelView extends View { public static final int HEIGHT = 57; + private final Label balanceLabel; public TopPanelView(TopPanelModel model, TopPanelController controller, @@ -38,17 +43,43 @@ public TopPanelView(TopPanelModel model, root.setSpacing(28); root.setFillHeight(true); root.setStyle("-fx-background-color: -bisq-dark-grey;"); - HBox.setMargin(marketPriceBox, new Insets(-10, 10, 0, 0)); + HBox.setMargin(marketPriceBox, new Insets(0, 10, 0, 0)); + + Pane userProfileSelectionRoot = userProfileSelection.getRoot(); userProfileSelection.setIsLeftAligned(true); - root.setPadding(new Insets(7, 30, 0, 0)); - root.getChildren().addAll(Spacer.fillHBox(), marketPriceBox, userProfileSelection.getRoot()); + HBox.setMargin(userProfileSelectionRoot, new Insets(6.5, 15, 0, 0)); + + Triple balanceTriple = createBalanceBox(); + HBox balanceBox = balanceTriple.getFirst(); + balanceLabel = balanceTriple.getSecond(); + HBox.setMargin(balanceBox, new Insets(0, 0, 0, 30)); + + root.getChildren().addAll(balanceBox, Spacer.fillHBox(), marketPriceBox, userProfileSelectionRoot); } @Override protected void onViewAttached() { + balanceLabel.textProperty().bind(model.getFormattedBalanceProperty()); } @Override protected void onViewDetached() { + balanceLabel.textProperty().unbind(); + } + + private Triple createBalanceBox() { + Label titleLabel = new Label(Res.get("wallet.balance").toUpperCase()); + titleLabel.getStyleClass().add("bisq-text-18"); + + Label valueLabel = new Label(); + valueLabel.setId("bisq-text-20"); + + Label codeLabel = new Label("BTC"); + codeLabel.setId("bisq-text-20"); + HBox.setMargin(codeLabel, new Insets(0, 0, 0, -10)); + + HBox hBox = new HBox(12, titleLabel, valueLabel, codeLabel); + hBox.setAlignment(Pos.CENTER_LEFT); + return new Triple<>(hBox, valueLabel, codeLabel); } } diff --git a/desktop/src/main/resources/bisq.css b/desktop/src/main/resources/bisq.css index 2742f84f12..b6d3469375 100644 --- a/desktop/src/main/resources/bisq.css +++ b/desktop/src/main/resources/bisq.css @@ -1238,6 +1238,39 @@ } +/******************************************************************************* + * * + * Card button * + * * + ******************************************************************************/ + +.grey-card-button { + -fx-font-size: 1.46em; + -fx-background-color: -bisq-grey-3; + -fx-background-radius: 4; + -fx-text-fill: -bisq-white; + -fx-cursor: hand; + -fx-font-family: "IBM Plex Sans Light"; +} + +.grey-card-button:hover { + -fx-background-color: -bisq-grey-18; +} + +.green-card-button { + -fx-font-size: 1.46em; + -fx-background-color: -bisq-green; + -fx-background-radius: 4; + -fx-text-fill: -bisq-white; + -fx-cursor: hand; + -fx-font-family: "IBM Plex Sans Light"; +} + +.green-card-button:hover { + -fx-background-color: -bisq-green-lighter; +} + + /******************************************************************************* * * * Hyperlink * @@ -1664,7 +1697,7 @@ tree-table-view:focused { /* column-header */ .table-view .column-header { -fx-background-color: transparent; - -fx-pref-height: 54px; + -fx-pref-height: 34px; } .table-view .column-header-background { @@ -1674,6 +1707,7 @@ tree-table-view:focused { .table-view .column-header .label { -fx-alignment: center; -fx-text-fill: -bisq-grey-dimmed; + -fx-font-family: "IBM Plex Sans Light"; -fx-font-size: 0.9em; -fx-label-padding: 0 10 0 10; } diff --git a/docker/electrumx/Dockerfile b/docker/electrumx/Dockerfile index b79d3cc58b..5e2af46ae3 100644 --- a/docker/electrumx/Dockerfile +++ b/docker/electrumx/Dockerfile @@ -1,12 +1,5 @@ FROM python:3 -# Install Bitcoin Core -WORKDIR /tmp -RUN wget https://bitcoincore.org/bin/bitcoin-core-24.0.1/bitcoin-24.0.1-x86_64-linux-gnu.tar.gz && \ - tar xvf bitcoin-24.0.1-x86_64-linux-gnu.tar.gz && \ - mv bitcoin-24.0.1/bin/* /usr/local/bin/ && \ - rm -rf /tmp/bitcoin* - # Install ElectrumX WORKDIR /root RUN git clone https://github.com/spesmilo/electrumx.git && \ @@ -14,12 +7,8 @@ RUN git clone https://github.com/spesmilo/electrumx.git && \ pip3 install . && \ mkdir db_directory -# Start Bitcoin Core Daemon and ElectrumX +# Start ElectrumX WORKDIR /root/electrumx -CMD bitcoind -regtest -daemon -server -debug=1 \ - -rpcbind -rpcallowip=127.0.0.1 -rpcuser=bisq -rpcpassword=bisq \ - -zmqpubhashblock=tcp://:7771 -zmqpubrawtx=tcp://:7771 \ - -fallbackfee=0.00000001 -whitelist=127.0.0.1 -txindex=1 && \ - ALLOW_ROOT=yes SERVICES=tcp://:50001,rpc:// COIN=Bitcoin NET=regtest \ - DAEMON_URL=http://bisq:bisq@localhost:18443 \ +CMD ALLOW_ROOT=yes SERVICES=tcp://:50001,rpc:// COIN=Bitcoin NET=regtest \ + DAEMON_URL=http://bisq:bisq@host.docker.internal:18443 \ DB_DIRECTORY=/root/electrumx/db_directory ./electrumx_server diff --git a/docker/electrumxAndBitcoind/Dockerfile b/docker/electrumxAndBitcoind/Dockerfile new file mode 100644 index 0000000000..b79d3cc58b --- /dev/null +++ b/docker/electrumxAndBitcoind/Dockerfile @@ -0,0 +1,25 @@ +FROM python:3 + +# Install Bitcoin Core +WORKDIR /tmp +RUN wget https://bitcoincore.org/bin/bitcoin-core-24.0.1/bitcoin-24.0.1-x86_64-linux-gnu.tar.gz && \ + tar xvf bitcoin-24.0.1-x86_64-linux-gnu.tar.gz && \ + mv bitcoin-24.0.1/bin/* /usr/local/bin/ && \ + rm -rf /tmp/bitcoin* + +# Install ElectrumX +WORKDIR /root +RUN git clone https://github.com/spesmilo/electrumx.git && \ + cd electrumx && \ + pip3 install . && \ + mkdir db_directory + +# Start Bitcoin Core Daemon and ElectrumX +WORKDIR /root/electrumx +CMD bitcoind -regtest -daemon -server -debug=1 \ + -rpcbind -rpcallowip=127.0.0.1 -rpcuser=bisq -rpcpassword=bisq \ + -zmqpubhashblock=tcp://:7771 -zmqpubrawtx=tcp://:7771 \ + -fallbackfee=0.00000001 -whitelist=127.0.0.1 -txindex=1 && \ + ALLOW_ROOT=yes SERVICES=tcp://:50001,rpc:// COIN=Bitcoin NET=regtest \ + DAEMON_URL=http://bisq:bisq@localhost:18443 \ + DB_DIRECTORY=/root/electrumx/db_directory ./electrumx_server diff --git a/i18n/src/main/resources/default.properties b/i18n/src/main/resources/default.properties index de01752a87..506bf738ea 100644 --- a/i18n/src/main/resources/default.properties +++ b/i18n/src/main/resources/default.properties @@ -50,6 +50,11 @@ chat=Discussions learn=Learn events=Events wallet=Wallet +wallet.dashboard=Dashboard +wallet.send=Send +wallet.receive=Receive +wallet.txs=Transactions +wallet.settings=Settings account=Account support=Support settings=Settings @@ -113,6 +118,7 @@ currency=Currency day=Day days=Days mediator=Mediator +at=at #################################################################### # @@ -443,17 +449,31 @@ OTHER=Other ###################################################### ## Wallet ###################################################### + +wallet.yourBalance=Your balance +wallet.sendBtc=Send Bitcoin +wallet.receiveBtc=Receive Bitcoin + +wallet.send.address=Receiver's address +wallet.send.amount=Bitcoin amount to send +wallet.send.password=Wallet password +wallet.send.sendBtc=Send Bitcoin + +wallet.receive.address=Unused address +wallet.receive.copy=Copy address + +wallet.txs.txId=Transaction ID +wallet.txs.amount=Amount in BTC +wallet.txs.confirmations=Confirmations + # Balance Box wallet.availableBalance=Available Balance # Wallet UI wallet.balance=Balance -wallet.btc=BTC wallet.withdraw=Withdraw wallet.withdrawFromWallet=Withdraw from Wallet wallet.withdrawToExternalWalletMessage=Send your funds to an external wallet. wallet.transaction.history=Transaction History -wallet.receive.address=Receive Address -wallet.receive.copy=Copy # Wallet Transaction History Table Columns wallet.transaction.history.description=Description wallet.column.confirmations=Confirmations diff --git a/presentation/src/main/java/bisq/presentation/formatters/DateFormatter.java b/presentation/src/main/java/bisq/presentation/formatters/DateFormatter.java index 60c47c4ce6..ac2118c68c 100644 --- a/presentation/src/main/java/bisq/presentation/formatters/DateFormatter.java +++ b/presentation/src/main/java/bisq/presentation/formatters/DateFormatter.java @@ -21,6 +21,7 @@ import java.text.DateFormat; import java.util.Date; +import java.util.Locale; import java.util.TimeZone; public class DateFormatter { @@ -29,24 +30,21 @@ public static String formatDateTime(long date) { } public static String formatDateTime(Date date) { - return formatDateTime(date, DateFormat.SHORT, DateFormat.SHORT, true, " "); + return formatDateTime(date, DateFormat.DEFAULT, DateFormat.DEFAULT, true, " "); } - public static String formatDateTimeV2(Date date) { - return formatDateTime(date, DateFormat.MEDIUM, DateFormat.SHORT, true, " at "); - } - - private static String formatDateTime(Date date, - int dateFormat, - int timeFormat, - boolean useLocalTimezone, - String delimiter) { + public static String formatDateTime(Date date, + int dateFormat, + int timeFormat, + boolean useLocalTimezone, + String delimiter) { if (date == null) { return ""; } - DateFormat dateFormatter = DateFormat.getDateInstance(dateFormat, LocaleRepository.getDefaultLocale()); - DateFormat timeFormatter = DateFormat.getTimeInstance(timeFormat, LocaleRepository.getDefaultLocale()); + Locale defaultLocale = LocaleRepository.getDefaultLocale(); + DateFormat dateFormatter = DateFormat.getDateInstance(dateFormat, defaultLocale); + DateFormat timeFormatter = DateFormat.getTimeInstance(timeFormat, defaultLocale); if (!useLocalTimezone) { dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); timeFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); diff --git a/wallets/bitcoind/src/main/java/bisq/wallets/bitcoind/rpc/responses/BitcoindListTransactionsResponse.java b/wallets/bitcoind/src/main/java/bisq/wallets/bitcoind/rpc/responses/BitcoindListTransactionsResponse.java index 8fa4b7d29e..bbb1f198df 100644 --- a/wallets/bitcoind/src/main/java/bisq/wallets/bitcoind/rpc/responses/BitcoindListTransactionsResponse.java +++ b/wallets/bitcoind/src/main/java/bisq/wallets/bitcoind/rpc/responses/BitcoindListTransactionsResponse.java @@ -17,11 +17,13 @@ package bisq.wallets.bitcoind.rpc.responses; +import bisq.common.monetary.Coin; import bisq.wallets.core.model.Transaction; import bisq.wallets.json_rpc.JsonRpcResponse; import com.squareup.moshi.Json; import lombok.Getter; +import java.util.Date; import java.util.List; public class BitcoindListTransactionsResponse extends JsonRpcResponse> { @@ -50,5 +52,15 @@ public static class Entry implements Transaction { @Json(name = "bip125-replaceable") private String bip125Replaceable; private boolean abandoned; + + @Override + public Coin getAmount() { + return Coin.asBtc(amount); + } + + @Override + public Date getDate() { + return new Date(time * 1000L); + } } } diff --git a/wallets/bitcoind/src/test/java/bisq/wallets/bitcoind/BitcoindSendAndListTxsIntegrationTests.java b/wallets/bitcoind/src/test/java/bisq/wallets/bitcoind/BitcoindSendAndListTxsIntegrationTests.java index 78b0098854..20c04675d8 100644 --- a/wallets/bitcoind/src/test/java/bisq/wallets/bitcoind/BitcoindSendAndListTxsIntegrationTests.java +++ b/wallets/bitcoind/src/test/java/bisq/wallets/bitcoind/BitcoindSendAndListTxsIntegrationTests.java @@ -63,7 +63,7 @@ public void sendBtcAndListTxs() throws MalformedURLException, InterruptedExcepti BitcoindListTransactionsResponse.Entry firstTx = txs.get(0); assertEquals(firstTxReceiverAddress, firstTx.getAddress()); assertEquals("receive", firstTx.getCategory()); - assertEquals(1, firstTx.getAmount()); + assertEquals(100000000, firstTx.getAmount().getValue()); assertEquals(1, firstTx.getConfirmations()); assertEquals(0, firstTx.getWalletconflicts().length); assertEquals("no", firstTx.getBip125Replaceable()); @@ -71,7 +71,7 @@ public void sendBtcAndListTxs() throws MalformedURLException, InterruptedExcepti BitcoindListTransactionsResponse.Entry secondTx = txs.get(1); assertEquals(secondTxReceiverAddress, secondTx.getAddress()); assertEquals("receive", secondTx.getCategory()); - assertEquals(1, secondTx.getAmount()); + assertEquals(100000000, secondTx.getAmount().getValue()); assertEquals(1, secondTx.getConfirmations()); assertEquals(0, secondTx.getWalletconflicts().length); assertEquals("no", secondTx.getBip125Replaceable()); @@ -79,7 +79,7 @@ public void sendBtcAndListTxs() throws MalformedURLException, InterruptedExcepti BitcoindListTransactionsResponse.Entry thirdTx = txs.get(2); assertEquals(thirdTxReceiverAddress, thirdTx.getAddress()); assertEquals("receive", thirdTx.getCategory()); - assertEquals(1, thirdTx.getAmount()); + assertEquals(100000000, thirdTx.getAmount().getValue()); assertEquals(1, thirdTx.getConfirmations()); assertEquals(0, thirdTx.getWalletconflicts().length); assertEquals("no", thirdTx.getBip125Replaceable()); diff --git a/wallets/core/src/main/java/bisq/wallets/core/model/Transaction.java b/wallets/core/src/main/java/bisq/wallets/core/model/Transaction.java index ddb2798443..105823a9d4 100644 --- a/wallets/core/src/main/java/bisq/wallets/core/model/Transaction.java +++ b/wallets/core/src/main/java/bisq/wallets/core/model/Transaction.java @@ -17,10 +17,16 @@ package bisq.wallets.core.model; +import bisq.common.monetary.Coin; + +import java.util.Date; + public interface Transaction { String getTxId(); - double getAmount(); + Coin getAmount(); int getConfirmations(); + + Date getDate(); } diff --git a/wallets/electrum/build.gradle b/wallets/electrum/build.gradle index 5a760f6529..ddb6ef7f32 100644 --- a/wallets/electrum/build.gradle +++ b/wallets/electrum/build.gradle @@ -25,7 +25,8 @@ dependencies { implementation project(':core') implementation project(':json-rpc') implementation project(':process') - + + implementation libs.typesafe.config implementation libs.bundles.glassfish.jersey testImplementation project(':bitcoind') diff --git a/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumConfigFileCreationFailed.java b/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumConfigFileCreationFailedException.java similarity index 82% rename from wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumConfigFileCreationFailed.java rename to wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumConfigFileCreationFailedException.java index 77f7ca6657..ae3ea77938 100644 --- a/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumConfigFileCreationFailed.java +++ b/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumConfigFileCreationFailedException.java @@ -17,8 +17,8 @@ package bisq.wallets.electrum; -public class ElectrumConfigFileCreationFailed extends RuntimeException { - public ElectrumConfigFileCreationFailed(Throwable cause) { +public class ElectrumConfigFileCreationFailedException extends RuntimeException { + public ElectrumConfigFileCreationFailedException(Throwable cause) { super(cause); } } diff --git a/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumRegtestProcess.java b/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumRegtestProcess.java index 12d2216c63..089598b277 100644 --- a/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumRegtestProcess.java +++ b/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumRegtestProcess.java @@ -140,7 +140,7 @@ private void createElectrumConfigFile() { Files.writeString(configFilePath, configAsString); } catch (IOException e) { - throw new ElectrumConfigFileCreationFailed(e); + throw new ElectrumConfigFileCreationFailedException(e); } } } diff --git a/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumWalletService.java b/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumWalletService.java index cba013fef9..1caca7a0a7 100644 --- a/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumWalletService.java +++ b/wallets/electrum/src/main/java/bisq/wallets/electrum/ElectrumWalletService.java @@ -38,22 +38,34 @@ @Slf4j public class ElectrumWalletService implements Service { - private static final String CURRENCY_CODE = "BTC"; + @Getter + public static class Config { + private final boolean enabled; + + public Config(boolean enabled) { + this.enabled = enabled; + } - private final boolean isWalletEnabled; + public static Config from(com.typesafe.config.Config config) { + return new Config(config.getBoolean("enabled")); + } + } + + private final Config config; private final Path electrumRootDataDir; private final ElectrumProcess electrumProcess; private final ElectrumNotifyWebServer electrumNotifyWebServer = new ElectrumNotifyWebServer(NetworkUtils.findFreeSystemPort()); @Getter - private final Observable observableBalanceAsCoin = new Observable<>(Coin.of(0, CURRENCY_CODE)); + private final Observable observableBalanceAsCoin = new Observable<>(Coin.asBtc(0)); @Getter private final ObservableSet receiveAddresses = new ObservableSet<>(); private ElectrumWallet electrumWallet; - public ElectrumWalletService(boolean isWalletEnabled, Path bisqDataDir) { - this.isWalletEnabled = isWalletEnabled; + public ElectrumWalletService(Config config, Path bisqDataDir) { + this.config = config; + electrumRootDataDir = bisqDataDir.resolve("wallets") .resolve("electrum"); this.electrumProcess = createElectrumProcess(); @@ -61,7 +73,7 @@ public ElectrumWalletService(boolean isWalletEnabled, Path bisqDataDir) { @Override public CompletableFuture initialize() { - if (!isWalletEnabled) { + if (!config.isEnabled()) { return CompletableFuture.completedFuture(true); } @@ -92,7 +104,7 @@ public CompletableFuture initialize() { @Override public CompletableFuture shutdown() { - if (!isWalletEnabled) { + if (!config.isEnabled()) { return CompletableFuture.completedFuture(true); } @@ -132,6 +144,20 @@ public CompletableFuture sendToAddress(Optional passphrase, Stri }); } + public CompletableFuture isWalletEncrypted() { + //todo implement + return CompletableFuture.supplyAsync(() -> true); + } + + public CompletableFuture getBalance() { + return CompletableFuture.supplyAsync(() -> { + double balance = electrumWallet.getBalance(); + Coin balanceAsCoin = Coin.asBtc(balance); + observableBalanceAsCoin.set(balanceAsCoin); + return balanceAsCoin; + }); + } + private ElectrumProcess createElectrumProcess() { var processConfig = ElectrumProcessConfig.builder() .dataDir(electrumRootDataDir.resolve("wallet")) @@ -164,7 +190,7 @@ private void monitorAddress(String address) { private void updateBalance() { CompletableFuture.runAsync(() -> { double balance = electrumWallet.getBalance(); - Coin coin = Coin.of(balance, CURRENCY_CODE); + Coin coin = Coin.asBtc(balance); // Balance changed? if (!observableBalanceAsCoin.get().equals(coin)) { diff --git a/wallets/electrum/src/main/java/bisq/wallets/electrum/rpc/calls/ElectrumPayToRpcCall.java b/wallets/electrum/src/main/java/bisq/wallets/electrum/rpc/calls/ElectrumPayToRpcCall.java index 979e7dcfea..8616fc350c 100644 --- a/wallets/electrum/src/main/java/bisq/wallets/electrum/rpc/calls/ElectrumPayToRpcCall.java +++ b/wallets/electrum/src/main/java/bisq/wallets/electrum/rpc/calls/ElectrumPayToRpcCall.java @@ -17,8 +17,8 @@ package bisq.wallets.electrum.rpc.calls; -import bisq.wallets.json_rpc.reponses.JsonRpcStringResponse; import bisq.wallets.json_rpc.DaemonRpcCall; +import bisq.wallets.json_rpc.reponses.JsonRpcStringResponse; import lombok.Builder; import lombok.Getter; @@ -43,7 +43,8 @@ public String getRpcMethodName() { @Override public boolean isResponseValid(JsonRpcStringResponse response) { - return !response.getResult().isEmpty(); + String result = response.getResult(); + return result != null && !result.isEmpty(); } @Override diff --git a/wallets/electrum/src/main/java/bisq/wallets/electrum/rpc/responses/ElectrumOnChainTransactionResponse.java b/wallets/electrum/src/main/java/bisq/wallets/electrum/rpc/responses/ElectrumOnChainTransactionResponse.java index 2d58954c6c..e9cea12cd8 100644 --- a/wallets/electrum/src/main/java/bisq/wallets/electrum/rpc/responses/ElectrumOnChainTransactionResponse.java +++ b/wallets/electrum/src/main/java/bisq/wallets/electrum/rpc/responses/ElectrumOnChainTransactionResponse.java @@ -17,10 +17,15 @@ package bisq.wallets.electrum.rpc.responses; +import bisq.common.monetary.Coin; import bisq.wallets.core.model.Transaction; import com.squareup.moshi.Json; import lombok.Getter; +import lombok.ToString; +import java.util.Date; + +@ToString @Getter public class ElectrumOnChainTransactionResponse implements Transaction { @Json(name = "bc_balance") @@ -50,7 +55,12 @@ public class ElectrumOnChainTransactionResponse implements Transaction { private Integer txPosInBlock; @Override - public double getAmount() { - return Double.parseDouble(bcValue); + public Coin getAmount() { + return Coin.parseBtc(bcValue); + } + + @Override + public Date getDate() { + return timestamp != null ? new Date(timestamp * 1000L) : new Date(0); } } diff --git a/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumBasicIntegrationTests.java b/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumBasicIntegrationTests.java index 5aaecda748..d452be05d8 100644 --- a/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumBasicIntegrationTests.java +++ b/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumBasicIntegrationTests.java @@ -25,6 +25,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import java.util.Optional; + import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(ElectrumExtension.class) @@ -49,7 +51,7 @@ void getBalanceTest() { @Test void getSeedTest() { - String seed = electrumDaemon.getSeed(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE); + String seed = electrumDaemon.getSeed(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE)); String expectedSeed = electrumRegtestSetup.getWalletInfo().getResult().getSeed(); assertThat(seed).isEqualTo(expectedSeed); } @@ -64,7 +66,7 @@ void getUnusedAddressTest() { void signAndVerifyMessageTest() { String address = electrumDaemon.getUnusedAddress(); String message = "My proof that I own " + address; - String signature = electrumDaemon.signMessage(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE, address, message); + String signature = electrumDaemon.signMessage(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE), address, message); boolean isValid = electrumDaemon.verifyMessage(address, signature, message); assertThat(isValid).isTrue(); diff --git a/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumSendIntegrationTests.java b/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumSendIntegrationTests.java index 8b2c0276bd..96bfec3dc6 100644 --- a/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumSendIntegrationTests.java +++ b/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumSendIntegrationTests.java @@ -31,6 +31,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import java.util.Optional; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -85,8 +86,8 @@ void sendBtcTest() throws InterruptedException { double balanceBefore = minerWallet.getBalance(); String receiverAddress = minerWallet.getNewAddress(AddressType.BECH32, ""); - String unsignedTx = electrumDaemon.payTo(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE, receiverAddress, 5); - String signedTx = electrumDaemon.signTransaction(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE, unsignedTx); + String unsignedTx = electrumDaemon.payTo(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE), receiverAddress, 5); + String signedTx = electrumDaemon.signTransaction(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE), unsignedTx); String txId = electrumDaemon.broadcast(signedTx); assertThat(txId).isNotEmpty(); diff --git a/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumSetupIntegrationTests.java b/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumSetupIntegrationTests.java index c8b7fe0c42..4a71eebb93 100644 --- a/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumSetupIntegrationTests.java +++ b/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumSetupIntegrationTests.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -58,7 +59,7 @@ void afterAll() { @Test void createAndLoadWalletTest() { - ElectrumCreateResponse createResponse = electrumDaemon.create(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE); + ElectrumCreateResponse createResponse = electrumDaemon.create(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE)); Path electrumDataDir = electrumRegtestSetup.getElectrumDataDir(); String absoluteDataDirPath = electrumDataDir.toAbsolutePath().toString(); @@ -67,7 +68,7 @@ void createAndLoadWalletTest() { String[] seedWords = createResponse.getResult().getSeed().split(" "); assertThat(seedWords.length).isEqualTo(12); - electrumDaemon.loadWallet(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE); + electrumDaemon.loadWallet(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE)); } @Test diff --git a/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumTxAndPasswordIntegrationTests.java b/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumTxAndPasswordIntegrationTests.java index fa01a09d6c..4e3fadc2bd 100644 --- a/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumTxAndPasswordIntegrationTests.java +++ b/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumTxAndPasswordIntegrationTests.java @@ -35,6 +35,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.util.List; +import java.util.Optional; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -64,16 +65,16 @@ void setUp() { @Test void changePasswordTest() { - String expectedSeed = electrumDaemon.getSeed(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE); + String expectedSeed = electrumDaemon.getSeed(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE)); String newPassword = "My new password."; - electrumDaemon.password(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE, newPassword); + electrumDaemon.password(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE), newPassword); - String seed = electrumDaemon.getSeed(newPassword); + String seed = electrumDaemon.getSeed(Optional.of(newPassword)); assertThat(seed).isEqualTo(expectedSeed); // Change back otherwise other tests could fail. - electrumDaemon.password(newPassword, MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE); + electrumDaemon.password(Optional.of(newPassword), MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE); } @Test @@ -147,8 +148,8 @@ private void fundElectrumWallet() throws InterruptedException { BitcoindWallet minerWallet = remoteBitcoind.getMinerWallet(); String receiverAddress = minerWallet.getNewAddress(AddressType.BECH32, ""); - String unsignedTx = electrumDaemon.payTo(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE, receiverAddress, 5); - String signedTx = electrumDaemon.signTransaction(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE, unsignedTx); + String unsignedTx = electrumDaemon.payTo(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE), receiverAddress, 5); + String signedTx = electrumDaemon.signTransaction(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE), unsignedTx); electrumDaemon.broadcast(signedTx); electrumNotifyWebServer.stopServer(); diff --git a/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumUnconfirmedSendIntegrationTests.java b/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumUnconfirmedSendIntegrationTests.java index a5029ffe89..27790cd810 100644 --- a/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumUnconfirmedSendIntegrationTests.java +++ b/wallets/electrum/src/test/java/bisq/wallets/electrum/ElectrumUnconfirmedSendIntegrationTests.java @@ -32,6 +32,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -91,8 +92,8 @@ void unconfirmedBalanceTest() throws InterruptedException { addressToLatchMap.put(newAddress, electrumTxLatch); electrumDaemon.notify(newAddress, electrumNotifyWebServer.getNotifyEndpointUrl()); - String unsignedTx = electrumDaemon.payTo(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE, newAddress, 5); - String signedTx = electrumDaemon.signTransaction(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE, unsignedTx); + String unsignedTx = electrumDaemon.payTo(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE), newAddress, 5); + String signedTx = electrumDaemon.signTransaction(Optional.of(MacLinuxElectrumRegtestSetup.WALLET_PASSPHRASE), unsignedTx); String txId = electrumDaemon.broadcast(signedTx); assertThat(txId).isNotEmpty(); diff --git a/wallets/electrum/src/test/java/bisq/wallets/electrum/regtest/electrum/ElectrumRegtest.java b/wallets/electrum/src/test/java/bisq/wallets/electrum/regtest/electrum/ElectrumRegtest.java index 9ed96ccebe..1c1b9c094e 100644 --- a/wallets/electrum/src/test/java/bisq/wallets/electrum/regtest/electrum/ElectrumRegtest.java +++ b/wallets/electrum/src/test/java/bisq/wallets/electrum/regtest/electrum/ElectrumRegtest.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.Optional; public class ElectrumRegtest implements BisqProcess { @@ -56,8 +57,8 @@ public void start() { electrumDaemon = electrumProcess.getElectrumDaemon(); if (doCreateWallet) { - walletInfo = electrumDaemon.create(AbstractRegtestSetup.WALLET_PASSPHRASE); - electrumDaemon.loadWallet(AbstractRegtestSetup.WALLET_PASSPHRASE); + walletInfo = electrumDaemon.create(Optional.of(AbstractRegtestSetup.WALLET_PASSPHRASE)); + electrumDaemon.loadWallet(Optional.of(AbstractRegtestSetup.WALLET_PASSPHRASE)); } } diff --git a/wallets/elementsd/src/test/java/bisq/wallets/elementsd/ElementsdSendAndListTxsIntegrationTests.java b/wallets/elementsd/src/test/java/bisq/wallets/elementsd/ElementsdSendAndListTxsIntegrationTests.java index 3ff711cb9e..7249c3c096 100644 --- a/wallets/elementsd/src/test/java/bisq/wallets/elementsd/ElementsdSendAndListTxsIntegrationTests.java +++ b/wallets/elementsd/src/test/java/bisq/wallets/elementsd/ElementsdSendAndListTxsIntegrationTests.java @@ -51,7 +51,7 @@ public void sendLBtcAndListTxs() throws MalformedURLException, InterruptedExcept ElementsdListTransactionsResponse.Entry firstTx = txs.get(0); assertEquals(firstTxId, firstTx.getTxId()); assertEquals("receive", firstTx.getCategory()); - assertEquals(1, firstTx.getAmount()); + assertEquals(100000000, firstTx.getAmount().getValue()); assertEquals(1, firstTx.getConfirmations()); assertEquals(3, firstTx.getBlockheight()); assertEquals(0, firstTx.getWalletconflicts().length); @@ -60,7 +60,7 @@ public void sendLBtcAndListTxs() throws MalformedURLException, InterruptedExcept ElementsdListTransactionsResponse.Entry secondTx = txs.get(1); assertEquals(secondTxId, secondTx.getTxId()); assertEquals("receive", secondTx.getCategory()); - assertEquals(1, secondTx.getAmount()); + assertEquals(100000000, secondTx.getAmount().getValue()); assertEquals(1, secondTx.getConfirmations()); assertEquals(3, secondTx.getBlockheight()); assertEquals(0, secondTx.getWalletconflicts().length); @@ -69,7 +69,7 @@ public void sendLBtcAndListTxs() throws MalformedURLException, InterruptedExcept ElementsdListTransactionsResponse.Entry thirdTx = txs.get(2); assertEquals(thirdTxId, thirdTx.getTxId()); assertEquals("receive", thirdTx.getCategory()); - assertEquals(1, thirdTx.getAmount()); + assertEquals(100000000, thirdTx.getAmount().getValue()); assertEquals(1, thirdTx.getConfirmations()); assertEquals(3, thirdTx.getBlockheight()); assertEquals(0, thirdTx.getWalletconflicts().length);