This commit is contained in:
Manfred Karrer 2016-02-09 00:36:59 +01:00
parent 96090b71ad
commit 86284fe644
30 changed files with 135 additions and 115 deletions

View file

@ -56,6 +56,7 @@ import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.bitcoinj.store.BlockStoreException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.controlsfx.dialog.Dialogs;
import org.reactfx.EventStreams;
@ -108,10 +109,15 @@ public class BitsquareApp extends Application {
// setup UncaughtExceptionHandler
Thread.UncaughtExceptionHandler handler = (thread, throwable) -> {
// Might come from another thread
log.error("Uncaught Exception from thread " + Thread.currentThread().getName());
log.error("Uncaught Exception throwableMessage= " + throwable.getMessage());
throwable.printStackTrace();
UserThread.execute(() -> showErrorPopup(throwable, false));
if (throwable.getCause() != null && throwable.getCause().getCause() != null &&
throwable.getCause().getCause() instanceof BlockStoreException) {
log.error(throwable.getMessage());
} else {
log.error("Uncaught Exception from thread " + Thread.currentThread().getName());
log.error("Uncaught Exception throwableMessage= " + throwable.getMessage());
throwable.printStackTrace();
UserThread.execute(() -> showErrorPopup(throwable, false));
}
};
Thread.setDefaultUncaughtExceptionHandler(handler);
Thread.currentThread().setUncaughtExceptionHandler(handler);
@ -135,7 +141,7 @@ public class BitsquareApp extends Application {
if (mainView != null)
mainView.setPersistedFilesCorrupted(corruptedDatabaseFiles);
});
// load the main view and create the main scene
CachingViewLoader viewLoader = injector.getInstance(CachingViewLoader.class);
mainView = (MainView) viewLoader.load(MainView.class);

View file

