mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-03-15 10:26:37 -04:00
Add new Take offer screen
This commit is contained in:
parent
e04ed033e0
commit
30751b017b
@ -187,7 +187,7 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
icon.setId("image-alert-round");
|
||||
final Button alertButton = new Button("", icon);
|
||||
alertButton.setId("nav-alert-button");
|
||||
alertButton.relocate(36, 19);
|
||||
alertButton.relocate(30, 9);
|
||||
alertButton.setOnAction((e) ->
|
||||
navigation.navigationTo(Navigation.Item.MAIN,
|
||||
Navigation.Item.ORDERS,
|
||||
|
@ -30,6 +30,7 @@ import java.util.ResourceBundle;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.*;
|
||||
@ -41,10 +42,11 @@ class AccountViewCB extends CachedViewCB<AccountPM> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AccountViewCB.class);
|
||||
|
||||
Tab tab;
|
||||
private Navigation navigation;
|
||||
private Navigation.Listener listener;
|
||||
|
||||
@FXML Tab tab;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
|
@ -40,9 +40,9 @@ class ChangePasswordViewCB extends CachedViewCB<ChangePasswordPM> implements Con
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ChangePasswordViewCB.class);
|
||||
|
||||
@FXML private HBox buttonsHBox;
|
||||
@FXML private Button saveButton, skipButton;
|
||||
@FXML private PasswordField passwordField, repeatedPasswordField;
|
||||
@FXML HBox buttonsHBox;
|
||||
@FXML Button saveButton, skipButton;
|
||||
@FXML PasswordField passwordField, repeatedPasswordField;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -56,14 +56,14 @@ public class FiatAccountViewCB extends CachedViewCB<FiatAccountPm> implements Co
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(FiatAccountViewCB.class);
|
||||
|
||||
@FXML private HBox buttonsHBox;
|
||||
@FXML private ComboBox<Region> regionComboBox;
|
||||
@FXML private ComboBox<Country> countryComboBox;
|
||||
@FXML private InputTextField titleTextField, holderNameTextField, primaryIDTextField, secondaryIDTextField;
|
||||
@FXML private Button saveButton, completedButton, removeBankAccountButton;
|
||||
@FXML private ComboBox<BankAccount> selectionComboBox;
|
||||
@FXML private ComboBox<BankAccountType> typesComboBox;
|
||||
@FXML private ComboBox<Currency> currencyComboBox;
|
||||
@FXML HBox buttonsHBox;
|
||||
@FXML ComboBox<Region> regionComboBox;
|
||||
@FXML ComboBox<Country> countryComboBox;
|
||||
@FXML InputTextField titleTextField, holderNameTextField, primaryIDTextField, secondaryIDTextField;
|
||||
@FXML Button saveButton, completedButton, removeBankAccountButton;
|
||||
@FXML ComboBox<BankAccount> selectionComboBox;
|
||||
@FXML ComboBox<BankAccountType> typesComboBox;
|
||||
@FXML ComboBox<Currency> currencyComboBox;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -40,9 +40,9 @@ public class PasswordViewCB extends CachedViewCB<PasswordPM> implements ContextA
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(PasswordViewCB.class);
|
||||
|
||||
@FXML private HBox buttonsHBox;
|
||||
@FXML private Button saveButton, skipButton;
|
||||
@FXML private PasswordField oldPasswordField, passwordField, repeatedPasswordField;
|
||||
@FXML HBox buttonsHBox;
|
||||
@FXML Button saveButton, skipButton;
|
||||
@FXML PasswordField oldPasswordField, passwordField, repeatedPasswordField;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -55,10 +55,10 @@ public class RegistrationViewCB extends CachedViewCB<RegistrationPM> implements
|
||||
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@FXML private TextField feeTextField;
|
||||
@FXML private AddressTextField addressTextField;
|
||||
@FXML private BalanceTextField balanceTextField;
|
||||
@FXML private Button payButton;
|
||||
@FXML TextField feeTextField;
|
||||
@FXML AddressTextField addressTextField;
|
||||
@FXML BalanceTextField balanceTextField;
|
||||
@FXML Button payButton;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -57,11 +57,11 @@ public class RestrictionsViewCB extends CachedViewCB<RestrictionsPM> implements
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RestrictionsViewCB.class);
|
||||
|
||||
@FXML private ListView languagesListView, countriesListView, arbitratorsListView;
|
||||
@FXML private ComboBox<Locale> languageComboBox;
|
||||
@FXML private ComboBox<Region> regionComboBox;
|
||||
@FXML private ComboBox<Country> countryComboBox;
|
||||
@FXML private Button completedButton, addAllEuroCountriesButton;
|
||||
@FXML ListView languagesListView, countriesListView, arbitratorsListView;
|
||||
@FXML ComboBox<Locale> languageComboBox;
|
||||
@FXML ComboBox<Region> regionComboBox;
|
||||
@FXML ComboBox<Country> countryComboBox;
|
||||
@FXML Button completedButton, addAllEuroCountriesButton;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -40,8 +40,8 @@ public class SeedWordsViewCB extends CachedViewCB<SeedWordsPM> implements Contex
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SeedWordsViewCB.class);
|
||||
|
||||
@FXML private Button completedButton;
|
||||
@FXML private TextArea seedWordsTextArea;
|
||||
@FXML Button completedButton;
|
||||
@FXML TextArea seedWordsTextArea;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -65,8 +65,8 @@ public class ArbitratorBrowserController extends CachedViewController implements
|
||||
private ArbitratorProfileController arbitratorProfileController;
|
||||
private int index = -1;
|
||||
|
||||
@FXML private Button prevButton, nextButton, selectButton, closeButton;
|
||||
@FXML private Pane arbitratorProfile;
|
||||
@FXML Button prevButton, nextButton, selectButton, closeButton;
|
||||
@FXML Pane arbitratorProfile;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
|
@ -43,11 +43,11 @@ public class ArbitratorProfileController extends CachedViewController {
|
||||
private Arbitrator arbitrator;
|
||||
|
||||
|
||||
@FXML private Label nameLabel;
|
||||
@FXML private TextField nameTextField, languagesTextField, reputationTextField, maxTradeVolumeTextField,
|
||||
@FXML Label nameLabel;
|
||||
@FXML TextField nameTextField, languagesTextField, reputationTextField, maxTradeVolumeTextField,
|
||||
passiveServiceFeeTextField, arbitrationFeeTextField, methodsTextField,
|
||||
idVerificationsTextField, webPageTextField;
|
||||
@FXML private TextArea descriptionTextArea;
|
||||
@FXML TextArea descriptionTextArea;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -85,20 +85,20 @@ public class ArbitratorRegistrationController extends CachedViewController {
|
||||
private Arbitrator.ID_TYPE idType;
|
||||
private ConfidenceDisplay confidenceDisplay;
|
||||
|
||||
@FXML private Accordion accordion;
|
||||
@FXML private TitledPane profileTitledPane, payCollateralTitledPane;
|
||||
@FXML private Button saveProfileButton, paymentDoneButton;
|
||||
@FXML private Label nameLabel, infoLabel, copyIcon, confirmationLabel;
|
||||
@FXML private ComboBox<Locale> languageComboBox;
|
||||
@FXML private ComboBox<Arbitrator.ID_TYPE> idTypeComboBox;
|
||||
@FXML private ComboBox<Arbitrator.METHOD> methodsComboBox;
|
||||
@FXML private ComboBox<Arbitrator.ID_VERIFICATION> idVerificationsComboBox;
|
||||
@FXML private TextField nameTextField, idTypeTextField, languagesTextField, maxTradeVolumeTextField,
|
||||
@FXML Accordion accordion;
|
||||
@FXML TitledPane profileTitledPane, payCollateralTitledPane;
|
||||
@FXML Button saveProfileButton, paymentDoneButton;
|
||||
@FXML Label nameLabel, infoLabel, copyIcon, confirmationLabel;
|
||||
@FXML ComboBox<Locale> languageComboBox;
|
||||
@FXML ComboBox<Arbitrator.ID_TYPE> idTypeComboBox;
|
||||
@FXML ComboBox<Arbitrator.METHOD> methodsComboBox;
|
||||
@FXML ComboBox<Arbitrator.ID_VERIFICATION> idVerificationsComboBox;
|
||||
@FXML TextField nameTextField, idTypeTextField, languagesTextField, maxTradeVolumeTextField,
|
||||
passiveServiceFeeTextField, minPassiveServiceFeeTextField, arbitrationFeeTextField,
|
||||
minArbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField,
|
||||
collateralAddressTextField, balanceTextField;
|
||||
@FXML private TextArea descriptionTextArea;
|
||||
@FXML private ConfidenceProgressIndicator progressIndicator;
|
||||
@FXML TextArea descriptionTextArea;
|
||||
@FXML ConfidenceProgressIndicator progressIndicator;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -50,8 +50,8 @@ public class DepositController extends CachedViewController {
|
||||
private final WalletFacade walletFacade;
|
||||
private ObservableList<DepositListItem> addressList;
|
||||
|
||||
@FXML private TableView<DepositListItem> tableView;
|
||||
@FXML private TableColumn<String, DepositListItem> labelColumn, addressColumn, balanceColumn, copyColumn,
|
||||
@FXML TableView<DepositListItem> tableView;
|
||||
@FXML TableColumn<String, DepositListItem> labelColumn, addressColumn, balanceColumn, copyColumn,
|
||||
confidenceColumn;
|
||||
|
||||
|
||||
|
@ -46,10 +46,10 @@ public class TransactionsController extends CachedViewController {
|
||||
private final WalletFacade walletFacade;
|
||||
private ObservableList<TransactionsListItem> transactionsListItems;
|
||||
|
||||
@FXML private TableView<TransactionsListItem> tableView;
|
||||
@FXML private TableColumn<String, TransactionsListItem> dateColumn, addressColumn, amountColumn, typeColumn,
|
||||
@FXML TableView<TransactionsListItem> tableView;
|
||||
@FXML TableColumn<String, TransactionsListItem> dateColumn, addressColumn, amountColumn, typeColumn,
|
||||
confidenceColumn;
|
||||
@FXML private Button addNewAddressButton;
|
||||
@FXML Button addNewAddressButton;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -65,11 +65,11 @@ public class WithdrawalController extends CachedViewController {
|
||||
private final WalletFacade walletFacade;
|
||||
private ObservableList<WithdrawalListItem> addressList;
|
||||
|
||||
@FXML private TableView<WithdrawalListItem> tableView;
|
||||
@FXML private TableColumn<String, WithdrawalListItem> labelColumn, addressColumn, balanceColumn, copyColumn,
|
||||
@FXML TableView<WithdrawalListItem> tableView;
|
||||
@FXML TableColumn<String, WithdrawalListItem> labelColumn, addressColumn, balanceColumn, copyColumn,
|
||||
confidenceColumn;
|
||||
@FXML private Button addNewAddressButton;
|
||||
@FXML private TextField withdrawFromTextField, withdrawToTextField, amountTextField, changeAddressTextField;
|
||||
@FXML Button addNewAddressButton;
|
||||
@FXML TextField withdrawFromTextField, withdrawToTextField, amountTextField, changeAddressTextField;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -21,6 +21,9 @@ public enum HelpId {
|
||||
CREATE_OFFER_GENERAL,
|
||||
CREATE_OFFER_FUNDING,
|
||||
CREATE_OFFER_ADVANCED,
|
||||
TAKE_OFFER_GENERAL,
|
||||
TAKE_OFFER_FUNDING,
|
||||
TAKE_OFFER_ADVANCED,
|
||||
SETUP_SEED_WORDS,
|
||||
SETUP_PASSWORD,
|
||||
SETUP_RESTRICTION_LANGUAGES,
|
||||
|
@ -48,9 +48,9 @@ public class OfferController extends CachedViewController {
|
||||
private final TradeManager tradeManager;
|
||||
private ObservableList<OfferListItem> offerListItems;
|
||||
|
||||
@FXML private TableColumn<String, OfferListItem> offerIdColumn, dateColumn, amountColumn, priceColumn,
|
||||
@FXML TableColumn<String, OfferListItem> offerIdColumn, dateColumn, amountColumn, priceColumn,
|
||||
volumeColumn, removeColumn;
|
||||
@FXML private TableView<OfferListItem> offerTable;
|
||||
@FXML TableView<OfferListItem> offerTable;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -80,17 +80,17 @@ public class PendingTradeController extends CachedViewController {
|
||||
|
||||
private ConfidenceDisplay confidenceDisplay;
|
||||
|
||||
@FXML private TableView openTradesTable;
|
||||
@FXML private TableColumn<String, PendingTradesListItem> directionColumn, countryColumn, bankAccountTypeColumn,
|
||||
@FXML TableView openTradesTable;
|
||||
@FXML TableColumn<String, PendingTradesListItem> directionColumn, countryColumn, bankAccountTypeColumn,
|
||||
priceColumn, amountColumn, volumeColumn, statusColumn, selectColumn;
|
||||
@FXML private ConfidenceProgressIndicator progressIndicator;
|
||||
@FXML private Label txTitleLabel, txHeaderLabel, confirmationLabel, txIDCopyIcon, holderNameCopyIcon,
|
||||
@FXML ConfidenceProgressIndicator progressIndicator;
|
||||
@FXML Label txTitleLabel, txHeaderLabel, confirmationLabel, txIDCopyIcon, holderNameCopyIcon,
|
||||
primaryBankAccountIDCopyIcon, secondaryBankAccountIDCopyIcon, bankAccountDetailsHeaderLabel,
|
||||
bankAccountTypeTitleLabel, holderNameTitleLabel, primaryBankAccountIDTitleLabel,
|
||||
secondaryBankAccountIDTitleLabel;
|
||||
@FXML private TextField txTextField, bankAccountTypeTextField, holderNameTextField, primaryBankAccountIDTextField,
|
||||
@FXML TextField txTextField, bankAccountTypeTextField, holderNameTextField, primaryBankAccountIDTextField,
|
||||
secondaryBankAccountIDTextField;
|
||||
@FXML private Button bankTransferInitedButton;
|
||||
@FXML Button bankTransferInitedButton;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -22,7 +22,7 @@ import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.main.trade.createoffer.CreateOfferViewCB;
|
||||
import io.bitsquare.gui.main.trade.orderbook.OrderBookViewCB;
|
||||
import io.bitsquare.gui.main.trade.takeoffer.TakeOfferController;
|
||||
import io.bitsquare.gui.main.trade.takeoffer.TakeOfferViewCB;
|
||||
import io.bitsquare.trade.Direction;
|
||||
import io.bitsquare.util.ViewLoader;
|
||||
|
||||
@ -48,8 +48,9 @@ public class TradeViewCB extends CachedViewCB {
|
||||
private final OrderBookInfo orderBookInfo = new OrderBookInfo();
|
||||
private OrderBookViewCB orderBookViewCB;
|
||||
private CreateOfferViewCB createOfferViewCB;
|
||||
private TakeOfferController takeOfferController;
|
||||
private TakeOfferViewCB takeOfferViewCB;
|
||||
private Node createOfferView;
|
||||
private Node takeOfferView;
|
||||
private Navigation navigation;
|
||||
private Navigation.Listener listener;
|
||||
private Navigation.Item navigationItem;
|
||||
@ -170,21 +171,21 @@ public class TradeViewCB extends CachedViewCB {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
else if (navigationItem == Navigation.Item.TAKE_OFFER && takeOfferController == null) {
|
||||
else if (navigationItem == Navigation.Item.TAKE_OFFER && takeOfferViewCB == null &&
|
||||
orderBookInfo.getOffer() != null) {
|
||||
// CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times
|
||||
// in different graphs
|
||||
ViewLoader loader = new ViewLoader(getClass().getResource(navigationItem.getFxmlUrl()), false);
|
||||
ViewLoader loader = new ViewLoader(getClass().getResource(Navigation.Item.TAKE_OFFER.getFxmlUrl()), false);
|
||||
try {
|
||||
final Parent view = loader.load();
|
||||
takeOfferController = loader.getController();
|
||||
takeOfferController.setParentController(this);
|
||||
takeOfferController.initWithData(orderBookInfo);
|
||||
takeOfferView = loader.load();
|
||||
takeOfferViewCB = loader.getController();
|
||||
takeOfferViewCB.setParent(this);
|
||||
takeOfferViewCB.initWithOrderBookInfo(orderBookInfo);
|
||||
final Tab tab = new Tab("Take offer");
|
||||
tab.setContent(view);
|
||||
tab.setContent(takeOfferView);
|
||||
tabPane.getTabs().add(tab);
|
||||
tabPane.getSelectionModel().select(tab);
|
||||
|
||||
return takeOfferController;
|
||||
return takeOfferViewCB;
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
@ -202,7 +203,7 @@ public class TradeViewCB extends CachedViewCB {
|
||||
|
||||
//TODO takeOfferController is not updated yet to new UI pattern
|
||||
public void onTakeOfferViewRemoved() {
|
||||
takeOfferController = null;
|
||||
takeOfferViewCB = null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,7 +64,7 @@ import static io.bitsquare.gui.util.BSFormatter.reduceTo4Decimals;
|
||||
* Note that the create offer domain has a deeper scope in the application domain (TradeManager).
|
||||
* That model is just responsible for the domain specific parts displayed needed in that UI element.
|
||||
*/
|
||||
public class CreateOfferModel extends UIModel {
|
||||
class CreateOfferModel extends UIModel {
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateOfferModel.class);
|
||||
|
||||
private final TradeManager tradeManager;
|
||||
|
@ -49,7 +49,7 @@ import org.slf4j.LoggerFactory;
|
||||
import static io.bitsquare.gui.util.BSFormatter.*;
|
||||
import static javafx.beans.binding.Bindings.createStringBinding;
|
||||
|
||||
public class CreateOfferPM extends PresentationModel<CreateOfferModel> {
|
||||
class CreateOfferPM extends PresentationModel<CreateOfferModel> {
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateOfferPM.class);
|
||||
|
||||
private final BtcValidator btcValidator;
|
||||
@ -154,7 +154,7 @@ public class CreateOfferPM extends PresentationModel<CreateOfferModel> {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// setOrderBookFilter is a one time call
|
||||
void setOrderBookFilter(@NotNull OrderBookInfo orderBookInfo) {
|
||||
void setOrderBookInfo(@NotNull OrderBookInfo orderBookInfo) {
|
||||
model.setDirection(orderBookInfo.getDirection());
|
||||
directionLabel.set(model.getDirection() == Direction.BUY ? BSResources.get("shared.buy") : BSResources.get
|
||||
("shared.sell"));
|
||||
@ -176,7 +176,7 @@ public class CreateOfferPM extends PresentationModel<CreateOfferModel> {
|
||||
// UI actions
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void onPlaceOffer() {
|
||||
void placeOffer() {
|
||||
model.requestPlaceOfferErrorMessage.set(null);
|
||||
model.requestPlaceOfferSuccess.set(false);
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
<!--suppress JavaFxUnresolvedFxIdReference -->
|
||||
<GridPane fx:id="gridPane" hgap="5.0" vgap="5.0">
|
||||
<padding>
|
||||
<padding>
|
||||
<Insets bottom="-10.0" left="25.0" top="30.0" right="25"/>
|
||||
</padding>
|
||||
|
||||
@ -196,20 +196,6 @@
|
||||
<TitledGroupBg fx:id="showDetailsPane" text="%createOffer.advancedBox.title" GridPane.columnSpan="3"
|
||||
GridPane.rowIndex="9" GridPane.rowSpan="7" visible="false"/>
|
||||
|
||||
<!-- <Pane fx:id="showDetailsPane" id="form-group-background-active" GridPane.columnSpan="3"
|
||||
GridPane.rowIndex="9" GridPane.rowSpan="7" visible="false">
|
||||
<GridPane.margin>
|
||||
<Insets right="-10" bottom="-10" left="-10" top="-10"/>
|
||||
</GridPane.margin>
|
||||
<Label fx:id="showDetailsTitleLabel" text="%createOffer.advancedBox.title" id="form-group-title-active"
|
||||
layoutX="8"
|
||||
layoutY="-8">
|
||||
<padding>
|
||||
<Insets left="5" right="7"/>
|
||||
</padding>
|
||||
</Label>
|
||||
</Pane> -->
|
||||
|
||||
<HBox GridPane.rowIndex="9" spacing="4" alignment="CENTER_RIGHT">
|
||||
<Label fx:id="acceptedCountriesLabel" text="%createOffer.advancedBox.countries" visible="false"/>
|
||||
<Label fx:id="acceptedCountriesLabelIcon" visible="false"/>
|
||||
|
@ -159,7 +159,7 @@ public class CreateOfferViewCB extends CachedViewCB<CreateOfferPM> {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void initWithOrderBookInfo(OrderBookInfo orderBookInfo) {
|
||||
presentationModel.setOrderBookFilter(orderBookInfo);
|
||||
presentationModel.setOrderBookInfo(orderBookInfo);
|
||||
|
||||
if (orderBookInfo.getDirection() == Direction.BUY)
|
||||
imageView.setId("image-buy-large");
|
||||
@ -177,7 +177,7 @@ public class CreateOfferViewCB extends CachedViewCB<CreateOfferPM> {
|
||||
|
||||
@FXML
|
||||
void onPlaceOffer() {
|
||||
presentationModel.onPlaceOffer();
|
||||
presentationModel.placeOffer();
|
||||
}
|
||||
|
||||
@FXML
|
||||
@ -360,8 +360,6 @@ public class CreateOfferViewCB extends CachedViewCB<CreateOfferPM> {
|
||||
priceFiatLabel.textProperty().bind(presentationModel.fiatCode);
|
||||
volumeFiatLabel.textProperty().bind(presentationModel.fiatCode);
|
||||
minAmountBtcLabel.textProperty().bind(presentationModel.btcCode);
|
||||
priceDescriptionLabel.textProperty().bind(presentationModel.fiatCode);
|
||||
volumeDescriptionLabel.textProperty().bind(presentationModel.fiatCode);//Price per Bitcoin in EUR
|
||||
|
||||
priceDescriptionLabel.textProperty().bind(createStringBinding(() ->
|
||||
BSResources.get("createOffer.amountPriceBox.priceDescription",
|
||||
@ -402,7 +400,6 @@ public class CreateOfferViewCB extends CachedViewCB<CreateOfferPM> {
|
||||
// buttons
|
||||
placeOfferButton.visibleProperty().bind(presentationModel.isPlaceOfferButtonVisible);
|
||||
placeOfferButton.disableProperty().bind(presentationModel.isPlaceOfferButtonDisabled);
|
||||
// closeButton.visibleProperty().bind(presentationModel.isCloseButtonVisible);
|
||||
}
|
||||
|
||||
private void showDetailsScreen() {
|
||||
@ -459,7 +456,6 @@ public class CreateOfferViewCB extends CachedViewCB<CreateOfferPM> {
|
||||
}
|
||||
|
||||
private void initEditIcons() {
|
||||
advancedScreenInited = true;
|
||||
acceptedCountriesLabelIcon.setId("clickable-icon");
|
||||
AwesomeDude.setIcon(acceptedCountriesLabelIcon, AwesomeIcon.EDIT_SIGN);
|
||||
Tooltip.install(acceptedCountriesLabelIcon, new Tooltip(BSResources.get("shared.openSettings")));
|
||||
|
@ -1,337 +0,0 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.trade.takeoffer;
|
||||
|
||||
import io.bitsquare.btc.AddressEntry;
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.gui.CachedViewController;
|
||||
import io.bitsquare.gui.components.Popups;
|
||||
import io.bitsquare.gui.components.ValidatedTextField;
|
||||
import io.bitsquare.gui.main.trade.OrderBookInfo;
|
||||
import io.bitsquare.gui.main.trade.TradeViewCB;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.BitSquareValidator;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferProtocol;
|
||||
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferProtocolListener;
|
||||
|
||||
import com.google.bitcoin.core.Coin;
|
||||
import com.google.bitcoin.utils.Fiat;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.*;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TakeOfferController extends CachedViewController {
|
||||
private static final Logger log = LoggerFactory.getLogger(TakeOfferController.class);
|
||||
|
||||
private final TradeManager tradeManager;
|
||||
private final WalletFacade walletFacade;
|
||||
|
||||
|
||||
private Offer offer;
|
||||
private Coin requestedAmount;
|
||||
private String tradeId;
|
||||
private String depositTxId;
|
||||
|
||||
@FXML private Accordion accordion;
|
||||
@FXML private TitledPane takeOfferTitledPane, waitBankTxTitledPane, summaryTitledPane;
|
||||
@FXML private ValidatedTextField amountTextField;
|
||||
@FXML private TextField priceTextField, volumeTextField, collateralTextField, feeTextField, totalTextField,
|
||||
bankAccountTypeTextField, countryTextField, arbitratorsTextField,
|
||||
supportedLanguagesTextField, supportedCountriesTextField, depositTxIdTextField, summaryPaidTextField,
|
||||
summaryReceivedTextField, summaryFeesTextField, summaryCollateralTextField,
|
||||
summaryDepositTxIdTextField, summaryPayoutTxIdTextField;
|
||||
@FXML private Label infoLabel, headLineLabel, collateralLabel;
|
||||
@FXML private Button takeOfferButton, receivedFiatButton;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private TakeOfferController(TradeManager tradeManager, WalletFacade walletFacade) {
|
||||
this.tradeManager = tradeManager;
|
||||
this.walletFacade = walletFacade;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
super.initialize(url, rb);
|
||||
|
||||
accordion.setExpandedPane(takeOfferTitledPane);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
((TradeViewCB) parentController).onTakeOfferViewRemoved();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
super.activate();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void initWithData(OrderBookInfo orderBookInfo) {
|
||||
this.offer = orderBookInfo.getOffer();
|
||||
if (orderBookInfo.getAmount() != null && !orderBookInfo.getAmount().isZero())
|
||||
requestedAmount = orderBookInfo.getAmount();
|
||||
else
|
||||
requestedAmount = offer.getAmount();
|
||||
|
||||
if (amountTextField != null) {
|
||||
applyData();
|
||||
}
|
||||
}
|
||||
|
||||
public void applyData() {
|
||||
amountTextField.setText(requestedAmount.toPlainString());
|
||||
amountTextField.setPromptText(BSFormatter.formatCoinWithCode(
|
||||
offer.getMinAmount()) + " - " + BSFormatter.formatCoinWithCode(offer.getAmount()));
|
||||
priceTextField.setText(BSFormatter.formatFiat(offer.getPrice()));
|
||||
applyVolume();
|
||||
collateralLabel.setText("Collateral (" + getCollateralAsPercent() + "):");
|
||||
applyCollateral();
|
||||
applyTotal();
|
||||
feeTextField.setText(BSFormatter.formatCoinWithCode(getFee()));
|
||||
totalTextField.setText(getFormattedTotal());
|
||||
|
||||
bankAccountTypeTextField.setText(offer.getBankAccountType().toString());
|
||||
countryTextField.setText(offer.getBankAccountCountry().getName());
|
||||
|
||||
//todo list
|
||||
// arbitratorsTextField.setText(offer.getArbitrator().getName());
|
||||
|
||||
supportedLanguagesTextField.setText(BSFormatter.languageLocalesToString(
|
||||
offer.getAcceptedLanguageLocales()));
|
||||
supportedCountriesTextField.setText(BSFormatter.countryLocalesToString(offer.getAcceptedCountries()));
|
||||
|
||||
amountTextField.textProperty().addListener(e -> {
|
||||
applyVolume();
|
||||
applyCollateral();
|
||||
applyTotal();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GUI handlers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@FXML
|
||||
public void onTakeOffer() {
|
||||
AddressEntry addressEntry = walletFacade.getAddressInfoByTradeID(offer.getId());
|
||||
Coin amount = BSFormatter.parseToCoin(getAmountString());
|
||||
// TODO more validation (fee payment, blacklist,...)
|
||||
if (amountTextField.isInvalid()) {
|
||||
Popups.openErrorPopup("Invalid input", "The requested amount you entered is not a valid amount.");
|
||||
}
|
||||
else if (BitSquareValidator.tradeAmountOutOfRange(amount, offer)) {
|
||||
Popups.openErrorPopup(
|
||||
"Invalid input", "The requested amount you entered is outside of the range of the offered amount.");
|
||||
}
|
||||
else if (addressEntry == null ||
|
||||
getTotal().compareTo(walletFacade.getBalanceForAddress(addressEntry.getAddress())) > 0) {
|
||||
Popups.openErrorPopup("Insufficient money", "You don't have enough funds for that trade.");
|
||||
}
|
||||
else if (tradeManager.isOfferAlreadyInTrades(offer)) {
|
||||
Popups.openErrorPopup("Offer previously accepted",
|
||||
"You have that offer already taken. Open the offer section to find that trade.");
|
||||
}
|
||||
else {
|
||||
takeOfferButton.setDisable(true);
|
||||
amountTextField.setEditable(false);
|
||||
tradeManager.takeOffer(amount, offer, new SellerTakesOfferProtocolListener() {
|
||||
@Override
|
||||
public void onDepositTxPublished(String depositTxId) {
|
||||
setDepositTxId(depositTxId);
|
||||
accordion.setExpandedPane(waitBankTxTitledPane);
|
||||
infoLabel.setText("Deposit transaction published by offerer.\n" +
|
||||
"As soon as the offerer starts the \n" +
|
||||
"Bank transfer, you will be informed.");
|
||||
depositTxIdTextField.setText(depositTxId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBankTransferInited(String tradeId) {
|
||||
setTradeId(tradeId);
|
||||
headLineLabel.setText("Bank transfer initiated");
|
||||
infoLabel.setText("Check your bank account and continue \n" + "when you have received the money.");
|
||||
receivedFiatButton.setDisable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPayoutTxPublished(Trade trade, String payoutTxId) {
|
||||
accordion.setExpandedPane(summaryTitledPane);
|
||||
|
||||
summaryPaidTextField.setText(BSFormatter.formatCoinWithCode(trade.getTradeAmount()));
|
||||
summaryReceivedTextField.setText(BSFormatter.formatFiat(trade.getTradeVolume()));
|
||||
summaryFeesTextField.setText(BSFormatter.formatCoinWithCode(
|
||||
FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE)));
|
||||
summaryCollateralTextField.setText(BSFormatter.formatCoinWithCode(
|
||||
trade.getCollateralAmount()));
|
||||
summaryDepositTxIdTextField.setText(depositTxId);
|
||||
summaryPayoutTxIdTextField.setText(payoutTxId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(Throwable throwable, SellerTakesOfferProtocol.State state) {
|
||||
log.error("Error while executing trade process at state: " + state + " / " + throwable);
|
||||
Popups.openErrorPopup("Error while executing trade process",
|
||||
"Error while executing trade process at state: " + state + " / " + throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWaitingForPeerResponse(SellerTakesOfferProtocol.State state) {
|
||||
log.debug("Waiting for peers response at state " + state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted(SellerTakesOfferProtocol.State state) {
|
||||
log.debug("Trade protocol completed at state " + state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTakeOfferRequestRejected(Trade trade) {
|
||||
log.error("Take offer request rejected");
|
||||
Popups.openErrorPopup("Take offer request rejected",
|
||||
"Your take offer request has been rejected. It might be that the offerer got another " +
|
||||
"request shortly before your request arrived.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FXML
|
||||
public void onReceivedFiat() {
|
||||
tradeManager.onFiatReceived(tradeId);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onClose() {
|
||||
TabPane tabPane = ((TabPane) (root.getParent().getParent()));
|
||||
tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
private void applyCollateral() {
|
||||
collateralTextField.setText(getFormattedCollateralAsBtc());
|
||||
}
|
||||
|
||||
private void applyVolume() {
|
||||
volumeTextField.setText(getFormattedVolume());
|
||||
}
|
||||
|
||||
private void applyTotal() {
|
||||
totalTextField.setText(getFormattedTotal());
|
||||
}
|
||||
|
||||
// formatted
|
||||
private String getFormattedVolume() {
|
||||
return BSFormatter.formatFiat(getVolume());
|
||||
}
|
||||
|
||||
private String getFormattedTotal() {
|
||||
return BSFormatter.formatCoinWithCode(getTotal());
|
||||
}
|
||||
|
||||
|
||||
// values
|
||||
private double getAmountAsDouble() {
|
||||
return BSFormatter.parseToDouble(getAmountString());
|
||||
}
|
||||
|
||||
private Coin getAmountInSatoshis() {
|
||||
return BSFormatter.parseToCoin(getAmountString());
|
||||
}
|
||||
|
||||
private String getAmountString() {
|
||||
try {
|
||||
BitSquareValidator.textFieldsHasPositiveDoubleValueWithReset(amountTextField);
|
||||
return amountTextField.getText();
|
||||
} catch (BitSquareValidator.ValidationException e) {
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
||||
private Fiat getVolume() {
|
||||
//TODO
|
||||
return Fiat.valueOf("EUR", (long) (offer.getPrice().longValue() * getAmountAsDouble()));
|
||||
}
|
||||
|
||||
private Coin getFee() {
|
||||
return FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE);
|
||||
}
|
||||
|
||||
private Coin getTotal() {
|
||||
return getFee().add(getAmountInSatoshis()).add(getCollateralAsCoin());
|
||||
}
|
||||
|
||||
private Coin getCollateralAsCoin() {
|
||||
Coin amountAsCoin = BSFormatter.parseToCoin(getAmountString());
|
||||
return amountAsCoin.multiply(getCollateral()).divide(1000L);
|
||||
}
|
||||
|
||||
private String getFormattedCollateralAsBtc() {
|
||||
return BSFormatter.formatCoin(getCollateralAsCoin());
|
||||
}
|
||||
|
||||
private String getCollateralAsPercent() {
|
||||
return BSFormatter.formatCollateralPercent(getCollateral());
|
||||
}
|
||||
|
||||
private long getCollateral() {
|
||||
return offer.getCollateral();
|
||||
}
|
||||
|
||||
public void setTradeId(String tradeId) {
|
||||
this.tradeId = tradeId;
|
||||
}
|
||||
|
||||
public void setDepositTxId(String depositTxId) {
|
||||
this.depositTxId = depositTxId;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.trade.takeoffer;
|
||||
|
||||
import io.bitsquare.btc.AddressEntry;
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.btc.listeners.BalanceListener;
|
||||
import io.bitsquare.gui.UIModel;
|
||||
import io.bitsquare.gui.main.trade.OrderBookInfo;
|
||||
import io.bitsquare.settings.Settings;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferProtocol;
|
||||
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferProtocolListener;
|
||||
|
||||
import com.google.bitcoin.core.Coin;
|
||||
import com.google.bitcoin.utils.ExchangeRate;
|
||||
import com.google.bitcoin.utils.Fiat;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Domain for that UI element.
|
||||
* Note that the create offer domain has a deeper scope in the application domain (TradeManager).
|
||||
* That model is just responsible for the domain specific parts displayed needed in that UI element.
|
||||
*/
|
||||
class TakeOfferModel extends UIModel {
|
||||
private static final Logger log = LoggerFactory.getLogger(TakeOfferModel.class);
|
||||
|
||||
private final TradeManager tradeManager;
|
||||
private final WalletFacade walletFacade;
|
||||
private final Settings settings;
|
||||
|
||||
private OrderBookInfo orderBookInfo;
|
||||
private AddressEntry addressEntry;
|
||||
|
||||
final StringProperty requestTakeOfferErrorMessage = new SimpleStringProperty();
|
||||
final StringProperty transactionId = new SimpleStringProperty();
|
||||
final StringProperty btcCode = new SimpleStringProperty();
|
||||
|
||||
final BooleanProperty requestTakeOfferSuccess = new SimpleBooleanProperty();
|
||||
final BooleanProperty isWalletFunded = new SimpleBooleanProperty();
|
||||
final BooleanProperty useMBTC = new SimpleBooleanProperty();
|
||||
|
||||
final ObjectProperty<Coin> amountAsCoin = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Coin> minAmountAsCoin = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Fiat> priceAsFiat = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Fiat> volumeAsFiat = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Coin> totalToPayAsCoin = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Coin> collateralAsCoin = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Coin> offerFeeAsCoin = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Coin> networkFeeAsCoin = new SimpleObjectProperty<>();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
TakeOfferModel(TradeManager tradeManager, WalletFacade walletFacade, Settings settings) {
|
||||
this.tradeManager = tradeManager;
|
||||
this.walletFacade = walletFacade;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
|
||||
offerFeeAsCoin.set(FeePolicy.CREATE_OFFER_FEE);
|
||||
networkFeeAsCoin.set(FeePolicy.TX_FEE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
super.activate();
|
||||
|
||||
btcCode.bind(settings.btcDenominationProperty());
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
@Override
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
|
||||
btcCode.unbind();
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
@Override
|
||||
public void terminate() {
|
||||
super.terminate();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void takeOffer() {
|
||||
// data validation is done in the trade domain
|
||||
/*tradeManager.requestPlaceOffer(orderBookInfo.getOffer().getId(),
|
||||
orderBookInfo.getOffer().getDirection(),
|
||||
priceAsFiat.get(),
|
||||
amountAsCoin.get(),
|
||||
minAmountAsCoin.get(),
|
||||
(transaction) -> {
|
||||
transactionId.set(transaction.getHashAsString());
|
||||
requestTakeOfferSuccess.set(true);
|
||||
},
|
||||
requestTakeOfferErrorMessage::set
|
||||
);*/
|
||||
SellerTakesOfferProtocolListener listener = new SellerTakesOfferProtocolListener() {
|
||||
@Override
|
||||
public void onDepositTxPublished(String depositTxId) {
|
||||
transactionId.set(depositTxId);
|
||||
requestTakeOfferSuccess.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBankTransferInited(String tradeId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPayoutTxPublished(Trade trade, String hashAsString) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(Throwable throwable, SellerTakesOfferProtocol.State state) {
|
||||
requestTakeOfferErrorMessage.set("An error occurred. Error: " + throwable.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWaitingForPeerResponse(SellerTakesOfferProtocol.State state) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted(SellerTakesOfferProtocol.State state) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTakeOfferRequestRejected(Trade trade) {
|
||||
requestTakeOfferErrorMessage.set("Take offer request got rejected.");
|
||||
}
|
||||
};
|
||||
|
||||
tradeManager.takeOffer(amountAsCoin.get(), orderBookInfo.getOffer(), listener);
|
||||
/*new SellerTakesOfferProtocolListener() {
|
||||
@Override
|
||||
public void onDepositTxPublished(String depositTxId) {
|
||||
setDepositTxId(depositTxId);
|
||||
accordion.setExpandedPane(waitBankTxTitledPane);
|
||||
infoLabel.setText("Deposit transaction published by offerer.\n" +
|
||||
"As soon as the offerer starts the \n" +
|
||||
"Bank transfer, you will be informed.");
|
||||
depositTxIdTextField.setText(depositTxId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBankTransferInited(String tradeId) {
|
||||
setTradeId(tradeId);
|
||||
headLineLabel.setText("Bank transfer initiated");
|
||||
infoLabel.setText("Check your bank account and continue \n" + "when you have received the money.");
|
||||
receivedFiatButton.setDisable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPayoutTxPublished(Trade trade, String payoutTxId) {
|
||||
accordion.setExpandedPane(summaryTitledPane);
|
||||
|
||||
summaryPaidTextField.setText(BSFormatter.formatCoinWithCode(trade.getTradeAmount()));
|
||||
summaryReceivedTextField.setText(BSFormatter.formatFiat(trade.getTradeVolume()));
|
||||
summaryFeesTextField.setText(BSFormatter.formatCoinWithCode(
|
||||
FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE)));
|
||||
summaryCollateralTextField.setText(BSFormatter.formatCoinWithCode(
|
||||
trade.getCollateralAmount()));
|
||||
summaryDepositTxIdTextField.setText(depositTxId);
|
||||
summaryPayoutTxIdTextField.setText(payoutTxId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(Throwable throwable, SellerTakesOfferProtocol.State state) {
|
||||
log.error("Error while executing trade process at state: " + state + " / " + throwable);
|
||||
Popups.openErrorPopup("Error while executing trade process",
|
||||
"Error while executing trade process at state: " + state + " / " + throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWaitingForPeerResponse(SellerTakesOfferProtocol.State state) {
|
||||
log.debug("Waiting for peers response at state " + state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted(SellerTakesOfferProtocol.State state) {
|
||||
log.debug("Trade protocol completed at state " + state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTakeOfferRequestRejected(Trade trade) {
|
||||
log.error("Take offer request rejected");
|
||||
Popups.openErrorPopup("Take offer request rejected",
|
||||
"Your take offer request has been rejected. It might be that the offerer got another " +
|
||||
"request shortly before your request arrived.");
|
||||
}
|
||||
});*/
|
||||
|
||||
}
|
||||
|
||||
void calculateVolume() {
|
||||
try {
|
||||
if (priceAsFiat.get() != null &&
|
||||
amountAsCoin.get() != null &&
|
||||
!amountAsCoin.get().isZero() &&
|
||||
!priceAsFiat.get().isZero()) {
|
||||
volumeAsFiat.set(new ExchangeRate(priceAsFiat.get()).coinToFiat(amountAsCoin.get()));
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// Should be never reached
|
||||
log.error(t.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void calculateTotalToPay() {
|
||||
calculateCollateral();
|
||||
try {
|
||||
if (collateralAsCoin.get() != null) {
|
||||
totalToPayAsCoin.set(offerFeeAsCoin.get().add(amountAsCoin.get()).add(networkFeeAsCoin.get()).add
|
||||
(collateralAsCoin.get()));
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// Should be never reached
|
||||
log.error(t.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void calculateCollateral() {
|
||||
try {
|
||||
if (amountAsCoin.get() != null && orderBookInfo != null)
|
||||
collateralAsCoin.set(amountAsCoin.get().multiply(orderBookInfo.getOffer().getCollateral()).
|
||||
divide(1000L));
|
||||
} catch (Throwable t) {
|
||||
// The multiply might lead to too large numbers, we don't handle it but it should not break the app
|
||||
log.error(t.toString());
|
||||
}
|
||||
}
|
||||
|
||||
boolean isMinAmountLessOrEqualAmount() {
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (minAmountAsCoin.get() != null && amountAsCoin.get() != null)
|
||||
return !minAmountAsCoin.get().isGreaterThan(amountAsCoin.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setOrderBookInfo(@NotNull OrderBookInfo orderBookInfo) {
|
||||
this.orderBookInfo = orderBookInfo;
|
||||
addressEntry = walletFacade.getAddressInfoByTradeID(orderBookInfo.getOffer().getId());
|
||||
walletFacade.addBalanceListener(new BalanceListener(addressEntry.getAddress()) {
|
||||
@Override
|
||||
public void onBalanceChanged(@NotNull Coin balance) {
|
||||
updateBalance(balance);
|
||||
}
|
||||
});
|
||||
updateBalance(walletFacade.getBalanceForAddress(addressEntry.getAddress()));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WalletFacade getWalletFacade() {
|
||||
return walletFacade;
|
||||
}
|
||||
|
||||
AddressEntry getAddressEntry() {
|
||||
return addressEntry;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void updateBalance(@NotNull Coin balance) {
|
||||
isWalletFunded.set(totalToPayAsCoin.get() != null && balance.compareTo(totalToPayAsCoin.get()) >= 0);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,362 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.trade.takeoffer;
|
||||
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.gui.PresentationModel;
|
||||
import io.bitsquare.gui.main.trade.OrderBookInfo;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.validation.BtcValidator;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.trade.Direction;
|
||||
|
||||
import com.google.bitcoin.core.Address;
|
||||
import com.google.bitcoin.core.Coin;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static io.bitsquare.gui.util.BSFormatter.*;
|
||||
import static javafx.beans.binding.Bindings.createStringBinding;
|
||||
|
||||
class TakeOfferPM extends PresentationModel<TakeOfferModel> {
|
||||
private static final Logger log = LoggerFactory.getLogger(TakeOfferPM.class);
|
||||
|
||||
private String offerFee;
|
||||
private String networkFee;
|
||||
private String fiatCode;
|
||||
private String minAmount;
|
||||
private String price;
|
||||
private String directionLabel;
|
||||
private String collateralLabel;
|
||||
private String bankAccountType;
|
||||
private String bankAccountCurrency;
|
||||
private String bankAccountCounty;
|
||||
private String acceptedCountries;
|
||||
private String acceptedLanguages;
|
||||
private String acceptedArbitrators;
|
||||
private String addressAsString;
|
||||
private String paymentLabel;
|
||||
|
||||
// Needed for the addressTextField
|
||||
final ObjectProperty<Address> address = new SimpleObjectProperty<>();
|
||||
|
||||
private final BtcValidator btcValidator;
|
||||
|
||||
final StringProperty amount = new SimpleStringProperty();
|
||||
final StringProperty volume = new SimpleStringProperty();
|
||||
final StringProperty collateral = new SimpleStringProperty();
|
||||
final StringProperty totalToPay = new SimpleStringProperty();
|
||||
final StringProperty transactionId = new SimpleStringProperty();
|
||||
final StringProperty requestTakeOfferErrorMessage = new SimpleStringProperty();
|
||||
final StringProperty btcCode = new SimpleStringProperty();
|
||||
|
||||
|
||||
final BooleanProperty isTakeOfferButtonVisible = new SimpleBooleanProperty(false);
|
||||
final BooleanProperty isTakeOfferButtonDisabled = new SimpleBooleanProperty(true);
|
||||
final BooleanProperty showWarningInvalidBtcDecimalPlaces = new SimpleBooleanProperty();
|
||||
final BooleanProperty showTransactionPublishedScreen = new SimpleBooleanProperty();
|
||||
|
||||
final ObjectProperty<InputValidator.ValidationResult> amountValidationResult = new SimpleObjectProperty<>();
|
||||
|
||||
// Needed for the addressTextField
|
||||
final ObjectProperty<Coin> totalToPayAsCoin = new SimpleObjectProperty<>();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// non private for testing
|
||||
@Inject
|
||||
TakeOfferPM(TakeOfferModel model, BtcValidator btcValidator) {
|
||||
super(model);
|
||||
|
||||
this.btcValidator = btcValidator;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
|
||||
// static
|
||||
offerFee = formatCoinWithCode(model.offerFeeAsCoin.get());
|
||||
networkFee = formatCoinWithCode(model.networkFeeAsCoin.get());
|
||||
|
||||
setupBindings();
|
||||
setupListeners();
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
@Override
|
||||
public void activate() {
|
||||
super.activate();
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
@Override
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
@Override
|
||||
public void terminate() {
|
||||
super.terminate();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// setOrderBookFilter is a one time call
|
||||
void setOrderBookInfo(@NotNull OrderBookInfo orderBookInfo) {
|
||||
model.setOrderBookInfo(orderBookInfo);
|
||||
|
||||
directionLabel = orderBookInfo.getDirection() == Direction.BUY ?
|
||||
BSResources.get("shared.buy") : BSResources.get("shared.sell");
|
||||
|
||||
fiatCode = orderBookInfo.getOffer().getCurrency().getCurrencyCode();
|
||||
model.priceAsFiat.set(orderBookInfo.getOffer().getPrice());
|
||||
model.minAmountAsCoin.set(orderBookInfo.getOffer().getMinAmount());
|
||||
if (orderBookInfo.getAmount() != null &&
|
||||
isBtcInputValid(orderBookInfo.getAmount().toPlainString()).isValid &&
|
||||
!orderBookInfo.getAmount().isGreaterThan(orderBookInfo.getOffer().getAmount())) {
|
||||
model.amountAsCoin.set(orderBookInfo.getAmount());
|
||||
}
|
||||
else {
|
||||
model.amountAsCoin.set(orderBookInfo.getOffer().getAmount());
|
||||
}
|
||||
model.volumeAsFiat.set(orderBookInfo.getOffer().getVolumeByAmount(model.amountAsCoin.get()));
|
||||
|
||||
minAmount = BSFormatter.formatCoinWithCode(orderBookInfo.getOffer().getMinAmount());
|
||||
price = BSFormatter.formatFiatWithCode(orderBookInfo.getOffer().getPrice());
|
||||
|
||||
paymentLabel = BSResources.get("takeOffer.fundsBox.paymentLabel", orderBookInfo.getOffer().getId());
|
||||
if (model.getAddressEntry() != null) {
|
||||
addressAsString = model.getAddressEntry().getAddress().toString();
|
||||
address.set(model.getAddressEntry().getAddress());
|
||||
}
|
||||
collateralLabel = BSResources.get("takeOffer.fundsBox.collateral",
|
||||
BSFormatter.formatCollateralPercent(orderBookInfo.getOffer().getCollateral()));
|
||||
|
||||
acceptedCountries = BSFormatter.countryLocalesToString(orderBookInfo.getOffer().getAcceptedCountries());
|
||||
acceptedLanguages = BSFormatter.languageLocalesToString(orderBookInfo.getOffer().getAcceptedLanguageLocales());
|
||||
acceptedArbitrators = BSFormatter.arbitratorsToString(orderBookInfo.getOffer().getArbitrators());
|
||||
bankAccountType = BSResources.get(orderBookInfo.getOffer().getBankAccountType().toString());
|
||||
bankAccountCurrency = BSResources.get(orderBookInfo.getOffer().getCurrency().getDisplayName());
|
||||
bankAccountCounty = BSResources.get(orderBookInfo.getOffer().getBankAccountCountry().getName());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI actions
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void takeOffer() {
|
||||
model.requestTakeOfferErrorMessage.set(null);
|
||||
model.requestTakeOfferSuccess.set(false);
|
||||
|
||||
isTakeOfferButtonDisabled.set(true);
|
||||
|
||||
model.takeOffer();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI events
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void onShowPayFundsScreen() {
|
||||
isTakeOfferButtonVisible.set(true);
|
||||
}
|
||||
|
||||
// On focus out we do validation and apply the data to the model
|
||||
void onFocusOutAmountTextField(Boolean oldValue, Boolean newValue, String userInput) {
|
||||
if (oldValue && !newValue) {
|
||||
InputValidator.ValidationResult result = isBtcInputValid(amount.get());
|
||||
amountValidationResult.set(result);
|
||||
if (result.isValid) {
|
||||
showWarningInvalidBtcDecimalPlaces.set(!hasBtcValidDecimals(userInput));
|
||||
// only allow max 4 decimal places for btc values
|
||||
setAmountToModel();
|
||||
// reformat input
|
||||
amount.set(formatCoin(model.amountAsCoin.get()));
|
||||
|
||||
calculateVolume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WalletFacade getWalletFacade() {
|
||||
return model.getWalletFacade();
|
||||
}
|
||||
|
||||
String getOfferFee() {
|
||||
return offerFee;
|
||||
}
|
||||
|
||||
String getNetworkFee() {
|
||||
return networkFee;
|
||||
}
|
||||
|
||||
String getFiatCode() {
|
||||
return fiatCode;
|
||||
}
|
||||
|
||||
String getMinAmount() {
|
||||
return minAmount;
|
||||
}
|
||||
|
||||
String getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
String getDirectionLabel() {
|
||||
return directionLabel;
|
||||
}
|
||||
|
||||
String getCollateralLabel() {
|
||||
return collateralLabel;
|
||||
}
|
||||
|
||||
String getBankAccountType() {
|
||||
return bankAccountType;
|
||||
}
|
||||
|
||||
String getBankAccountCurrency() {
|
||||
return bankAccountCurrency;
|
||||
}
|
||||
|
||||
String getBankAccountCounty() {
|
||||
return bankAccountCounty;
|
||||
}
|
||||
|
||||
String getAcceptedCountries() {
|
||||
return acceptedCountries;
|
||||
}
|
||||
|
||||
String getAcceptedLanguages() {
|
||||
return acceptedLanguages;
|
||||
}
|
||||
|
||||
String getAcceptedArbitrators() {
|
||||
return acceptedArbitrators;
|
||||
}
|
||||
|
||||
String getAddressAsString() {
|
||||
return addressAsString;
|
||||
}
|
||||
|
||||
String getPaymentLabel() {
|
||||
return paymentLabel;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void setupListeners() {
|
||||
// Bidirectional bindings are used for all input fields: amount, price, volume and minAmount
|
||||
// We do volume/amount calculation during input, so user has immediate feedback
|
||||
amount.addListener((ov, oldValue, newValue) -> {
|
||||
if (isBtcInputValid(newValue).isValid) {
|
||||
setAmountToModel();
|
||||
calculateVolume();
|
||||
model.calculateTotalToPay();
|
||||
model.calculateCollateral();
|
||||
}
|
||||
validateInput();
|
||||
});
|
||||
|
||||
model.isWalletFunded.addListener((ov, oldValue, newValue) -> {
|
||||
if (newValue)
|
||||
validateInput();
|
||||
});
|
||||
|
||||
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding
|
||||
model.amountAsCoin.addListener((ov, oldValue, newValue) -> amount.set(formatCoin(newValue)));
|
||||
|
||||
model.requestTakeOfferErrorMessage.addListener((ov, oldValue, newValue) -> {
|
||||
if (newValue != null)
|
||||
isTakeOfferButtonDisabled.set(false);
|
||||
});
|
||||
model.requestTakeOfferSuccess.addListener((ov, oldValue, newValue) -> isTakeOfferButtonVisible.set
|
||||
(!newValue));
|
||||
}
|
||||
|
||||
private void setupBindings() {
|
||||
volume.bind(createStringBinding(() -> formatFiatWithCode(model.volumeAsFiat.get()), model.volumeAsFiat));
|
||||
totalToPay.bind(createStringBinding(() -> formatCoinWithCode(model.totalToPayAsCoin.get()),
|
||||
model.totalToPayAsCoin));
|
||||
collateral.bind(createStringBinding(() -> formatCoinWithCode(model.collateralAsCoin.get()),
|
||||
model.collateralAsCoin));
|
||||
|
||||
totalToPayAsCoin.bind(model.totalToPayAsCoin);
|
||||
|
||||
requestTakeOfferErrorMessage.bind(model.requestTakeOfferErrorMessage);
|
||||
showTransactionPublishedScreen.bind(model.requestTakeOfferSuccess);
|
||||
transactionId.bind(model.transactionId);
|
||||
|
||||
btcCode.bind(model.btcCode);
|
||||
}
|
||||
|
||||
private void calculateVolume() {
|
||||
setAmountToModel();
|
||||
model.calculateVolume();
|
||||
}
|
||||
|
||||
private void setAmountToModel() {
|
||||
model.amountAsCoin.set(parseToCoinWith4Decimals(amount.get()));
|
||||
}
|
||||
|
||||
private void validateInput() {
|
||||
isTakeOfferButtonDisabled.set(!(isBtcInputValid(amount.get()).isValid &&
|
||||
model.isMinAmountLessOrEqualAmount() &&
|
||||
model.isWalletFunded.get())
|
||||
);
|
||||
}
|
||||
|
||||
private InputValidator.ValidationResult isBtcInputValid(String input) {
|
||||
return btcValidator.validate(input);
|
||||
}
|
||||
}
|
@ -17,192 +17,248 @@
|
||||
~ along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<?import io.bitsquare.gui.components.ValidatedTextField?>
|
||||
<?import io.bitsquare.gui.components.btc.AddressTextField?>
|
||||
<?import io.bitsquare.gui.components.btc.BalanceTextField?>
|
||||
<?import io.bitsquare.gui.components.InfoDisplay?>
|
||||
<?import io.bitsquare.gui.components.InputTextField?>
|
||||
<?import io.bitsquare.gui.components.TitledGroupBg?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.image.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.trade.takeoffer.TakeOfferController"
|
||||
<?import javafx.scene.text.*?>
|
||||
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.main.trade.takeoffer.TakeOfferViewCB"
|
||||
AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0"
|
||||
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
||||
<Accordion fx:id="accordion" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0"
|
||||
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
|
||||
<panes>
|
||||
|
||||
<TitledPane fx:id="takeOfferTitledPane" text="Offer details">
|
||||
<ScrollPane fitToWidth="true">
|
||||
<GridPane hgap="5.0" vgap="5.0">
|
||||
<padding>
|
||||
<Insets left="10" right="10" top="10" bottom="10"/>
|
||||
</padding>
|
||||
<ScrollPane fx:id="scrollPane" hbarPolicy="NEVER" vbarPolicy="NEVER" fitToWidth="true" fitToHeight="true"
|
||||
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
|
||||
AnchorPane.bottomAnchor="0.0">
|
||||
|
||||
<Label text="Take offer:" id="form-header-text"/>
|
||||
<!--suppress JavaFxUnresolvedFxIdReference -->
|
||||
<GridPane fx:id="gridPane" hgap="5.0" vgap="5.0">
|
||||
<padding>
|
||||
<Insets bottom="-10.0" left="25.0" top="30.0" right="25"/>
|
||||
</padding>
|
||||
|
||||
<Label text="Amount in BTC:" GridPane.rowIndex="1"/>
|
||||
<ValidatedTextField fx:id="amountTextField" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
|
||||
<!--
|
||||
Amount/Price group
|
||||
-->
|
||||
<TitledGroupBg fx:id="priceAmountPane" text="%takeOffer.amountPriceBox.title"
|
||||
GridPane.rowSpan="3" GridPane.columnSpan="3"/>
|
||||
|
||||
<Label text="Price (EUR/BTC):" GridPane.rowIndex="2"/>
|
||||
<TextField fx:id="priceTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="2" GridPane.columnIndex="1"/>
|
||||
|
||||
<Label text="Amount in EUR:" GridPane.rowIndex="3"/>
|
||||
<TextField fx:id="volumeTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="3" GridPane.columnIndex="1"/>
|
||||
|
||||
<Label fx:id="collateralLabel" text="Collateral:" GridPane.rowIndex="4"/>
|
||||
<TextField fx:id="collateralTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="4" GridPane.columnIndex="1"/>
|
||||
|
||||
<Label text="Total Fees (Offer + tx):" GridPane.rowIndex="5"/>
|
||||
<TextField fx:id="feeTextField" editable="false" focusTraversable="false" GridPane.rowIndex="5"
|
||||
GridPane.columnIndex="1"/>
|
||||
|
||||
<Label text="Total:" GridPane.rowIndex="6"/>
|
||||
<TextField fx:id="totalTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="6" GridPane.columnIndex="1"/>
|
||||
|
||||
<Button fx:id="takeOfferButton" text="Take offer and pay" onAction="#onTakeOffer"
|
||||
defaultButton="true" GridPane.rowIndex="7" GridPane.columnIndex="1"/>
|
||||
|
||||
<Label text="Offer details:" id="form-header-text" GridPane.rowIndex="8"/>
|
||||
|
||||
<Label text="Bank account type:" GridPane.rowIndex="9"/>
|
||||
<TextField fx:id="bankAccountTypeTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="9" GridPane.columnIndex="1"/>
|
||||
|
||||
<Label text="Country:" GridPane.rowIndex="10"/>
|
||||
<TextField fx:id="countryTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="10" GridPane.columnIndex="1"/>
|
||||
|
||||
<Label text="Arbitrators:" GridPane.rowIndex="11"/>
|
||||
<TextField fx:id="arbitratorsTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="11" GridPane.columnIndex="1"/>
|
||||
|
||||
<Label text="Supported languages:" GridPane.rowIndex="12"/>
|
||||
<TextField fx:id="supportedLanguagesTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="12" GridPane.columnIndex="1"/>
|
||||
|
||||
<Label text="Supported countries:" GridPane.rowIndex="13"/>
|
||||
<TextField fx:id="supportedCountriesTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="13" GridPane.columnIndex="1"/>
|
||||
|
||||
|
||||
<columnConstraints>
|
||||
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0"/>
|
||||
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0"/>
|
||||
</columnConstraints>
|
||||
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
</rowConstraints>
|
||||
|
||||
</GridPane>
|
||||
</ScrollPane>
|
||||
</TitledPane>
|
||||
|
||||
<TitledPane fx:id="waitBankTxTitledPane" text="Wait for bank transfer">
|
||||
<GridPane hgap="5.0" vgap="5.0">
|
||||
<VBox alignment="CENTER" spacing="6" GridPane.rowSpan="2">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="20.0"/>
|
||||
</GridPane.margin>
|
||||
<ImageView fx:id="imageView" pickOnBounds="true"/>
|
||||
<Label fx:id="buyLabel" id="direction-icon-label" text="%takeOffer.amountPriceBox.subTitle"
|
||||
alignment="CENTER">
|
||||
<padding>
|
||||
<Insets left="10" right="10" top="10" bottom="10"/>
|
||||
<Insets top="-5.0"/>
|
||||
</padding>
|
||||
</Label>
|
||||
</VBox>
|
||||
|
||||
<Label fx:id="headLineLabel" text="Deposit transaction published" id="form-header-text"/>
|
||||
|
||||
<Label text="Status information:" GridPane.rowIndex="1" GridPane.valignment="TOP"/>
|
||||
<Label fx:id="infoLabel" GridPane.rowIndex="1" GridPane.columnIndex="1" GridPane.valignment="TOP"/>
|
||||
|
||||
<Label text="Deposit transaction ID:" GridPane.rowIndex="2"/>
|
||||
<TextField fx:id="depositTxIdTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="2" GridPane.columnIndex="1"/>
|
||||
|
||||
<Button fx:id="receivedFiatButton" text="I have received the money at my bank account"
|
||||
onAction="#onReceivedFiat" defaultButton="true" disable="true" GridPane.rowIndex="3"
|
||||
GridPane.columnIndex="1"/>
|
||||
|
||||
<columnConstraints>
|
||||
<ColumnConstraints halignment="RIGHT" hgrow="NEVER" minWidth="10.0"/>
|
||||
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0"/>
|
||||
</columnConstraints>
|
||||
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
</rowConstraints>
|
||||
|
||||
</GridPane>
|
||||
</TitledPane>
|
||||
|
||||
<TitledPane fx:id="summaryTitledPane" text="Summary">
|
||||
<GridPane hgap="5.0" vgap="5.0">
|
||||
<HBox GridPane.columnIndex="1" alignment="CENTER_LEFT" spacing="5">
|
||||
<GridPane.margin>
|
||||
<Insets right="10.0" top="20.0"/>
|
||||
</GridPane.margin>
|
||||
<VBox spacing="4">
|
||||
<Label id="input-description-label" text="%takeOffer.amountPriceBox.amountDescription"
|
||||
prefWidth="170"/>
|
||||
<HBox>
|
||||
<InputTextField fx:id="amountTextField" id="text-input-with-currency-text-field"
|
||||
promptText="%takeOffer.amount.prompt" prefWidth="170"
|
||||
alignment="CENTER_RIGHT"/>
|
||||
<Label fx:id="amountBtcLabel" id="currency-info-label"/>
|
||||
</HBox>
|
||||
</VBox>
|
||||
<Label text="x">
|
||||
<font>
|
||||
<Font name="Helvetica" size="20.0"/>
|
||||
</font>
|
||||
<padding>
|
||||
<Insets left="10" right="10" top="10" bottom="10"/>
|
||||
<Insets top="14.0" left="3" right="3"/>
|
||||
</padding>
|
||||
</Label>
|
||||
|
||||
<Label text="Trade completed" id="form-header-text"/>
|
||||
<VBox spacing="4">
|
||||
<Label fx:id="priceDescriptionLabel" id="input-description-label" prefWidth="170"/>
|
||||
<TextField fx:id="priceTextField" id="text-input-with-currency-text-field"
|
||||
prefWidth="170" alignment="CENTER_RIGHT" editable="false"/>
|
||||
</VBox>
|
||||
|
||||
<Label text="You have sold:" GridPane.rowIndex="2"/>
|
||||
<ValidatedTextField fx:id="summaryPaidTextField" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
|
||||
<Label text="=">
|
||||
<font>
|
||||
<Font name="Helvetica" size="20.0"/>
|
||||
</font>
|
||||
<padding>
|
||||
<Insets top="14.0" left="2" right="2"/>
|
||||
</padding>
|
||||
</Label>
|
||||
|
||||
<Label text="You have received (EUR):" GridPane.rowIndex="3"/>
|
||||
<TextField fx:id="summaryReceivedTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="3" GridPane.columnIndex="1"/>
|
||||
<VBox spacing="4">
|
||||
<Label fx:id="volumeDescriptionLabel" id="input-description-label" prefWidth="170"/>
|
||||
<TextField fx:id="volumeTextField" id="text-input-with-currency-text-field"
|
||||
prefWidth="170" alignment="CENTER_RIGHT" editable="false"/>
|
||||
</VBox>
|
||||
</HBox>
|
||||
|
||||
<Label text="Details" GridPane.rowIndex="4" id="form-header-text"/>
|
||||
<VBox GridPane.columnIndex="1" GridPane.rowIndex="1" spacing="4">
|
||||
<GridPane.margin>
|
||||
<Insets right="10.0" top="5.0" bottom="5.0"/>
|
||||
</GridPane.margin>
|
||||
<Label id="input-description-label" text="%takeOffer.amountPriceBox.minAmountDescription"
|
||||
prefWidth="170.0"/>
|
||||
<TextField fx:id="minAmountTextField" id="text-input-with-currency-text-field"
|
||||
prefWidth="170.0" editable="false"/>
|
||||
</VBox>
|
||||
|
||||
<Label text="Total fees (take offer fee + tx fee):" GridPane.rowIndex="5"/>
|
||||
<TextField fx:id="summaryFeesTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="5" GridPane.columnIndex="1"/>
|
||||
<InfoDisplay gridPane="$gridPane" onAction="#onOpenGeneralHelp" rowIndex="2" prefWidth="740"
|
||||
text="%takeOffer.amountPriceBox.info"/>
|
||||
|
||||
<Label text="Refunded collateral:" GridPane.rowIndex="6"/>
|
||||
<TextField fx:id="summaryCollateralTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="6" GridPane.columnIndex="1"/>
|
||||
<Button fx:id="showPaymentInfoScreenButton" text="%takeOffer.amountPriceBox.next" id="show-details-button"
|
||||
GridPane.columnIndex="1" GridPane.rowIndex="3" defaultButton="true"
|
||||
onAction="#onShowPayFundsScreen">
|
||||
<GridPane.margin>
|
||||
<Insets top="15.0"/>
|
||||
</GridPane.margin>
|
||||
</Button>
|
||||
|
||||
<Label text="Deposit transaction ID:" GridPane.rowIndex="7"/>
|
||||
<TextField fx:id="summaryDepositTxIdTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="7" GridPane.columnIndex="1"/>
|
||||
<!--
|
||||
Pay funds group
|
||||
-->
|
||||
<TitledGroupBg fx:id="payFundsPane" text="%takeOffer.fundsBox.title" GridPane.rowIndex="4"
|
||||
GridPane.rowSpan="4" GridPane.columnSpan="3" visible="false"/>
|
||||
|
||||
<Label text="Payout transaction ID:" GridPane.rowIndex="8"/>
|
||||
<TextField fx:id="summaryPayoutTxIdTextField" editable="false" focusTraversable="false"
|
||||
GridPane.rowIndex="8" GridPane.columnIndex="1"/>
|
||||
<HBox GridPane.rowIndex="4" spacing="4" alignment="CENTER_RIGHT">
|
||||
<Label fx:id="totalToPayLabel" text="%takeOffer.fundsBox.totalsNeeded" visible="false"/>
|
||||
<Label fx:id="totalToPayInfoIconLabel" visible="false"/>
|
||||
<GridPane.margin>
|
||||
<Insets top="10.0"/>
|
||||
</GridPane.margin>
|
||||
</HBox>
|
||||
<TextField fx:id="totalToPayTextField" promptText="%takeOffer.fundsBox.totalsNeeded.prompt"
|
||||
GridPane.columnIndex="1"
|
||||
GridPane.rowIndex="4"
|
||||
editable="false" focusTraversable="false" visible="false">
|
||||
<GridPane.margin>
|
||||
<Insets top="10.0"/>
|
||||
</GridPane.margin>
|
||||
</TextField>
|
||||
|
||||
<Label fx:id="addressLabel" text="%takeOffer.fundsBox.address" GridPane.rowIndex="5" visible="false"/>
|
||||
<AddressTextField fx:id="addressTextField" GridPane.columnIndex="1" GridPane.rowIndex="5"
|
||||
focusTraversable="true" visible="false"/>
|
||||
|
||||
<Button text="Close" onAction="#onClose" defaultButton="true" GridPane.rowIndex="9"
|
||||
GridPane.columnIndex="1"/>
|
||||
<Label fx:id="balanceLabel" text="%takeOffer.fundsBox.balance" GridPane.rowIndex="6" visible="false">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="5.0"/>
|
||||
</GridPane.margin>
|
||||
</Label>
|
||||
<BalanceTextField fx:id="balanceTextField" GridPane.columnIndex="1" GridPane.rowIndex="6"
|
||||
focusTraversable="false" visible="false">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="5.0"/>
|
||||
</GridPane.margin>
|
||||
</BalanceTextField>
|
||||
|
||||
<columnConstraints>
|
||||
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0"/>
|
||||
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0"/>
|
||||
</columnConstraints>
|
||||
<InfoDisplay fx:id="fundsBoxInfoDisplay" gridPane="$gridPane" onAction="#onOpenFundingHelp" rowIndex="7"
|
||||
text="%takeOffer.fundsBox.info" visible="false" prefWidth="740"/>
|
||||
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||
</rowConstraints>
|
||||
<HBox spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="8">
|
||||
<Button fx:id="showAdvancedSettingsButton" text="%takeOffer.fundsBox.showAdvanced"
|
||||
onAction="#onToggleShowAdvancedSettings" visible="false"/>
|
||||
<Button fx:id="takeOfferButton" text="%takeOffer.fundsBox.takeOffer" visible="false"
|
||||
defaultButton="true"
|
||||
onAction="#onTakeOffer"/>
|
||||
<GridPane.margin>
|
||||
<Insets bottom="30" top="15.0"/>
|
||||
</GridPane.margin>
|
||||
</HBox>
|
||||
|
||||
</GridPane>
|
||||
</TitledPane>
|
||||
<!--
|
||||
Advanced settings group
|
||||
-->
|
||||
<TitledGroupBg fx:id="showDetailsPane" text="%takeOffer.advancedBox.title" GridPane.columnSpan="3"
|
||||
GridPane.rowIndex="9" GridPane.rowSpan="7" visible="false"/>
|
||||
|
||||
</panes>
|
||||
</Accordion>
|
||||
<Label fx:id="acceptedCountriesLabel" text="%takeOffer.advancedBox.countries" GridPane.rowIndex="9"
|
||||
visible="false">
|
||||
<GridPane.margin>
|
||||
<Insets top="0.0"/>
|
||||
</GridPane.margin>
|
||||
</Label>
|
||||
<TextField fx:id="acceptedCountriesTextField" GridPane.columnIndex="1" GridPane.rowIndex="9"
|
||||
visible="false"
|
||||
editable="false" focusTraversable="false"/>
|
||||
|
||||
<Label fx:id="acceptedLanguagesLabel" text="%takeOffer.advancedBox.languages" GridPane.rowIndex="10"
|
||||
visible="false"/>
|
||||
<TextField fx:id="acceptedLanguagesTextField" GridPane.columnIndex="1" GridPane.rowIndex="10"
|
||||
editable="false" focusTraversable="false" visible="false"/>
|
||||
|
||||
<Label fx:id="acceptedArbitratorsLabel" text="%takeOffer.advancedBox.arbitrators" GridPane.rowIndex="11"
|
||||
visible="false"/>
|
||||
<TextField fx:id="acceptedArbitratorsTextField" GridPane.columnIndex="1" GridPane.rowIndex="11"
|
||||
editable="false" focusTraversable="false" visible="false"/>
|
||||
|
||||
<Label fx:id="bankAccountTypeLabel" text="%takeOffer.advancedBox.txType" GridPane.rowIndex="12"
|
||||
visible="false"/>
|
||||
<TextField fx:id="bankAccountTypeTextField" GridPane.columnIndex="1" GridPane.rowIndex="12" editable="false"
|
||||
focusTraversable="false" visible="false"/>
|
||||
|
||||
<Label fx:id="bankAccountCurrencyLabel" text="%takeOffer.advancedBox.currency" GridPane.rowIndex="13"
|
||||
visible="false"/>
|
||||
<TextField fx:id="bankAccountCurrencyTextField" GridPane.rowIndex="13" GridPane.columnIndex="1"
|
||||
editable="false" focusTraversable="false" visible="false"/>
|
||||
|
||||
<Label fx:id="bankAccountCountyLabel" text="%takeOffer.advancedBox.county" GridPane.rowIndex="14"
|
||||
visible="false">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="5.0"/>
|
||||
</GridPane.margin>
|
||||
</Label>
|
||||
<TextField fx:id="bankAccountCountyTextField" GridPane.rowIndex="14" GridPane.columnIndex="1"
|
||||
editable="false" focusTraversable="false" visible="false">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="5.0"/>
|
||||
</GridPane.margin>
|
||||
</TextField>
|
||||
|
||||
<InfoDisplay fx:id="advancedInfoDisplay" gridPane="$gridPane" onAction="#onOpenAdvancedSettingsHelp"
|
||||
rowIndex="15" visible="false" prefWidth="740"
|
||||
text="%takeOffer.advancedBox.info">
|
||||
</InfoDisplay>
|
||||
|
||||
<columnConstraints>
|
||||
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
|
||||
<ColumnConstraints hgrow="ALWAYS"/>
|
||||
</columnConstraints>
|
||||
|
||||
<rowConstraints>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints/>
|
||||
<RowConstraints minHeight="35"/>
|
||||
</rowConstraints>
|
||||
|
||||
</GridPane>
|
||||
</ScrollPane>
|
||||
</AnchorPane>
|
||||
|
@ -0,0 +1,463 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.trade.takeoffer;
|
||||
|
||||
|
||||
import io.bitsquare.gui.CachedViewCB;
|
||||
import io.bitsquare.gui.CloseListener;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.OverlayManager;
|
||||
import io.bitsquare.gui.components.InfoDisplay;
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.components.Popups;
|
||||
import io.bitsquare.gui.components.TitledGroupBg;
|
||||
import io.bitsquare.gui.components.btc.AddressTextField;
|
||||
import io.bitsquare.gui.components.btc.BalanceTextField;
|
||||
import io.bitsquare.gui.main.help.Help;
|
||||
import io.bitsquare.gui.main.help.HelpId;
|
||||
import io.bitsquare.gui.main.trade.OrderBookInfo;
|
||||
import io.bitsquare.gui.util.ImageUtil;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.trade.Direction;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.geometry.VPos;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.image.*;
|
||||
import javafx.scene.input.*;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.stage.Window;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import org.controlsfx.control.PopOver;
|
||||
import org.controlsfx.control.action.AbstractAction;
|
||||
import org.controlsfx.control.action.Action;
|
||||
import org.controlsfx.dialog.Dialog;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TakeOfferViewCB extends CachedViewCB<TakeOfferPM> {
|
||||
private static final Logger log = LoggerFactory.getLogger(TakeOfferViewCB.class);
|
||||
|
||||
private Navigation navigation;
|
||||
private OverlayManager overlayManager;
|
||||
private CloseListener closeListener;
|
||||
|
||||
private boolean detailsVisible;
|
||||
private boolean advancedScreenInited;
|
||||
|
||||
private ImageView expand;
|
||||
private ImageView collapse;
|
||||
private PopOver totalToPayInfoPopover;
|
||||
|
||||
@FXML InfoDisplay advancedInfoDisplay, fundsBoxInfoDisplay;
|
||||
@FXML ScrollPane scrollPane;
|
||||
@FXML ImageView imageView;
|
||||
@FXML TitledGroupBg priceAmountPane, payFundsPane, showDetailsPane;
|
||||
@FXML Label buyLabel, addressLabel,
|
||||
balanceLabel, totalToPayLabel, totalToPayInfoIconLabel,
|
||||
bankAccountTypeLabel, bankAccountCurrencyLabel, bankAccountCountyLabel,
|
||||
acceptedCountriesLabel, acceptedLanguagesLabel,
|
||||
acceptedArbitratorsLabel, amountBtcLabel,
|
||||
priceDescriptionLabel, volumeDescriptionLabel;
|
||||
@FXML Button showPaymentInfoScreenButton, showAdvancedSettingsButton, takeOfferButton;
|
||||
|
||||
@FXML InputTextField amountTextField;
|
||||
@FXML TextField minAmountTextField, priceTextField, volumeTextField, acceptedArbitratorsTextField,
|
||||
totalToPayTextField,
|
||||
bankAccountTypeTextField,
|
||||
bankAccountCurrencyTextField, bankAccountCountyTextField, acceptedCountriesTextField,
|
||||
acceptedLanguagesTextField;
|
||||
@FXML AddressTextField addressTextField;
|
||||
@FXML BalanceTextField balanceTextField;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private TakeOfferViewCB(TakeOfferPM presentationModel, Navigation navigation,
|
||||
OverlayManager overlayManager) {
|
||||
super(presentationModel);
|
||||
|
||||
this.navigation = navigation;
|
||||
this.overlayManager = overlayManager;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
super.initialize(url, rb);
|
||||
|
||||
setupListeners();
|
||||
setupBindings();
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
public void activate() {
|
||||
super.activate();
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void terminate() {
|
||||
super.terminate();
|
||||
|
||||
// Inform parent that we gor removed.
|
||||
// Needed to reset disable state of createOfferButton in OrderBookController
|
||||
if (closeListener != null)
|
||||
closeListener.onClosed();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public methods (called form other views/CB)
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void initWithOrderBookInfo(OrderBookInfo orderBookInfo) {
|
||||
presentationModel.setOrderBookInfo(orderBookInfo);
|
||||
|
||||
if (orderBookInfo.getDirection() == Direction.BUY)
|
||||
imageView.setId("image-buy-large");
|
||||
else
|
||||
imageView.setId("image-sell-large");
|
||||
|
||||
priceDescriptionLabel.setText(BSResources.get("takeOffer.amountPriceBox.priceDescription",
|
||||
presentationModel.getFiatCode()));
|
||||
volumeDescriptionLabel.setText(BSResources.get("takeOffer.amountPriceBox.volumeDescription",
|
||||
presentationModel.getFiatCode()));
|
||||
|
||||
balanceTextField.setup(presentationModel.getWalletFacade(), presentationModel.address.get());
|
||||
|
||||
buyLabel.setText(presentationModel.getDirectionLabel());
|
||||
minAmountTextField.setText(presentationModel.getMinAmount());
|
||||
priceTextField.setText(presentationModel.getPrice());
|
||||
addressTextField.setPaymentLabel(presentationModel.getPaymentLabel());
|
||||
addressTextField.setAddress(presentationModel.getAddressAsString());
|
||||
bankAccountTypeTextField.setText(presentationModel.getBankAccountType());
|
||||
bankAccountTypeTextField.setText(presentationModel.getBankAccountType());
|
||||
bankAccountCurrencyTextField.setText(presentationModel.getBankAccountCurrency());
|
||||
bankAccountCountyTextField.setText(presentationModel.getBankAccountCounty());
|
||||
acceptedCountriesTextField.setText(presentationModel.getAcceptedCountries());
|
||||
acceptedLanguagesTextField.setText(presentationModel.getAcceptedLanguages());
|
||||
acceptedArbitratorsTextField.setText(presentationModel.getAcceptedArbitrators());
|
||||
}
|
||||
|
||||
//TODO not used yet
|
||||
public void setCloseListener(CloseListener closeListener) {
|
||||
this.closeListener = closeListener;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI Handlers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@FXML
|
||||
void onTakeOffer() {
|
||||
presentationModel.takeOffer();
|
||||
}
|
||||
|
||||
@FXML
|
||||
void onShowPayFundsScreen() {
|
||||
priceAmountPane.setInactive();
|
||||
|
||||
showPaymentInfoScreenButton.setVisible(false);
|
||||
|
||||
payFundsPane.setVisible(true);
|
||||
totalToPayLabel.setVisible(true);
|
||||
totalToPayInfoIconLabel.setVisible(true);
|
||||
totalToPayTextField.setVisible(true);
|
||||
addressLabel.setVisible(true);
|
||||
addressTextField.setVisible(true);
|
||||
balanceLabel.setVisible(true);
|
||||
balanceTextField.setVisible(true);
|
||||
fundsBoxInfoDisplay.setVisible(true);
|
||||
showAdvancedSettingsButton.setVisible(true);
|
||||
|
||||
if (expand == null) {
|
||||
expand = ImageUtil.getImageViewById(ImageUtil.EXPAND);
|
||||
collapse = ImageUtil.getImageViewById(ImageUtil.COLLAPSE);
|
||||
}
|
||||
showAdvancedSettingsButton.setGraphic(expand);
|
||||
|
||||
setupTotalToPayInfoIconLabel();
|
||||
|
||||
presentationModel.onShowPayFundsScreen();
|
||||
}
|
||||
|
||||
@FXML
|
||||
void onToggleShowAdvancedSettings() {
|
||||
detailsVisible = !detailsVisible;
|
||||
if (detailsVisible) {
|
||||
showAdvancedSettingsButton.setText(BSResources.get("takeOffer.fundsBox.hideAdvanced"));
|
||||
showAdvancedSettingsButton.setGraphic(collapse);
|
||||
showDetailsScreen();
|
||||
}
|
||||
else {
|
||||
showAdvancedSettingsButton.setText(BSResources.get("takeOffer.fundsBox.showAdvanced"));
|
||||
showAdvancedSettingsButton.setGraphic(expand);
|
||||
hideDetailsScreen();
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
void onOpenGeneralHelp() {
|
||||
Help.openWindow(HelpId.TAKE_OFFER_GENERAL);
|
||||
}
|
||||
|
||||
@FXML
|
||||
void onOpenFundingHelp() {
|
||||
Help.openWindow(HelpId.TAKE_OFFER_FUNDING);
|
||||
}
|
||||
|
||||
@FXML
|
||||
void onOpenAdvancedSettingsHelp() {
|
||||
Help.openWindow(HelpId.TAKE_OFFER_ADVANCED);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Navigation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void close() {
|
||||
TabPane tabPane = ((TabPane) (root.getParent().getParent()));
|
||||
tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void setupListeners() {
|
||||
scrollPane.setOnScroll(e -> InputTextField.hideErrorMessageDisplay());
|
||||
|
||||
// focus out
|
||||
amountTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
|
||||
presentationModel.onFocusOutAmountTextField(oldValue, newValue, amountTextField.getText());
|
||||
amountTextField.setText(presentationModel.amount.get());
|
||||
});
|
||||
|
||||
// warnings
|
||||
presentationModel.showWarningInvalidBtcDecimalPlaces.addListener((o, oldValue, newValue) -> {
|
||||
if (newValue) {
|
||||
Popups.openWarningPopup(BSResources.get("shared.warning"),
|
||||
BSResources.get("takeOffer.amountPriceBox.warning.invalidBtcDecimalPlaces"));
|
||||
presentationModel.showWarningInvalidBtcDecimalPlaces.set(false);
|
||||
}
|
||||
});
|
||||
|
||||
presentationModel.requestTakeOfferErrorMessage.addListener((o, oldValue, newValue) -> {
|
||||
if (newValue != null) {
|
||||
Popups.openErrorPopup(BSResources.get("shared.error"),
|
||||
BSResources.get("takeOffer.amountPriceBox.error.message",
|
||||
presentationModel.requestTakeOfferErrorMessage.get()));
|
||||
}
|
||||
});
|
||||
|
||||
presentationModel.showTransactionPublishedScreen.addListener((o, oldValue, newValue) -> {
|
||||
if (newValue) {
|
||||
overlayManager.blurContent();
|
||||
|
||||
// Dialogs are a bit limited. There is no callback for the InformationDialog button click, so we added
|
||||
// our own actions.
|
||||
List<Action> actions = new ArrayList<>();
|
||||
actions.add(new AbstractAction(BSResources.get("shared.copyTxId")) {
|
||||
@Override
|
||||
public void handle(ActionEvent actionEvent) {
|
||||
Clipboard clipboard = Clipboard.getSystemClipboard();
|
||||
ClipboardContent content = new ClipboardContent();
|
||||
content.putString(presentationModel.transactionId.get());
|
||||
clipboard.setContent(content);
|
||||
}
|
||||
});
|
||||
actions.add(new AbstractAction(BSResources.get("shared.close")) {
|
||||
@Override
|
||||
public void handle(ActionEvent actionEvent) {
|
||||
try {
|
||||
close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Dialog.Actions.CLOSE.handle(actionEvent);
|
||||
overlayManager.removeBlurContent();
|
||||
}
|
||||
});
|
||||
|
||||
Popups.openInfo(BSResources.get("takeOffer.success.info",
|
||||
presentationModel.transactionId.get()),
|
||||
BSResources.get("takeOffer.success.headline"),
|
||||
actions);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupBindings() {
|
||||
amountBtcLabel.textProperty().bind(presentationModel.btcCode);
|
||||
amountTextField.textProperty().bindBidirectional(presentationModel.amount);
|
||||
volumeTextField.textProperty().bindBidirectional(presentationModel.volume);
|
||||
totalToPayTextField.textProperty().bind(presentationModel.totalToPay);
|
||||
addressTextField.amountAsCoinProperty().bind(presentationModel.totalToPayAsCoin);
|
||||
|
||||
// Validation
|
||||
amountTextField.validationResultProperty().bind(presentationModel.amountValidationResult);
|
||||
|
||||
// buttons
|
||||
takeOfferButton.visibleProperty().bind(presentationModel.isTakeOfferButtonVisible);
|
||||
takeOfferButton.disableProperty().bind(presentationModel.isTakeOfferButtonDisabled);
|
||||
}
|
||||
|
||||
private void showDetailsScreen() {
|
||||
payFundsPane.setInactive();
|
||||
|
||||
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
|
||||
scrollPane.layout();
|
||||
|
||||
advancedScreenInited = !advancedScreenInited;
|
||||
|
||||
toggleDetailsScreen(true);
|
||||
}
|
||||
|
||||
private void hideDetailsScreen() {
|
||||
payFundsPane.setActive();
|
||||
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
|
||||
scrollPane.layout();
|
||||
toggleDetailsScreen(false);
|
||||
}
|
||||
|
||||
private void toggleDetailsScreen(boolean visible) {
|
||||
scrollPane.setOnScroll(scrollEvent -> {
|
||||
if (!visible)
|
||||
scrollEvent.consume();
|
||||
});
|
||||
|
||||
// deactivate mouse wheel scrolling if hidden
|
||||
scrollPane.setVmax(visible ? scrollPane.getHeight() : 0);
|
||||
scrollPane.setVvalue(visible ? scrollPane.getHeight() : 0);
|
||||
|
||||
showDetailsPane.setVisible(visible);
|
||||
|
||||
acceptedCountriesLabel.setVisible(visible);
|
||||
acceptedCountriesTextField.setVisible(visible);
|
||||
acceptedLanguagesLabel.setVisible(visible);
|
||||
acceptedLanguagesTextField.setVisible(visible);
|
||||
acceptedArbitratorsLabel.setVisible(visible);
|
||||
acceptedArbitratorsTextField.setVisible(visible);
|
||||
|
||||
bankAccountTypeLabel.setVisible(visible);
|
||||
bankAccountTypeTextField.setVisible(visible);
|
||||
bankAccountCurrencyLabel.setVisible(visible);
|
||||
bankAccountCurrencyTextField.setVisible(visible);
|
||||
bankAccountCountyLabel.setVisible(visible);
|
||||
bankAccountCountyTextField.setVisible(visible);
|
||||
|
||||
advancedInfoDisplay.setVisible(visible);
|
||||
}
|
||||
|
||||
private void setupTotalToPayInfoIconLabel() {
|
||||
totalToPayInfoIconLabel.setId("clickable-icon");
|
||||
AwesomeDude.setIcon(totalToPayInfoIconLabel, AwesomeIcon.QUESTION_SIGN);
|
||||
|
||||
totalToPayInfoIconLabel.setOnMouseEntered(e -> createInfoPopover());
|
||||
totalToPayInfoIconLabel.setOnMouseExited(e -> {
|
||||
if (totalToPayInfoPopover != null)
|
||||
totalToPayInfoPopover.hide();
|
||||
});
|
||||
}
|
||||
|
||||
// As we don't use binding here we need to recreate it on mouse over to reflect the current state
|
||||
private void createInfoPopover() {
|
||||
GridPane infoGridPane = new GridPane();
|
||||
infoGridPane.setHgap(5);
|
||||
infoGridPane.setVgap(5);
|
||||
infoGridPane.setPadding(new Insets(10, 10, 10, 10));
|
||||
|
||||
addPayInfoEntry(infoGridPane, 0,
|
||||
BSResources.get("takeOffer.fundsBox.amount"),
|
||||
presentationModel.amount.get());
|
||||
addPayInfoEntry(infoGridPane, 1,
|
||||
presentationModel.getCollateralLabel(),
|
||||
presentationModel.collateral.get());
|
||||
addPayInfoEntry(infoGridPane, 2, BSResources.get("takeOffer.fundsBox.offerFee"),
|
||||
presentationModel.getOfferFee());
|
||||
addPayInfoEntry(infoGridPane, 3, BSResources.get("takeOffer.fundsBox.networkFee"),
|
||||
presentationModel.getNetworkFee());
|
||||
Separator separator = new Separator();
|
||||
separator.setOrientation(Orientation.HORIZONTAL);
|
||||
separator.setStyle("-fx-background: #666;");
|
||||
GridPane.setConstraints(separator, 1, 4);
|
||||
infoGridPane.getChildren().add(separator);
|
||||
addPayInfoEntry(infoGridPane, 5, BSResources.get("takeOffer.fundsBox.total"),
|
||||
presentationModel.totalToPay.get());
|
||||
totalToPayInfoPopover = new PopOver(infoGridPane);
|
||||
if (totalToPayInfoIconLabel.getScene() != null) {
|
||||
totalToPayInfoPopover.setDetachable(false);
|
||||
totalToPayInfoPopover.setArrowIndent(5);
|
||||
totalToPayInfoPopover.show(totalToPayInfoIconLabel.getScene().getWindow(),
|
||||
getPopupPosition().getX(),
|
||||
getPopupPosition().getY());
|
||||
}
|
||||
}
|
||||
|
||||
private void addPayInfoEntry(GridPane infoGridPane, int row, String labelText, String value) {
|
||||
Label label = new Label(labelText);
|
||||
TextField textField = new TextField(value);
|
||||
textField.setEditable(false);
|
||||
textField.setFocusTraversable(false);
|
||||
textField.setId("payment-info");
|
||||
GridPane.setConstraints(label, 0, row, 1, 1, HPos.RIGHT, VPos.CENTER);
|
||||
GridPane.setConstraints(textField, 1, row);
|
||||
infoGridPane.getChildren().addAll(label, textField);
|
||||
}
|
||||
|
||||
private Point2D getPopupPosition() {
|
||||
Window window = totalToPayInfoIconLabel.getScene().getWindow();
|
||||
Point2D point = totalToPayInfoIconLabel.localToScene(0, 0);
|
||||
double x = point.getX() + window.getX() + totalToPayInfoIconLabel.getWidth() - 3;
|
||||
double y = point.getY() + window.getY() + Math.floor(totalToPayInfoIconLabel.getHeight() / 2) - 9;
|
||||
return new Point2D(x, y);
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ createOffer.amountPriceBox.amountDescription=Amount of Bitcoin to buy
|
||||
createOffer.amountPriceBox.priceDescription=Price per Bitcoin in {0}
|
||||
createOffer.amountPriceBox.volumeDescription=Amount in {0} to spend
|
||||
createOffer.amountPriceBox.minAmountDescription=Minimum amount of Bitcoin
|
||||
createOffer.amountPriceBox.info=Define a price for which you want to byu Bitcoin and either enter the amount or the trade volume. With the minimum amount you can attract more potential traders with giving them more flexibility. But note that there is no automatic creation of a new offer for the remaining amount in the case that a trader takes your offer with a lower amount as defined in the amount field. Your offer will be removed from the orderbook once a trader has taken your offer.
|
||||
createOffer.amountPriceBox.info=Define a price for which you want to buy Bitcoin and either enter the amount or the trade volume. With the minimum amount you can attract more potential traders with giving them more flexibility. But note that there is no automatic creation of a new offer for the remaining amount in the case that a trader takes your offer with a lower amount as defined in the amount field. Your offer will be removed from the orderbook once a trader has taken your offer.
|
||||
createOffer.amountPriceBox.next=Next step
|
||||
createOffer.amountPriceBox.warning.invalidBtcDecimalPlaces=The amount you have entered exceeds the number of allowed decimal places.\nThe amount has been adjusted to 4 decimal places.
|
||||
createOffer.amountPriceBox.warning.invalidFiatDecimalPlaces=The amount you have entered exceeds the number of allowed decimal places. The amount has been adjusted to 2 decimal places.
|
||||
@ -73,6 +73,57 @@ createOffer.success.info=The Transaction ID for the offer payment is: {0}
|
||||
createOffer.error.message=An error occurred when placing the offer.\n{0}
|
||||
|
||||
|
||||
# Take offer
|
||||
takeOffer.amount.prompt=Enter amount in BTC
|
||||
takeOffer.price.prompt=Enter price
|
||||
takeOffer.volume.prompt=Enter amount in {0}
|
||||
takeOffer.minAmount.prompt=Enter min. amount
|
||||
|
||||
takeOffer.amountPriceBox.title=Take offer
|
||||
takeOffer.amountPriceBox.subTitle=Buy Bitcoin
|
||||
takeOffer.amountPriceBox.amountDescription=Amount of Bitcoin to sell
|
||||
takeOffer.amountPriceBox.priceDescription=Price per Bitcoin in {0}
|
||||
takeOffer.amountPriceBox.volumeDescription=Receiving amount in {0}
|
||||
takeOffer.amountPriceBox.minAmountDescription=The offer requires that minimum amount of Bitcoin
|
||||
takeOffer.amountPriceBox.info=Enter the amount of Bitcoin you want to sell. You can choose an amount between the minimum amount and the amount.
|
||||
takeOffer.amountPriceBox.next=Next step
|
||||
takeOffer.amountPriceBox.warning.invalidBtcDecimalPlaces=The amount you have entered exceeds the number of allowed decimal places.\nThe amount has been adjusted to 4 decimal places.
|
||||
takeOffer.amountPriceBox.error.message=An error occurred when taking the offer:\n\n {0}
|
||||
takeOffer.validation.amountSmallerThanMinAmount=Amount cannot be smaller than minimum amount.
|
||||
|
||||
takeOffer.fundsBox.title=Fund your trade wallet
|
||||
takeOffer.fundsBox.totalsNeeded=Funds needed for that trade:
|
||||
takeOffer.fundsBox.totalsNeeded.prompt=Will be calculated from the Bitcoin amount entered above
|
||||
takeOffer.fundsBox.address=Trade wallet address:
|
||||
takeOffer.fundsBox.balance=Trade wallet balance:
|
||||
takeOffer.fundsBox.info=For every offer there is a dedicated trade wallet. You need to fund that trade wallet with the necessary Bitcoin amount. Those funds will be paid in to a locked deposit address. At the end of a successful trade you will get back your collateral and the Bitcoin amount you sold will be transferred to the buyer.
|
||||
takeOffer.fundsBox.amount=Amount to sell:
|
||||
takeOffer.fundsBox.collateral=Refundable collateral ({0}):
|
||||
takeOffer.fundsBox.offerFee=Offer fee:
|
||||
takeOffer.fundsBox.networkFee=Bitcoin network fee:
|
||||
takeOffer.fundsBox.total=Total:
|
||||
takeOffer.fundsBox.showAdvanced=Show advanced settings
|
||||
takeOffer.fundsBox.hideAdvanced=Hide advanced settings
|
||||
takeOffer.fundsBox.takeOffer=Take offer
|
||||
takeOffer.fundsBox.paymentLabel=Bitsquare trade ({0})
|
||||
|
||||
takeOffer.advancedBox.title=Advanced settings
|
||||
takeOffer.advancedBox.countries=Accepted countries:
|
||||
takeOffer.advancedBox.languages=Accepted languages:
|
||||
takeOffer.advancedBox.arbitrators=Accepted arbitrators:
|
||||
takeOffer.advancedBox.txType=Payments method:
|
||||
takeOffer.advancedBox.currency=Currency:
|
||||
takeOffer.advancedBox.county=Payments account country:
|
||||
takeOffer.advancedBox.info=These are the offer restrictions your trading partner has defined in his offer. Your \
|
||||
settings are matching those constraints and you are able to trade with him.
|
||||
|
||||
takeOffer.success.headline=Your have successfully published the deposit.
|
||||
takeOffer.success.info=You need to wait now for the Bitcoin buyer to transfer the money to you. \nYou will get a \
|
||||
notification when he has started the EUR payment.You can see the status of your trade in the orders section under \
|
||||
pending orders.\n\nThe Transaction ID for the deposit payment is: {0}
|
||||
takeOffer.error.message=An error occurred when taking the offer.\n{0}
|
||||
|
||||
|
||||
|
||||
# TODO Update the following string when doing the UI (old stuff...)
|
||||
# generic
|
||||
|
Loading…
x
Reference in New Issue
Block a user