@ -26,7 +26,6 @@ import javafx.scene.layout.Pane;
public class TitledGroupBg extends Pane {
private final Label label;
private final StringProperty text = new SimpleStringProperty();

View file

@ -637,7 +637,10 @@ public class MainViewModel implements ViewModel {
if (error instanceof TimeoutException) {
walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout.");
} else if (error.getCause() instanceof BlockStoreException) {
walletServiceErrorMsg.set("Bitsquare is already running. You cannot run 2 instances of Bitsquare.");
new Popup().warning("Bitsquare is already running. You cannot run 2 instances of Bitsquare.")
.closeButtonText("Shut down")
.onClose(BitsquareApp.shutDownHandler::run)
.show();
} else if (error.getMessage() != null) {
walletServiceErrorMsg.set("Connection to the bitcoin network failed because of an error:" + error.getMessage());
} else {

View file

@ -29,7 +29,7 @@
<TableView fx:id="table" VBox.vgrow="ALWAYS">
<columns>
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="170" maxWidth="170"/>
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="180" maxWidth="180"/>
<TableColumn text="Details" fx:id="detailsColumn" minWidth="260"/>
<TableColumn text="Address" fx:id="addressColumn" minWidth="320" maxWidth="320">
<cellValueFactory>

View file

@ -28,12 +28,12 @@
</padding>
<TableView fx:id="table" VBox.vgrow="ALWAYS">
<columns>
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="160" maxWidth="160">
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="180" maxWidth="180">
<cellValueFactory>
<PropertyValueFactory property="date"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Details" fx:id="detailsColumn" minWidth="210" maxWidth="210"/>
<TableColumn text="Details" fx:id="detailsColumn" minWidth="220" maxWidth="220"/>
<TableColumn text="Address" fx:id="addressColumn" minWidth="180"/>
<TableColumn text="Transaction" fx:id="transactionColumn" minWidth="100"/>
<TableColumn text="Amount (BTC)" fx:id="amountColumn" minWidth="110" maxWidth="110">

View file

@ -30,7 +30,7 @@
<TableView fx:id="table" VBox.vgrow="ALWAYS">
<columns>
<TableColumn text="Select" fx:id="selectColumn" minWidth="60" maxWidth="60" sortable="false"/>
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="170" maxWidth="170"/>
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="180" maxWidth="180"/>
<TableColumn text="Details" fx:id="detailsColumn" minWidth="160" maxWidth="160"/>
<TableColumn text="Address" fx:id="addressColumn" minWidth="320" maxWidth="320">
<cellValueFactory>

View file

@ -191,9 +191,9 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
new Popup().headLine("Confirm your withdrawal request")
.message("Sending: " + formatter.formatCoinWithCode(senderAmount) + "\n" +
"From address: " + withdrawFromTextField.getText() + "\n" +
"To receiving address: " + withdrawToTextField.getText() + ".\n\n" +
"Required transaction fee is: " + formatter.formatCoinWithCode(requiredFee) + "\n" +
"Recipient will receive: " + formatter.formatCoinWithCode(receiverAmount) + "\n\n" +
"To receiving address: " + withdrawToTextField.getText() + ".\n" +
"Required transaction fee is: " + formatter.formatCoinWithCode(requiredFee) + "\n\n" +
"The recipient will receive: " + formatter.formatCoinWithCode(receiverAmount) + "\n\n" +
"Are you sure you want to withdraw that amount?")
.onAction(() -> doWithdraw(receiverAmount, callback))
.show();

View file

@ -103,6 +103,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
final ObservableList<PaymentAccount> paymentAccounts = FXCollections.observableArrayList();
private PaymentAccount paymentAccount;
private WalletEventListener walletEventListener;
///////////////////////////////////////////////////////////////////////////////////////////
@ -138,42 +139,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
};
paymentAccountsChangeListener = change -> paymentAccounts.setAll(user.getPaymentAccounts());
}
@Override
protected void activate() {
addBindings();
addListeners();
paymentAccounts.setAll(user.getPaymentAccounts());
updateBalance(walletService.getBalanceForAddress(getAddressEntry().getAddress()));
if (direction == Offer.Direction.BUY)
calculateTotalToPay();
}
@Override
protected void deactivate() {
removeBindings();
removeListeners();
}
private void addBindings() {
btcCode.bind(preferences.btcDenominationProperty());
}
private void removeBindings() {
btcCode.unbind();
}
boolean isFeeFromFundingTxSufficient() {
return feeFromFundingTxProperty.get().compareTo(FeePolicy.getMinFundingFee()) >= 0;
}
private void addListeners() {
walletService.addBalanceListener(balanceListener);
walletService.getWallet().addEventListener(new WalletEventListener() {
walletEventListener = new WalletEventListener() {
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
requestFeeFromBlockchain(tx.getHashAsString());
@ -202,28 +168,45 @@ class CreateOfferDataModel extends ActivatableDataModel {
@Override
public void onKeysAdded(List<ECKey> keys) {
}
});
user.getPaymentAccountsAsObservable().addListener(paymentAccountsChangeListener);
};
}
private void requestFeeFromBlockchain(String transactionId) {
SettableFuture<Coin> future = blockchainService.requestFeeFromBlockchain(transactionId);
Futures.addCallback(future, new FutureCallback<Coin>() {
public void onSuccess(Coin fee) {
UserThread.execute(() -> feeFromFundingTxProperty.set(fee));
}
@Override
protected void activate() {
addBindings();
addListeners();
public void onFailure(@NotNull Throwable throwable) {
UserThread.execute(() -> new Popup()
.warning("We did not get a result for the mining fee used in the funding transaction.")
.show());
}
});
paymentAccounts.setAll(user.getPaymentAccounts());
updateBalance(walletService.getBalanceForAddress(getAddressEntry().getAddress()));
if (direction == Offer.Direction.BUY)
calculateTotalToPay();
}
@Override
protected void deactivate() {
removeBindings();
removeListeners();
}
private void addBindings() {
btcCode.bind(preferences.btcDenominationProperty());
}
private void removeBindings() {
btcCode.unbind();
}
private void addListeners() {
walletService.addBalanceListener(balanceListener);
walletService.getWallet().addEventListener(walletEventListener);
user.getPaymentAccountsAsObservable().addListener(paymentAccountsChangeListener);
}
private void removeListeners() {
walletService.removeBalanceListener(balanceListener);
walletService.getWallet().removeEventListener(walletEventListener);
user.getPaymentAccountsAsObservable().removeListener(paymentAccountsChangeListener);
}
@ -343,10 +326,30 @@ class CreateOfferDataModel extends ActivatableDataModel {
return user.getAcceptedArbitrators().size() > 0;
}
boolean isFeeFromFundingTxSufficient() {
return feeFromFundingTxProperty.get().compareTo(FeePolicy.getMinRequiredFeeForFundingTx()) >= 0;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Utils
///////////////////////////////////////////////////////////////////////////////////////////
private void requestFeeFromBlockchain(String transactionId) {
SettableFuture<Coin> future = blockchainService.requestFeeFromBlockchain(transactionId);
Futures.addCallback(future, new FutureCallback<Coin>() {
public void onSuccess(Coin fee) {
UserThread.execute(() -> feeFromFundingTxProperty.set(fee));
}
public void onFailure(@NotNull Throwable throwable) {
UserThread.execute(() -> new Popup()
.warning("We did not get a response for the request of the mining fee used in the funding transaction.")
.show());
}
});
}
void calculateVolume() {
if (priceAsFiat.get() != null &&
amountAsCoin.get() != null &&

View file

@ -241,7 +241,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
"You can see the details when you move the mouse over the question mark.\n\n" +
"Important notice!\n" +
"Please take care that you use a mining fee of at least " +
model.formatter.formatCoinWithCode(FeePolicy.getMinFundingFee()) + " when you transfer bitcoin from your external " +
model.formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) + " when you transfer bitcoin from your external " +
"wallet to ensure the trade transactions will get into the blockchain.\n" +
"A too low mining fee might result in a delayed trade and will be rejected!")
.closeButtonText("I understand")
@ -448,7 +448,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
if (!model.dataModel.isFeeFromFundingTxSufficient()) {
new Popup().warning("The mining fee from your funding transaction is not sufficiently high.\n\n" +
"You need to use at least a mining fee of " +
model.formatCoin(FeePolicy.getMinFundingFee()) + ".\n\n" +
model.formatCoin(FeePolicy.getMinRequiredFeeForFundingTx()) + ".\n\n" +
"The fee used in your funding transaction was only " + model.formatCoin(newValue) + ".\n\n" +
"The trade transactions might take too much time to be included in " +
"a block if the fee is too low.\n" +

View file

@ -347,7 +347,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
"You can see the details when you move the mouse over the question mark.\n\n" +
"Important notice!\n" +
"Please take care that you use a mining fee of at least " +
model.formatter.formatCoinWithCode(FeePolicy.getMinFundingFee()) + " when you transfer bitcoin from your external " +
model.formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) + " when you transfer bitcoin from your external " +
"wallet to ensure the trade transactions will get into the blockchain.\n" +
"A too low mining fee might result in a delayed trade and will be rejected!")
.closeButtonText("I understand")

View file

@ -321,7 +321,8 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
}
public String getOpenDisputeTimeAsFormattedDate() {
return formatter.addBlocksToNowDateFormatted(getOpenDisputeTimeAsBlockHeight() - getBestChainHeight() + (getLockTime() - getBestChainHeight()));
return formatter.addBlocksToNowDateFormatted(getOpenDisputeTimeAsBlockHeight() - getBestChainHeight() +
(dataModel.getTrade().getOffer().getPaymentMethod().getLockTime()));
}
public String getReference() {

View file

@ -150,7 +150,6 @@ public abstract class TradeStepView extends AnchorPane {
tradeInfoTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 4, "Trade information");
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
//TODO
PaymentMethodForm.addAllowedPeriod(gridPane, ++gridRow, model.dataModel.getSellersPaymentAccountContractData(),
model.getOpenDisputeTimeAsFormattedDate());

View file

@ -294,8 +294,8 @@ public class FormBuilder {
InputTextField inputTextField = new InputTextField();
CheckBox checkBox = new CheckBox(checkBoxTitle);
checkBox.setPadding(new Insets(6, 0, 0, 0));
HBox.setMargin(checkBox, new Insets(4, 0, 0, 0));
HBox hBox = new HBox();
hBox.setSpacing(10);
hBox.getChildren().addAll(inputTextField, checkBox);