mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Merge branch 'cbeams'
Significant changes in the way that controllers and models interact with backend services. Most important is the introduction of RxJava's Observable. See individual commit comments for details. Conflicts were minor, mainly dealing with the fact that MainPM had been modified in master, but removed completely on the 'cbeams' branch. All changes have been preserved by carrying them over to MainModel. * cbeams: Improve service initialization coordination using rx.Observable Redesign controller/model types and apply to gui.main.Main* Conflicts: build.gradle src/main/java/io/bitsquare/btc/WalletService.java src/main/java/io/bitsquare/gui/main/MainPM.java src/main/java/io/bitsquare/msg/tomp2p/TomP2PNode.java
This commit is contained in:
commit
30c0ade5f9
@ -41,6 +41,7 @@ repositories {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile 'org.bitcoinj:bitcoinj-core:0.12.2'
|
compile 'org.bitcoinj:bitcoinj-core:0.12.2'
|
||||||
compile 'net.tomp2p:tomp2p-all:5.0-Alpha.8f1cafb-SNAPSHOT'
|
compile 'net.tomp2p:tomp2p-all:5.0-Alpha.8f1cafb-SNAPSHOT'
|
||||||
|
compile 'io.reactivex:rxjava:1.0.0-rc.12'
|
||||||
compile 'org.springframework:spring-core:4.1.1.RELEASE'
|
compile 'org.springframework:spring-core:4.1.1.RELEASE'
|
||||||
compile 'net.sf.jopt-simple:jopt-simple:4.8'
|
compile 'net.sf.jopt-simple:jopt-simple:4.8'
|
||||||
compile 'org.slf4j:slf4j-api:1.7.7'
|
compile 'org.slf4j:slf4j-api:1.7.7'
|
||||||
|
@ -23,6 +23,7 @@ import io.bitsquare.btc.listeners.TxConfidenceListener;
|
|||||||
import io.bitsquare.crypto.SignatureService;
|
import io.bitsquare.crypto.SignatureService;
|
||||||
import io.bitsquare.persistence.Persistence;
|
import io.bitsquare.persistence.Persistence;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.AbstractWalletEventListener;
|
||||||
import org.bitcoinj.core.Address;
|
import org.bitcoinj.core.Address;
|
||||||
import org.bitcoinj.core.AddressFormatException;
|
import org.bitcoinj.core.AddressFormatException;
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
@ -85,6 +86,10 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import rx.Observable;
|
||||||
|
import rx.subjects.BehaviorSubject;
|
||||||
|
import rx.subjects.Subject;
|
||||||
|
|
||||||
import static org.bitcoinj.script.ScriptOpCodes.OP_RETURN;
|
import static org.bitcoinj.script.ScriptOpCodes.OP_RETURN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,6 +108,10 @@ public class WalletService {
|
|||||||
private final List<BalanceListener> balanceListeners = new CopyOnWriteArrayList<>();
|
private final List<BalanceListener> balanceListeners = new CopyOnWriteArrayList<>();
|
||||||
private final ReentrantLock lock = Threading.lock(LOCK_NAME);
|
private final ReentrantLock lock = Threading.lock(LOCK_NAME);
|
||||||
|
|
||||||
|
private final ObservableDownloadListener downloadListener = new ObservableDownloadListener();
|
||||||
|
private final Observable<Double> downloadProgress = downloadListener.getObservable();
|
||||||
|
private final WalletEventListener walletEventListener = new BitsquareWalletEventListener();
|
||||||
|
|
||||||
private final NetworkParameters params;
|
private final NetworkParameters params;
|
||||||
private final FeePolicy feePolicy;
|
private final FeePolicy feePolicy;
|
||||||
private final SignatureService signatureService;
|
private final SignatureService signatureService;
|
||||||
@ -113,7 +122,6 @@ public class WalletService {
|
|||||||
|
|
||||||
private WalletAppKit walletAppKit;
|
private WalletAppKit walletAppKit;
|
||||||
private Wallet wallet;
|
private Wallet wallet;
|
||||||
private WalletEventListener walletEventListener;
|
|
||||||
private AddressEntry registrationAddressEntry;
|
private AddressEntry registrationAddressEntry;
|
||||||
private AddressEntry arbitratorDepositAddressEntry;
|
private AddressEntry arbitratorDepositAddressEntry;
|
||||||
private @GuardedBy(LOCK_NAME) List<AddressEntry> addressEntryList = new ArrayList<>();
|
private @GuardedBy(LOCK_NAME) List<AddressEntry> addressEntryList = new ArrayList<>();
|
||||||
@ -140,8 +148,9 @@ public class WalletService {
|
|||||||
// Public Methods
|
// Public Methods
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void initialize(Executor executor, BlockchainDownloadListener blockchainDownloadListener,
|
public Observable<Object> initialize(Executor executor) {
|
||||||
StartupListener startupListener) {
|
Subject<Object, Object> status = BehaviorSubject.create();
|
||||||
|
|
||||||
// Tell bitcoinj to execute event handlers on the JavaFX UI thread. This keeps things simple and means
|
// Tell bitcoinj to execute event handlers on the JavaFX UI thread. This keeps things simple and means
|
||||||
// we cannot forget to switch threads when adding event handlers. Unfortunately, the DownloadListener
|
// we cannot forget to switch threads when adding event handlers. Unfortunately, the DownloadListener
|
||||||
// we give to the app kit is currently an exception and runs on a library thread. It'll get fixed in
|
// we give to the app kit is currently an exception and runs on a library thread. It'll get fixed in
|
||||||
@ -159,7 +168,7 @@ public class WalletService {
|
|||||||
walletAppKit.peerGroup().setMaxConnections(11);
|
walletAppKit.peerGroup().setMaxConnections(11);
|
||||||
walletAppKit.peerGroup().setBloomFilterFalsePositiveRate(0.00001);
|
walletAppKit.peerGroup().setBloomFilterFalsePositiveRate(0.00001);
|
||||||
initWallet();
|
initWallet();
|
||||||
executor.execute(() -> startupListener.completed());
|
status.onCompleted();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Now configure and start the appkit. This will take a second or two - we could show a temporary splash screen
|
// Now configure and start the appkit. This will take a second or two - we could show a temporary splash screen
|
||||||
@ -186,21 +195,6 @@ public class WalletService {
|
|||||||
//walletAppKit.useTor();
|
//walletAppKit.useTor();
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadListener does not run yet in a user thread, so we map it our self
|
|
||||||
DownloadListener downloadListener = new DownloadListener() {
|
|
||||||
@Override
|
|
||||||
protected void progress(double percentage, int blocksLeft, Date date) {
|
|
||||||
super.progress(percentage, blocksLeft, date);
|
|
||||||
executor.execute(() -> blockchainDownloadListener.progress(percentage));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doneDownload() {
|
|
||||||
super.doneDownload();
|
|
||||||
executor.execute(() -> blockchainDownloadListener.doneDownload());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
walletAppKit.setDownloadListener(downloadListener)
|
walletAppKit.setDownloadListener(downloadListener)
|
||||||
.setBlockingStartup(false)
|
.setBlockingStartup(false)
|
||||||
.setUserAgent(userAgent.getName(), userAgent.getVersion());
|
.setUserAgent(userAgent.getName(), userAgent.getVersion());
|
||||||
@ -215,52 +209,16 @@ public class WalletService {
|
|||||||
@Override
|
@Override
|
||||||
public void failed(@NotNull Service.State from, @NotNull Throwable failure) {
|
public void failed(@NotNull Service.State from, @NotNull Throwable failure) {
|
||||||
walletAppKit = null;
|
walletAppKit = null;
|
||||||
startupListener.failed(failure);
|
status.onError(failure);
|
||||||
}
|
}
|
||||||
}, Threading.USER_THREAD);
|
}, Threading.USER_THREAD);
|
||||||
walletAppKit.startAsync();
|
walletAppKit.startAsync();
|
||||||
|
|
||||||
|
return status.mergeWith(downloadProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initWallet() {
|
private void initWallet() {
|
||||||
wallet = walletAppKit.wallet();
|
wallet = walletAppKit.wallet();
|
||||||
|
|
||||||
walletEventListener = new WalletEventListener() {
|
|
||||||
@Override
|
|
||||||
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
|
|
||||||
notifyBalanceListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
|
|
||||||
notifyBalanceListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReorganize(Wallet wallet) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) {
|
|
||||||
log.trace("onTransactionConfidenceChanged " + tx.getHashAsString());
|
|
||||||
notifyConfidenceListeners(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onWalletChanged(Wallet wallet) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onScriptsAdded(Wallet wallet, List<Script> scripts) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onKeysAdded(List<ECKey> keys) {
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
wallet.addEventListener(walletEventListener);
|
wallet.addEventListener(walletEventListener);
|
||||||
|
|
||||||
Serializable serializable = persistence.read(this, "addressEntryList");
|
Serializable serializable = persistence.read(this, "addressEntryList");
|
||||||
@ -292,6 +250,10 @@ public class WalletService {
|
|||||||
walletAppKit.stopAsync();
|
walletAppKit.stopAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Observable<Double> getDownloadProgress() {
|
||||||
|
return downloadProgress;
|
||||||
|
}
|
||||||
|
|
||||||
public Wallet getWallet() {
|
public Wallet getWallet() {
|
||||||
return wallet;
|
return wallet;
|
||||||
}
|
}
|
||||||
@ -406,17 +368,6 @@ public class WalletService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void notifyConfidenceListeners(Transaction tx) {
|
private void notifyConfidenceListeners(Transaction tx) {
|
||||||
for (AddressConfidenceListener addressConfidenceListener : addressConfidenceListeners) {
|
|
||||||
List<TransactionConfidence> transactionConfidenceList = new ArrayList<>();
|
|
||||||
transactionConfidenceList.add(getTransactionConfidence(tx, addressConfidenceListener.getAddress()));
|
|
||||||
|
|
||||||
TransactionConfidence transactionConfidence = getMostRecentConfidence(transactionConfidenceList);
|
|
||||||
addressConfidenceListener.onTransactionConfidenceChanged(transactionConfidence);
|
|
||||||
}
|
|
||||||
|
|
||||||
txConfidenceListeners.stream().filter(txConfidenceListener -> tx.getHashAsString().equals
|
|
||||||
(txConfidenceListener.getTxID())).forEach(txConfidenceListener -> txConfidenceListener
|
|
||||||
.onTransactionConfidenceChanged(tx.getConfidence()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransactionConfidence getTransactionConfidence(Transaction tx, Address address) {
|
private TransactionConfidence getTransactionConfidence(Transaction tx, Address address) {
|
||||||
@ -505,18 +456,6 @@ public class WalletService {
|
|||||||
return balance;
|
return balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyBalanceListeners() {
|
|
||||||
for (BalanceListener balanceListener : balanceListeners) {
|
|
||||||
Coin balance;
|
|
||||||
if (balanceListener.getAddress() != null)
|
|
||||||
balance = getBalanceForAddress(balanceListener.getAddress());
|
|
||||||
else
|
|
||||||
balance = getWalletBalance();
|
|
||||||
|
|
||||||
balanceListener.onBalanceChanged(balance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Coin getWalletBalance() {
|
public Coin getWalletBalance() {
|
||||||
return wallet.getBalance(Wallet.BalanceType.ESTIMATED);
|
return wallet.getBalance(Wallet.BalanceType.ESTIMATED);
|
||||||
}
|
}
|
||||||
@ -1154,16 +1093,66 @@ public class WalletService {
|
|||||||
// Inner classes
|
// Inner classes
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public static interface StartupListener {
|
|
||||||
void completed();
|
|
||||||
|
|
||||||
void failed(Throwable failure);
|
private static class ObservableDownloadListener extends DownloadListener {
|
||||||
|
|
||||||
|
private final Subject<Double, Double> subject = BehaviorSubject.create(0d);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void progress(double percentage, int blocksLeft, Date date) {
|
||||||
|
super.progress(percentage, blocksLeft, date);
|
||||||
|
subject.onNext(percentage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doneDownload() {
|
||||||
|
super.doneDownload();
|
||||||
|
subject.onCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Observable<Double> getObservable() {
|
||||||
|
return subject.asObservable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface BlockchainDownloadListener {
|
|
||||||
void progress(double percentage);
|
|
||||||
|
|
||||||
void doneDownload();
|
private class BitsquareWalletEventListener extends AbstractWalletEventListener {
|
||||||
|
@Override
|
||||||
|
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
|
||||||
|
notifyBalanceListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
|
||||||
|
notifyBalanceListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) {
|
||||||
|
for (AddressConfidenceListener addressConfidenceListener : addressConfidenceListeners) {
|
||||||
|
List<TransactionConfidence> transactionConfidenceList = new ArrayList<>();
|
||||||
|
transactionConfidenceList.add(getTransactionConfidence(tx, addressConfidenceListener.getAddress()));
|
||||||
|
|
||||||
|
TransactionConfidence transactionConfidence = getMostRecentConfidence(transactionConfidenceList);
|
||||||
|
addressConfidenceListener.onTransactionConfidenceChanged(transactionConfidence);
|
||||||
|
}
|
||||||
|
|
||||||
|
txConfidenceListeners.stream()
|
||||||
|
.filter(txConfidenceListener -> tx.getHashAsString().equals(txConfidenceListener.getTxID()))
|
||||||
|
.forEach(txConfidenceListener ->
|
||||||
|
txConfidenceListener.onTransactionConfidenceChanged(tx.getConfidence()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyBalanceListeners() {
|
||||||
|
for (BalanceListener balanceListener : balanceListeners) {
|
||||||
|
Coin balance;
|
||||||
|
if (balanceListener.getAddress() != null)
|
||||||
|
balance = getBalanceForAddress(balanceListener.getAddress());
|
||||||
|
else
|
||||||
|
balance = getWalletBalance();
|
||||||
|
|
||||||
|
balanceListener.onBalanceChanged(balance);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
52
src/main/java/io/bitsquare/gui/Controller.java
Normal file
52
src/main/java/io/bitsquare/gui/Controller.java
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
public abstract class Controller<M extends Model> implements Initializable {
|
||||||
|
|
||||||
|
public static final String TITLE_KEY = "view.title";
|
||||||
|
|
||||||
|
protected M model;
|
||||||
|
|
||||||
|
protected Controller(M model) {
|
||||||
|
this.model = checkNotNull(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL url, ResourceBundle rb) {
|
||||||
|
model.initialize();
|
||||||
|
doInitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void terminate() {
|
||||||
|
//model.terminate();
|
||||||
|
//doTerminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void doInitialize();
|
||||||
|
|
||||||
|
protected void doTerminate() { };
|
||||||
|
}
|
44
src/main/java/io/bitsquare/gui/FxmlController.java
Normal file
44
src/main/java/io/bitsquare/gui/FxmlController.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.*;
|
||||||
|
|
||||||
|
public abstract class FxmlController<R extends Node, M extends Model> extends Controller<M> {
|
||||||
|
|
||||||
|
protected @FXML R root;
|
||||||
|
|
||||||
|
protected FxmlController(M model) {
|
||||||
|
super(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL url, ResourceBundle rb) {
|
||||||
|
root.sceneProperty().addListener((ov, oldValue, newValue) -> {
|
||||||
|
// root node has been removed the scene
|
||||||
|
if (oldValue != null && newValue == null)
|
||||||
|
terminate();
|
||||||
|
});
|
||||||
|
super.initialize(url, rb);
|
||||||
|
}
|
||||||
|
}
|
@ -15,15 +15,8 @@
|
|||||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.bitsquare.msg.listeners;
|
package io.bitsquare.gui;
|
||||||
|
|
||||||
import io.bitsquare.network.BootstrapState;
|
|
||||||
|
|
||||||
public interface BootstrapListener {
|
|
||||||
public void onCompleted();
|
|
||||||
|
|
||||||
public void onFailed(Throwable throwable);
|
|
||||||
|
|
||||||
public void onBootstrapStateChanged(BootstrapState state);
|
|
||||||
|
|
||||||
|
public interface Model {
|
||||||
|
void initialize();
|
||||||
}
|
}
|
@ -40,7 +40,7 @@ public class ViewCB<T extends PresentationModel> implements Initializable {
|
|||||||
|
|
||||||
protected T presentationModel;
|
protected T presentationModel;
|
||||||
protected Initializable childController;
|
protected Initializable childController;
|
||||||
protected ViewCB<? extends PresentationModel> parent;
|
protected Initializable parent;
|
||||||
|
|
||||||
@FXML protected Parent root;
|
@FXML protected Parent root;
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ public class ViewCB<T extends PresentationModel> implements Initializable {
|
|||||||
* @param parent Controller who has created this.getClass().getSimpleName() instance (via
|
* @param parent Controller who has created this.getClass().getSimpleName() instance (via
|
||||||
* navigateToView/FXMLLoader).
|
* navigateToView/FXMLLoader).
|
||||||
*/
|
*/
|
||||||
public void setParent(ViewCB<? extends PresentationModel> parent) {
|
public void setParent(Initializable parent) {
|
||||||
log.trace("Lifecycle: setParentController " + this.getClass().getSimpleName() + " / parent = " +
|
log.trace("Lifecycle: setParentController " + this.getClass().getSimpleName() + " / parent = " +
|
||||||
parent);
|
parent);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
@ -18,11 +18,11 @@
|
|||||||
package io.bitsquare.gui.main;
|
package io.bitsquare.gui.main;
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
|
import io.bitsquare.btc.BitcoinNetwork;
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.btc.WalletService;
|
||||||
import io.bitsquare.gui.UIModel;
|
import io.bitsquare.gui.Model;
|
||||||
import io.bitsquare.gui.util.Profiler;
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
import io.bitsquare.msg.MessageService;
|
import io.bitsquare.msg.MessageService;
|
||||||
import io.bitsquare.msg.listeners.BootstrapListener;
|
|
||||||
import io.bitsquare.network.BootstrapState;
|
import io.bitsquare.network.BootstrapState;
|
||||||
import io.bitsquare.persistence.Persistence;
|
import io.bitsquare.persistence.Persistence;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
@ -40,170 +40,189 @@ import javafx.beans.property.SimpleBooleanProperty;
|
|||||||
import javafx.beans.property.SimpleDoubleProperty;
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
import javafx.beans.property.SimpleIntegerProperty;
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.collections.MapChangeListener;
|
import javafx.collections.MapChangeListener;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.util.StringConverter;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
class MainModel extends UIModel {
|
import rx.Observable;
|
||||||
|
|
||||||
|
class MainModel implements Model {
|
||||||
private static final Logger log = LoggerFactory.getLogger(MainModel.class);
|
private static final Logger log = LoggerFactory.getLogger(MainModel.class);
|
||||||
|
|
||||||
|
final DoubleProperty networkSyncProgress = new SimpleDoubleProperty(-1);
|
||||||
|
final IntegerProperty numPendingTrades = new SimpleIntegerProperty(0);
|
||||||
|
final ObjectProperty<BootstrapState> bootstrapState = new SimpleObjectProperty<>();
|
||||||
|
final StringProperty bootstrapStateText = new SimpleStringProperty();
|
||||||
|
final ObjectProperty walletServiceException = new SimpleObjectProperty<Throwable>();
|
||||||
|
|
||||||
|
final StringProperty bankAccountsComboBoxPrompt = new SimpleStringProperty();
|
||||||
|
final BooleanProperty bankAccountsComboBoxDisable = new SimpleBooleanProperty();
|
||||||
|
|
||||||
|
final StringProperty blockchainSyncState = new SimpleStringProperty("Initializing");
|
||||||
|
final DoubleProperty blockchainSyncProgress = new SimpleDoubleProperty();
|
||||||
|
final BooleanProperty blockchainSyncIndicatorVisible = new SimpleBooleanProperty(true);
|
||||||
|
final StringProperty blockchainSyncIconId = new SimpleStringProperty();
|
||||||
|
final StringProperty walletServiceErrorMsg = new SimpleStringProperty();
|
||||||
|
|
||||||
|
final DoubleProperty bootstrapProgress = new SimpleDoubleProperty(-1);
|
||||||
|
final BooleanProperty bootstrapFailed = new SimpleBooleanProperty();
|
||||||
|
final StringProperty bootstrapErrorMsg = new SimpleStringProperty();
|
||||||
|
final StringProperty bootstrapIconId = new SimpleStringProperty();
|
||||||
|
|
||||||
private final User user;
|
private final User user;
|
||||||
private final WalletService walletService;
|
private final WalletService walletService;
|
||||||
private final MessageService messageService;
|
private final MessageService messageService;
|
||||||
private final TradeManager tradeManager;
|
private final TradeManager tradeManager;
|
||||||
private final Persistence persistence;
|
private final BitcoinNetwork bitcoinNetwork;
|
||||||
|
private final BSFormatter formatter;
|
||||||
|
|
||||||
private boolean messageServiceInited;
|
|
||||||
private boolean walletServiceInited;
|
|
||||||
private boolean servicesInitialised;
|
|
||||||
|
|
||||||
final BooleanProperty backendReady = new SimpleBooleanProperty();
|
|
||||||
final DoubleProperty networkSyncProgress = new SimpleDoubleProperty(-1);
|
|
||||||
final IntegerProperty numPendingTrades = new SimpleIntegerProperty(0);
|
|
||||||
final ObjectProperty<BootstrapState> bootstrapState = new SimpleObjectProperty<>();
|
|
||||||
final ObjectProperty walletServiceException = new SimpleObjectProperty<Throwable>();
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructor
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private MainModel(User user, WalletService walletService, MessageService messageService,
|
public MainModel(User user, WalletService walletService, MessageService messageService, TradeManager tradeManager,
|
||||||
TradeManager tradeManager, Persistence persistence) {
|
BitcoinNetwork bitcoinNetwork, BSFormatter formatter, Persistence persistence) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.walletService = walletService;
|
this.walletService = walletService;
|
||||||
this.messageService = messageService;
|
this.messageService = messageService;
|
||||||
this.tradeManager = tradeManager;
|
this.tradeManager = tradeManager;
|
||||||
this.persistence = persistence;
|
this.formatter = formatter;
|
||||||
|
this.bitcoinNetwork = bitcoinNetwork;
|
||||||
|
|
||||||
|
user.getCurrentBankAccount().addListener((observable, oldValue, newValue) -> persistence.write(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Lifecycle
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
@SuppressWarnings("EmptyMethod")
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
super.initialize();
|
bootstrapState.addListener((ov, oldValue, newValue) -> {
|
||||||
}
|
if (newValue == BootstrapState.DISCOVERY_DIRECT_SUCCEEDED ||
|
||||||
|
newValue == BootstrapState.DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED ||
|
||||||
|
newValue == BootstrapState.RELAY_SUCCEEDED) {
|
||||||
|
bootstrapStateText.set("Successfully connected to P2P network: " + newValue.getMessage());
|
||||||
|
bootstrapProgress.set(1);
|
||||||
|
|
||||||
@SuppressWarnings("EmptyMethod")
|
if (newValue == BootstrapState.DISCOVERY_DIRECT_SUCCEEDED)
|
||||||
@Override
|
bootstrapIconId.set("image-connection-direct");
|
||||||
public void terminate() {
|
else if (newValue == BootstrapState.DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED)
|
||||||
super.terminate();
|
bootstrapIconId.set("image-connection-nat");
|
||||||
}
|
else if (newValue == BootstrapState.RELAY_SUCCEEDED)
|
||||||
|
bootstrapIconId.set("image-connection-relay");
|
||||||
|
}
|
||||||
|
else if (newValue == BootstrapState.PEER_CREATION_FAILED ||
|
||||||
|
newValue == BootstrapState.DISCOVERY_FAILED ||
|
||||||
|
newValue == BootstrapState.DISCOVERY_AUTO_PORT_FORWARDING_FAILED ||
|
||||||
|
newValue == BootstrapState.RELAY_FAILED) {
|
||||||
|
|
||||||
|
bootstrapErrorMsg.set(newValue.getMessage());
|
||||||
|
bootstrapStateText.set("Connection to P2P network failed.");
|
||||||
|
bootstrapProgress.set(0);
|
||||||
|
bootstrapFailed.set(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bootstrapStateText.set("Connecting to P2P network: " + newValue.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
walletServiceException.addListener((ov, oldValue, newValue) -> {
|
||||||
// Public
|
blockchainSyncProgress.set(0);
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
blockchainSyncIndicatorVisible.set(false);
|
||||||
|
blockchainSyncState.set("Startup failed.");
|
||||||
void initBackend() {
|
walletServiceErrorMsg.set(((Throwable) newValue).getMessage());
|
||||||
|
|
||||||
// For testing with the bootstrap node we need the BootstrappedPeerFactory which gets started from
|
|
||||||
// messageService.init
|
|
||||||
|
|
||||||
messageService.init(new BootstrapListener() {
|
|
||||||
@Override
|
|
||||||
public void onCompleted() {
|
|
||||||
messageServiceInited = true;
|
|
||||||
if (walletServiceInited) onServicesInitialised();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed(Throwable throwable) {
|
|
||||||
log.error(throwable.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBootstrapStateChanged(BootstrapState bootstrapState) {
|
|
||||||
MainModel.this.bootstrapState.set(bootstrapState);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Profiler.printMsgWithTime("MainModel.initServices");
|
networkSyncProgress.addListener((ov, oldValue, newValue) -> {
|
||||||
|
setNetworkSyncProgress((double) newValue);
|
||||||
|
|
||||||
WalletService.BlockchainDownloadListener blockchainDownloadListener = new WalletService
|
if ((double) newValue >= 1)
|
||||||
.BlockchainDownloadListener() {
|
blockchainSyncIconId.set("image-connection-synced");
|
||||||
|
});
|
||||||
|
setNetworkSyncProgress(networkSyncProgress.get());
|
||||||
|
|
||||||
|
|
||||||
|
user.getBankAccounts().addListener((ListChangeListener<BankAccount>) change -> {
|
||||||
|
bankAccountsComboBoxDisable.set(change.getList().isEmpty());
|
||||||
|
bankAccountsComboBoxPrompt.set(change.getList().isEmpty() ? "No accounts" : "");
|
||||||
|
});
|
||||||
|
bankAccountsComboBoxDisable.set(user.getBankAccounts().isEmpty());
|
||||||
|
bankAccountsComboBoxPrompt.set(user.getBankAccounts().isEmpty() ? "No accounts" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Observable<?> initBackend() {
|
||||||
|
|
||||||
|
walletService.getDownloadProgress().subscribe(
|
||||||
|
percentage -> Platform.runLater(() -> networkSyncProgress.set(percentage / 100.0)),
|
||||||
|
error -> Platform.runLater(() -> System.out.println("error = " + error)),
|
||||||
|
() -> Platform.runLater(() -> networkSyncProgress.set(1.0)));
|
||||||
|
|
||||||
|
Observable<BootstrapState> message = messageService.init();
|
||||||
|
message.subscribe(
|
||||||
|
state -> Platform.runLater(() -> bootstrapState.set(state)),
|
||||||
|
error -> log.error(error.toString()));
|
||||||
|
|
||||||
|
Observable<Object> wallet = walletService.initialize(Platform::runLater);
|
||||||
|
wallet.subscribe(
|
||||||
|
next -> { },
|
||||||
|
error -> Platform.runLater(() -> walletServiceException.set(error)),
|
||||||
|
() -> { });
|
||||||
|
|
||||||
|
Observable<?> backend = Observable.merge(message, wallet);
|
||||||
|
backend.subscribe(
|
||||||
|
next -> { },
|
||||||
|
error -> { },
|
||||||
|
() -> Platform.runLater(() -> {
|
||||||
|
tradeManager.getPendingTrades().addListener(
|
||||||
|
(MapChangeListener<String, Trade>) change -> updateNumPendingTrades());
|
||||||
|
updateNumPendingTrades();
|
||||||
|
}));
|
||||||
|
|
||||||
|
return backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TradeManager getTradeManager() {
|
||||||
|
return tradeManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringConverter<BankAccount> getBankAccountsConverter() {
|
||||||
|
return new StringConverter<BankAccount>() {
|
||||||
@Override
|
@Override
|
||||||
public void progress(double percentage) {
|
public String toString(BankAccount bankAccount) {
|
||||||
networkSyncProgress.set(percentage / 100.0);
|
return bankAccount.getNameOfBank();
|
||||||
|
|
||||||
if (servicesInitialised && percentage >= 100.0)
|
|
||||||
backendReady.set(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doneDownload() {
|
public BankAccount fromString(String s) {
|
||||||
networkSyncProgress.set(1.0);
|
return null;
|
||||||
|
|
||||||
if (servicesInitialised)
|
|
||||||
backendReady.set(true);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletService.StartupListener startupListener = new WalletService.StartupListener() {
|
|
||||||
@Override
|
|
||||||
public void completed() {
|
|
||||||
walletServiceInited = true;
|
|
||||||
if (messageServiceInited)
|
|
||||||
onServicesInitialised();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void failed(final Throwable failure) {
|
|
||||||
walletServiceException.set(failure);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
walletService.initialize(Platform::runLater, blockchainDownloadListener, startupListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Setters
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void setCurrentBankAccount(BankAccount bankAccount) {
|
|
||||||
user.setCurrentBankAccount(bankAccount);
|
|
||||||
persistence.write(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Getters
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ObservableList<BankAccount> getBankAccounts() {
|
|
||||||
return user.getBankAccounts();
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectProperty<BankAccount> currentBankAccountProperty() {
|
|
||||||
return user.currentBankAccountProperty();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Private
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void onServicesInitialised() {
|
|
||||||
tradeManager.getPendingTrades().addListener((MapChangeListener<String,
|
|
||||||
Trade>) change -> updateNumPendingTrades());
|
|
||||||
updateNumPendingTrades();
|
|
||||||
|
|
||||||
servicesInitialised = true;
|
|
||||||
|
|
||||||
if (networkSyncProgress.get() >= 1.0)
|
|
||||||
backendReady.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateNumPendingTrades() {
|
private void updateNumPendingTrades() {
|
||||||
numPendingTrades.set(tradeManager.getPendingTrades().size());
|
numPendingTrades.set(tradeManager.getPendingTrades().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setNetworkSyncProgress(double value) {
|
||||||
|
blockchainSyncProgress.set(value);
|
||||||
|
if (value >= 1)
|
||||||
|
blockchainSyncState.set("Synchronization completed.");
|
||||||
|
else if (value > 0.0)
|
||||||
|
blockchainSyncState.set("Synchronizing blockchain: " + formatter.formatToPercent(value));
|
||||||
|
else
|
||||||
|
blockchainSyncState.set("Connecting to bitcoin network...");
|
||||||
|
|
||||||
|
blockchainSyncIndicatorVisible.set(value < 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitcoinNetwork getBitcoinNetwork() {
|
||||||
|
return bitcoinNetwork;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,211 +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;
|
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
|
||||||
import io.bitsquare.gui.PresentationModel;
|
|
||||||
import io.bitsquare.gui.util.BSFormatter;
|
|
||||||
import io.bitsquare.network.BootstrapState;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
|
|
||||||
import javafx.beans.property.BooleanProperty;
|
|
||||||
import javafx.beans.property.DoubleProperty;
|
|
||||||
import javafx.beans.property.IntegerProperty;
|
|
||||||
import javafx.beans.property.ObjectProperty;
|
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
|
||||||
import javafx.beans.property.SimpleDoubleProperty;
|
|
||||||
import javafx.beans.property.SimpleIntegerProperty;
|
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
|
||||||
import javafx.beans.property.StringProperty;
|
|
||||||
import javafx.collections.ListChangeListener;
|
|
||||||
import javafx.collections.ObservableList;
|
|
||||||
import javafx.util.StringConverter;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
class MainPM extends PresentationModel<MainModel> {
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(MainPM.class);
|
|
||||||
|
|
||||||
private final BSFormatter formatter;
|
|
||||||
|
|
||||||
final BooleanProperty backendReady = new SimpleBooleanProperty();
|
|
||||||
final StringProperty bankAccountsComboBoxPrompt = new SimpleStringProperty();
|
|
||||||
final BooleanProperty bankAccountsComboBoxDisable = new SimpleBooleanProperty();
|
|
||||||
final IntegerProperty numPendingTrades = new SimpleIntegerProperty();
|
|
||||||
|
|
||||||
final StringProperty blockchainSyncState = new SimpleStringProperty("Initializing");
|
|
||||||
final DoubleProperty blockchainSyncProgress = new SimpleDoubleProperty();
|
|
||||||
final BooleanProperty blockchainSyncIndicatorVisible = new SimpleBooleanProperty(true);
|
|
||||||
final StringProperty blockchainSyncIconId = new SimpleStringProperty();
|
|
||||||
final StringProperty walletServiceErrorMsg = new SimpleStringProperty();
|
|
||||||
|
|
||||||
final DoubleProperty bootstrapProgress = new SimpleDoubleProperty(-1);
|
|
||||||
final BooleanProperty bootstrapFailed = new SimpleBooleanProperty();
|
|
||||||
final StringProperty bootstrapState = new SimpleStringProperty();
|
|
||||||
final StringProperty bootstrapErrorMsg = new SimpleStringProperty();
|
|
||||||
final StringProperty bootstrapIconId = new SimpleStringProperty();
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructor
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private MainPM(MainModel model, BSFormatter formatter) {
|
|
||||||
super(model);
|
|
||||||
this.formatter = formatter;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Lifecycle
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("EmptyMethod")
|
|
||||||
@Override
|
|
||||||
public void initialize() {
|
|
||||||
super.initialize();
|
|
||||||
|
|
||||||
backendReady.bind(model.backendReady);
|
|
||||||
numPendingTrades.bind(model.numPendingTrades);
|
|
||||||
|
|
||||||
model.bootstrapState.addListener((ov, oldValue, newValue) -> {
|
|
||||||
if (newValue == BootstrapState.DISCOVERY_DIRECT_SUCCEEDED ||
|
|
||||||
newValue == BootstrapState.DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED ||
|
|
||||||
newValue == BootstrapState.RELAY_SUCCEEDED) {
|
|
||||||
bootstrapState.set("Successfully connected to P2P network: " + newValue.getMessage());
|
|
||||||
bootstrapProgress.set(1);
|
|
||||||
|
|
||||||
if (newValue == BootstrapState.DISCOVERY_DIRECT_SUCCEEDED)
|
|
||||||
bootstrapIconId.set("image-connection-direct");
|
|
||||||
else if (newValue == BootstrapState.DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED)
|
|
||||||
bootstrapIconId.set("image-connection-nat");
|
|
||||||
else if (newValue == BootstrapState.RELAY_SUCCEEDED)
|
|
||||||
bootstrapIconId.set("image-connection-relay");
|
|
||||||
}
|
|
||||||
else if (newValue == BootstrapState.PEER_CREATION_FAILED ||
|
|
||||||
newValue == BootstrapState.DISCOVERY_FAILED ||
|
|
||||||
newValue == BootstrapState.DISCOVERY_AUTO_PORT_FORWARDING_FAILED ||
|
|
||||||
newValue == BootstrapState.RELAY_FAILED) {
|
|
||||||
|
|
||||||
bootstrapErrorMsg.set(newValue.getMessage());
|
|
||||||
bootstrapState.set("Connection to P2P network failed.");
|
|
||||||
bootstrapProgress.set(0);
|
|
||||||
bootstrapFailed.set(true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bootstrapState.set("Connecting to P2P network: " + newValue.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
model.walletServiceException.addListener((ov, oldValue, newValue) -> {
|
|
||||||
blockchainSyncProgress.set(0);
|
|
||||||
blockchainSyncIndicatorVisible.set(false);
|
|
||||||
blockchainSyncState.set("Startup failed.");
|
|
||||||
walletServiceErrorMsg.set(((Throwable) newValue).getMessage());
|
|
||||||
});
|
|
||||||
|
|
||||||
model.networkSyncProgress.addListener((ov, oldValue, newValue) -> {
|
|
||||||
setNetworkSyncProgress((double) newValue);
|
|
||||||
|
|
||||||
if ((double) newValue >= 1)
|
|
||||||
blockchainSyncIconId.set("image-connection-synced");
|
|
||||||
});
|
|
||||||
setNetworkSyncProgress(model.networkSyncProgress.get());
|
|
||||||
|
|
||||||
|
|
||||||
model.getBankAccounts().addListener((ListChangeListener<BankAccount>) change -> {
|
|
||||||
bankAccountsComboBoxDisable.set(change.getList().isEmpty());
|
|
||||||
bankAccountsComboBoxPrompt.set(change.getList().isEmpty() ? "No accounts" : "");
|
|
||||||
});
|
|
||||||
bankAccountsComboBoxDisable.set(model.getBankAccounts().isEmpty());
|
|
||||||
bankAccountsComboBoxPrompt.set(model.getBankAccounts().isEmpty() ? "No accounts" : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("EmptyMethod")
|
|
||||||
@Override
|
|
||||||
public void terminate() {
|
|
||||||
super.terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Public
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void initBackend() {
|
|
||||||
model.initBackend();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Setters
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void setCurrentBankAccount(BankAccount bankAccount) {
|
|
||||||
model.setCurrentBankAccount(bankAccount);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Getters
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ObservableList<BankAccount> getBankAccounts() {
|
|
||||||
return model.getBankAccounts();
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectProperty<BankAccount> currentBankAccountProperty() {
|
|
||||||
return model.currentBankAccountProperty();
|
|
||||||
}
|
|
||||||
|
|
||||||
StringConverter<BankAccount> getBankAccountsConverter() {
|
|
||||||
return new StringConverter<BankAccount>() {
|
|
||||||
@Override
|
|
||||||
public String toString(BankAccount bankAccount) {
|
|
||||||
return bankAccount.getNameOfBank();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BankAccount fromString(String s) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Private
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void setNetworkSyncProgress(double value) {
|
|
||||||
blockchainSyncProgress.set(value);
|
|
||||||
if (value >= 1)
|
|
||||||
blockchainSyncState.set("Synchronization completed.");
|
|
||||||
else if (value > 0.0)
|
|
||||||
blockchainSyncState.set("Synchronizing blockchain: " + formatter.formatToPercent(value));
|
|
||||||
else
|
|
||||||
blockchainSyncState.set("Connecting to bitcoin network...");
|
|
||||||
|
|
||||||
blockchainSyncIndicatorVisible.set(value < 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -19,7 +19,7 @@ package io.bitsquare.gui.main;
|
|||||||
|
|
||||||
import io.bitsquare.BitsquareException;
|
import io.bitsquare.BitsquareException;
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
import io.bitsquare.btc.BitcoinNetwork;
|
import io.bitsquare.gui.FxmlController;
|
||||||
import io.bitsquare.gui.Navigation;
|
import io.bitsquare.gui.Navigation;
|
||||||
import io.bitsquare.gui.OverlayManager;
|
import io.bitsquare.gui.OverlayManager;
|
||||||
import io.bitsquare.gui.ViewCB;
|
import io.bitsquare.gui.ViewCB;
|
||||||
@ -27,11 +27,6 @@ import io.bitsquare.gui.ViewLoader;
|
|||||||
import io.bitsquare.gui.components.Popups;
|
import io.bitsquare.gui.components.Popups;
|
||||||
import io.bitsquare.gui.components.SystemNotification;
|
import io.bitsquare.gui.components.SystemNotification;
|
||||||
import io.bitsquare.gui.util.Transitions;
|
import io.bitsquare.gui.util.Transitions;
|
||||||
import io.bitsquare.trade.TradeManager;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
@ -50,7 +45,7 @@ import javafx.scene.text.*;
|
|||||||
import static io.bitsquare.gui.Navigation.Item.*;
|
import static io.bitsquare.gui.Navigation.Item.*;
|
||||||
import static javafx.scene.layout.AnchorPane.*;
|
import static javafx.scene.layout.AnchorPane.*;
|
||||||
|
|
||||||
public class MainViewCB extends ViewCB<MainPM> {
|
public class MainViewCB extends FxmlController<Pane, MainModel> {
|
||||||
|
|
||||||
private final ToggleGroup navButtons = new ToggleGroup();
|
private final ToggleGroup navButtons = new ToggleGroup();
|
||||||
|
|
||||||
@ -58,33 +53,28 @@ public class MainViewCB extends ViewCB<MainPM> {
|
|||||||
private final Navigation navigation;
|
private final Navigation navigation;
|
||||||
private final OverlayManager overlayManager;
|
private final OverlayManager overlayManager;
|
||||||
private final Transitions transitions;
|
private final Transitions transitions;
|
||||||
private final BitcoinNetwork bitcoinNetwork;
|
|
||||||
private final String title;
|
private final String title;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public MainViewCB(MainPM presentationModel, ViewLoader viewLoader, Navigation navigation,
|
public MainViewCB(MainModel model, ViewLoader viewLoader, Navigation navigation, OverlayManager overlayManager,
|
||||||
OverlayManager overlayManager, TradeManager tradeManager, Transitions transitions,
|
Transitions transitions, @Named(TITLE_KEY) String title) {
|
||||||
BitcoinNetwork bitcoinNetwork, @Named(TITLE_KEY) String title) {
|
super(model);
|
||||||
super(presentationModel);
|
|
||||||
this.viewLoader = viewLoader;
|
this.viewLoader = viewLoader;
|
||||||
this.navigation = navigation;
|
this.navigation = navigation;
|
||||||
this.overlayManager = overlayManager;
|
this.overlayManager = overlayManager;
|
||||||
this.transitions = transitions;
|
this.transitions = transitions;
|
||||||
this.bitcoinNetwork = bitcoinNetwork;
|
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
|
||||||
tradeManager.featureNotImplementedWarningProperty().addListener((ov, oldValue, newValue) -> {
|
model.getTradeManager().featureNotImplementedWarningProperty().addListener((ov, oldValue, newValue) -> {
|
||||||
if (oldValue == null && newValue != null) {
|
if (oldValue == null && newValue != null) {
|
||||||
Popups.openWarningPopup(newValue);
|
Popups.openWarningPopup(newValue);
|
||||||
tradeManager.setFeatureNotImplementedWarning(null);
|
model.getTradeManager().setFeatureNotImplementedWarning(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle rb) {
|
public void doInitialize() {
|
||||||
super.initialize(url, rb);
|
|
||||||
|
|
||||||
ToggleButton homeButton = new NavButton(HOME) {{
|
ToggleButton homeButton = new NavButton(HOME) {{
|
||||||
setDisable(true); // during irc demo
|
setDisable(true); // during irc demo
|
||||||
}};
|
}};
|
||||||
@ -151,24 +141,26 @@ public class MainViewCB extends ViewCB<MainPM> {
|
|||||||
|
|
||||||
VBox splashScreen = createSplashScreen();
|
VBox splashScreen = createSplashScreen();
|
||||||
|
|
||||||
((Pane) root).getChildren().addAll(baseApplicationContainer, splashScreen);
|
root.getChildren().addAll(baseApplicationContainer, splashScreen);
|
||||||
|
|
||||||
presentationModel.backendReady.addListener((ov1, prev1, ready) -> {
|
Platform.runLater(
|
||||||
if (!ready)
|
() -> model.initBackend().subscribe(
|
||||||
return;
|
next -> { },
|
||||||
|
error -> { },
|
||||||
|
() -> Platform.runLater(() -> {
|
||||||
|
bankAccountComboBoxHolder.getChildren().setAll(createBankAccountComboBox());
|
||||||
|
|
||||||
bankAccountComboBoxHolder.getChildren().setAll(createBankAccountComboBox());
|
applyPendingTradesInfoIcon(model.numPendingTrades.get(), portfolioButtonHolder);
|
||||||
|
model.numPendingTrades.addListener((ov2, prev2, numPendingTrades) ->
|
||||||
|
applyPendingTradesInfoIcon((int) numPendingTrades, portfolioButtonHolder));
|
||||||
|
|
||||||
applyPendingTradesInfoIcon(presentationModel.numPendingTrades.get(), portfolioButtonHolder);
|
navigation.navigateToLastStoredItem();
|
||||||
presentationModel.numPendingTrades.addListener((ov2, prev2, numPendingTrades) ->
|
|
||||||
applyPendingTradesInfoIcon((int) numPendingTrades, portfolioButtonHolder));
|
|
||||||
|
|
||||||
navigation.navigateToLastStoredItem();
|
transitions.fadeOutAndRemove(splashScreen, 1500);
|
||||||
|
}
|
||||||
transitions.fadeOutAndRemove(splashScreen, 1500);
|
)
|
||||||
});
|
)
|
||||||
|
);
|
||||||
Platform.runLater(presentationModel::initBackend);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private VBox createSplashScreen() {
|
private VBox createSplashScreen() {
|
||||||
@ -181,8 +173,8 @@ public class MainViewCB extends ViewCB<MainPM> {
|
|||||||
logo.setId("image-splash-logo");
|
logo.setId("image-splash-logo");
|
||||||
|
|
||||||
Label blockchainSyncLabel = new Label();
|
Label blockchainSyncLabel = new Label();
|
||||||
blockchainSyncLabel.textProperty().bind(presentationModel.blockchainSyncState);
|
blockchainSyncLabel.textProperty().bind(model.blockchainSyncState);
|
||||||
presentationModel.walletServiceErrorMsg.addListener((ov, oldValue, newValue) -> {
|
model.walletServiceErrorMsg.addListener((ov, oldValue, newValue) -> {
|
||||||
blockchainSyncLabel.setId("splash-error-state-msg");
|
blockchainSyncLabel.setId("splash-error-state-msg");
|
||||||
Popups.openErrorPopup("Error", "An error occurred at startup. \n\nError message:\n" +
|
Popups.openErrorPopup("Error", "An error occurred at startup. \n\nError message:\n" +
|
||||||
newValue);
|
newValue);
|
||||||
@ -190,13 +182,13 @@ public class MainViewCB extends ViewCB<MainPM> {
|
|||||||
|
|
||||||
ProgressBar blockchainSyncIndicator = new ProgressBar(-1);
|
ProgressBar blockchainSyncIndicator = new ProgressBar(-1);
|
||||||
blockchainSyncIndicator.setPrefWidth(120);
|
blockchainSyncIndicator.setPrefWidth(120);
|
||||||
blockchainSyncIndicator.progressProperty().bind(presentationModel.blockchainSyncProgress);
|
blockchainSyncIndicator.progressProperty().bind(model.blockchainSyncProgress);
|
||||||
|
|
||||||
ImageView blockchainSyncIcon = new ImageView();
|
ImageView blockchainSyncIcon = new ImageView();
|
||||||
blockchainSyncIcon.setVisible(false);
|
blockchainSyncIcon.setVisible(false);
|
||||||
blockchainSyncIcon.setManaged(false);
|
blockchainSyncIcon.setManaged(false);
|
||||||
|
|
||||||
presentationModel.blockchainSyncIconId.addListener((ov, oldValue, newValue) -> {
|
model.blockchainSyncIconId.addListener((ov, oldValue, newValue) -> {
|
||||||
blockchainSyncIcon.setId(newValue);
|
blockchainSyncIcon.setId(newValue);
|
||||||
blockchainSyncIcon.setVisible(true);
|
blockchainSyncIcon.setVisible(true);
|
||||||
blockchainSyncIcon.setManaged(true);
|
blockchainSyncIcon.setManaged(true);
|
||||||
@ -206,7 +198,7 @@ public class MainViewCB extends ViewCB<MainPM> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Label bitcoinNetworkLabel = new Label();
|
Label bitcoinNetworkLabel = new Label();
|
||||||
bitcoinNetworkLabel.setText(bitcoinNetwork.toString());
|
bitcoinNetworkLabel.setText(model.getBitcoinNetwork().toString());
|
||||||
bitcoinNetworkLabel.setId("splash-bitcoin-network-label");
|
bitcoinNetworkLabel.setId("splash-bitcoin-network-label");
|
||||||
|
|
||||||
HBox blockchainSyncBox = new HBox();
|
HBox blockchainSyncBox = new HBox();
|
||||||
@ -221,19 +213,19 @@ public class MainViewCB extends ViewCB<MainPM> {
|
|||||||
bootstrapStateLabel.setWrapText(true);
|
bootstrapStateLabel.setWrapText(true);
|
||||||
bootstrapStateLabel.setMaxWidth(500);
|
bootstrapStateLabel.setMaxWidth(500);
|
||||||
bootstrapStateLabel.setTextAlignment(TextAlignment.CENTER);
|
bootstrapStateLabel.setTextAlignment(TextAlignment.CENTER);
|
||||||
bootstrapStateLabel.textProperty().bind(presentationModel.bootstrapState);
|
bootstrapStateLabel.textProperty().bind(model.bootstrapStateText);
|
||||||
|
|
||||||
ProgressIndicator bootstrapIndicator = new ProgressIndicator();
|
ProgressIndicator bootstrapIndicator = new ProgressIndicator();
|
||||||
bootstrapIndicator.setMaxSize(24, 24);
|
bootstrapIndicator.setMaxSize(24, 24);
|
||||||
bootstrapIndicator.progressProperty().bind(presentationModel.bootstrapProgress);
|
bootstrapIndicator.progressProperty().bind(model.bootstrapProgress);
|
||||||
|
|
||||||
presentationModel.bootstrapFailed.addListener((ov, oldValue, newValue) -> {
|
model.bootstrapFailed.addListener((ov, oldValue, newValue) -> {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
bootstrapStateLabel.setId("splash-error-state-msg");
|
bootstrapStateLabel.setId("splash-error-state-msg");
|
||||||
bootstrapIndicator.setVisible(false);
|
bootstrapIndicator.setVisible(false);
|
||||||
|
|
||||||
Popups.openErrorPopup("Error", "Cannot connect to P2P network. \n\nError message:\n" +
|
Popups.openErrorPopup("Error", "Cannot connect to P2P network. \n\nError message:\n" +
|
||||||
presentationModel.bootstrapErrorMsg.get());
|
model.bootstrapErrorMsg.get());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -241,7 +233,7 @@ public class MainViewCB extends ViewCB<MainPM> {
|
|||||||
bootstrapIcon.setVisible(false);
|
bootstrapIcon.setVisible(false);
|
||||||
bootstrapIcon.setManaged(false);
|
bootstrapIcon.setManaged(false);
|
||||||
|
|
||||||
presentationModel.bootstrapIconId.addListener((ov, oldValue, newValue) -> {
|
model.bootstrapIconId.addListener((ov, oldValue, newValue) -> {
|
||||||
bootstrapIcon.setId(newValue);
|
bootstrapIcon.setId(newValue);
|
||||||
bootstrapIcon.setVisible(true);
|
bootstrapIcon.setVisible(true);
|
||||||
bootstrapIcon.setManaged(true);
|
bootstrapIcon.setManaged(true);
|
||||||
@ -262,21 +254,21 @@ public class MainViewCB extends ViewCB<MainPM> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private VBox createBankAccountComboBox() {
|
private VBox createBankAccountComboBox() {
|
||||||
final ComboBox<BankAccount> comboBox = new ComboBox<>(presentationModel.getBankAccounts());
|
final ComboBox<BankAccount> comboBox = new ComboBox<>(model.getUser().getBankAccounts());
|
||||||
comboBox.setLayoutY(12);
|
comboBox.setLayoutY(12);
|
||||||
comboBox.setVisibleRowCount(5);
|
comboBox.setVisibleRowCount(5);
|
||||||
comboBox.setConverter(presentationModel.getBankAccountsConverter());
|
comboBox.setConverter(model.getBankAccountsConverter());
|
||||||
|
|
||||||
comboBox.valueProperty().addListener((ov, oldValue, newValue) ->
|
comboBox.valueProperty().addListener((ov, oldValue, newValue) ->
|
||||||
presentationModel.setCurrentBankAccount(newValue));
|
model.getUser().setCurrentBankAccount(newValue));
|
||||||
|
|
||||||
comboBox.disableProperty().bind(presentationModel.bankAccountsComboBoxDisable);
|
comboBox.disableProperty().bind(model.bankAccountsComboBoxDisable);
|
||||||
comboBox.promptTextProperty().bind(presentationModel.bankAccountsComboBoxPrompt);
|
comboBox.promptTextProperty().bind(model.bankAccountsComboBoxPrompt);
|
||||||
|
|
||||||
presentationModel.currentBankAccountProperty().addListener((ov, oldValue, newValue) ->
|
model.getUser().currentBankAccountProperty().addListener((ov, oldValue, newValue) ->
|
||||||
comboBox.getSelectionModel().select(newValue));
|
comboBox.getSelectionModel().select(newValue));
|
||||||
|
|
||||||
comboBox.getSelectionModel().select(presentationModel.currentBankAccountProperty().get());
|
comboBox.getSelectionModel().select(model.getUser().currentBankAccountProperty().get());
|
||||||
|
|
||||||
final Label titleLabel = new Label("Bank account");
|
final Label titleLabel = new Label("Bank account");
|
||||||
titleLabel.setMouseTransparent(true);
|
titleLabel.setMouseTransparent(true);
|
||||||
|
@ -152,7 +152,7 @@ class CreateOfferModel extends UIModel {
|
|||||||
if (user != null) {
|
if (user != null) {
|
||||||
user.currentBankAccountProperty().addListener((ov, oldValue, newValue) -> applyBankAccount(newValue));
|
user.currentBankAccountProperty().addListener((ov, oldValue, newValue) -> applyBankAccount(newValue));
|
||||||
|
|
||||||
applyBankAccount(user.getCurrentBankAccount());
|
applyBankAccount(user.getCurrentBankAccount().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accountSettings != null)
|
if (accountSettings != null)
|
||||||
|
@ -171,7 +171,7 @@ public class OfferBook {
|
|||||||
// TODO Just temporary, will be removed later when we have a push solution
|
// TODO Just temporary, will be removed later when we have a push solution
|
||||||
private void startPolling() {
|
private void startPolling() {
|
||||||
addListeners();
|
addListeners();
|
||||||
setBankAccount(user.getCurrentBankAccount());
|
setBankAccount(user.getCurrentBankAccount().get());
|
||||||
pollingTimer = Utilities.setInterval(3000, (animationTimer) -> {
|
pollingTimer = Utilities.setInterval(3000, (animationTimer) -> {
|
||||||
offerRepository.requestInvalidationTimeStampFromDHT(fiatCode);
|
offerRepository.requestInvalidationTimeStampFromDHT(fiatCode);
|
||||||
return null;
|
return null;
|
||||||
|
@ -121,7 +121,7 @@ class OfferBookModel extends UIModel {
|
|||||||
user.currentBankAccountProperty().addListener(bankAccountChangeListener);
|
user.currentBankAccountProperty().addListener(bankAccountChangeListener);
|
||||||
btcCode.bind(preferences.btcDenominationProperty());
|
btcCode.bind(preferences.btcDenominationProperty());
|
||||||
|
|
||||||
setBankAccount(user.getCurrentBankAccount());
|
setBankAccount(user.getCurrentBankAccount().get());
|
||||||
applyFilter();
|
applyFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,16 +181,18 @@ class OfferBookModel extends UIModel {
|
|||||||
|
|
||||||
boolean isTradable(Offer offer) {
|
boolean isTradable(Offer offer) {
|
||||||
// if user has not registered yet we display all
|
// if user has not registered yet we display all
|
||||||
if (user.getCurrentBankAccount() == null)
|
BankAccount currentBankAccount = user.getCurrentBankAccount().get();
|
||||||
|
if (currentBankAccount == null)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
boolean countryResult = offer.getAcceptedCountries().contains(user.getCurrentBankAccount().getCountry());
|
boolean countryResult = offer.getAcceptedCountries().contains(currentBankAccount.getCountry());
|
||||||
// for IRC test version deactivate the check
|
// for IRC test version deactivate the check
|
||||||
countryResult = true;
|
countryResult = true;
|
||||||
if (!countryResult)
|
if (!countryResult)
|
||||||
restrictionsInfo.set("This offer requires that the payments account resides in one of those countries:\n" +
|
restrictionsInfo.set("This offer requires that the payments account resides in one of those countries:\n" +
|
||||||
formatter.countryLocalesToString(offer.getAcceptedCountries()) +
|
formatter.countryLocalesToString(offer.getAcceptedCountries()) +
|
||||||
"\n\nThe country of your payments account (" + user.getCurrentBankAccount().getCountry().getName() +
|
"\n\nThe country of your payments account (" + user.getCurrentBankAccount().get().getCountry()
|
||||||
|
.getName() +
|
||||||
") is not included in that list." +
|
") is not included in that list." +
|
||||||
"\n\n Do you want to edit your preferences now?");
|
"\n\n Do you want to edit your preferences now?");
|
||||||
|
|
||||||
|
@ -19,16 +19,18 @@ package io.bitsquare.msg;
|
|||||||
|
|
||||||
import io.bitsquare.arbitrator.Arbitrator;
|
import io.bitsquare.arbitrator.Arbitrator;
|
||||||
import io.bitsquare.msg.listeners.ArbitratorListener;
|
import io.bitsquare.msg.listeners.ArbitratorListener;
|
||||||
import io.bitsquare.msg.listeners.BootstrapListener;
|
|
||||||
import io.bitsquare.msg.listeners.GetPeerAddressListener;
|
import io.bitsquare.msg.listeners.GetPeerAddressListener;
|
||||||
import io.bitsquare.msg.listeners.IncomingMessageListener;
|
import io.bitsquare.msg.listeners.IncomingMessageListener;
|
||||||
import io.bitsquare.msg.listeners.OutgoingMessageListener;
|
import io.bitsquare.msg.listeners.OutgoingMessageListener;
|
||||||
|
import io.bitsquare.network.BootstrapState;
|
||||||
import io.bitsquare.network.Peer;
|
import io.bitsquare.network.Peer;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import rx.Observable;
|
||||||
|
|
||||||
public interface MessageService extends MessageBroker {
|
public interface MessageService extends MessageBroker {
|
||||||
|
|
||||||
void sendMessage(Peer peer, Message message, OutgoingMessageListener listener);
|
void sendMessage(Peer peer, Message message, OutgoingMessageListener listener);
|
||||||
@ -45,7 +47,7 @@ public interface MessageService extends MessageBroker {
|
|||||||
|
|
||||||
void getArbitrators(Locale defaultLanguageLocale);
|
void getArbitrators(Locale defaultLanguageLocale);
|
||||||
|
|
||||||
void init(BootstrapListener bootstrapListener);
|
Observable<BootstrapState> init();
|
||||||
|
|
||||||
void getPeerAddress(PublicKey messagePublicKey, GetPeerAddressListener getPeerAddressListener);
|
void getPeerAddress(PublicKey messagePublicKey, GetPeerAddressListener getPeerAddressListener);
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,10 @@ import io.bitsquare.arbitrator.Arbitrator;
|
|||||||
import io.bitsquare.msg.Message;
|
import io.bitsquare.msg.Message;
|
||||||
import io.bitsquare.msg.MessageService;
|
import io.bitsquare.msg.MessageService;
|
||||||
import io.bitsquare.msg.listeners.ArbitratorListener;
|
import io.bitsquare.msg.listeners.ArbitratorListener;
|
||||||
import io.bitsquare.msg.listeners.BootstrapListener;
|
|
||||||
import io.bitsquare.msg.listeners.GetPeerAddressListener;
|
import io.bitsquare.msg.listeners.GetPeerAddressListener;
|
||||||
import io.bitsquare.msg.listeners.IncomingMessageListener;
|
import io.bitsquare.msg.listeners.IncomingMessageListener;
|
||||||
import io.bitsquare.msg.listeners.OutgoingMessageListener;
|
import io.bitsquare.msg.listeners.OutgoingMessageListener;
|
||||||
|
import io.bitsquare.network.BootstrapState;
|
||||||
import io.bitsquare.network.Peer;
|
import io.bitsquare.network.Peer;
|
||||||
import io.bitsquare.network.tomp2p.TomP2PPeer;
|
import io.bitsquare.network.tomp2p.TomP2PPeer;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
@ -55,6 +55,8 @@ import net.tomp2p.utils.Utils;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import rx.Observable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* That service delivers direct messaging and DHT functionality from the TomP2P library
|
* That service delivers direct messaging and DHT functionality from the TomP2P library
|
||||||
@ -90,10 +92,8 @@ class TomP2PMessageService implements MessageService {
|
|||||||
// Public Methods
|
// Public Methods
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void init(BootstrapListener bootstrapListener) {
|
public Observable<BootstrapState> init() {
|
||||||
p2pNode.setMessageBroker(this);
|
return p2pNode.bootstrap(this, user.getMessageKeyPair());
|
||||||
p2pNode.setKeyPair(user.getMessageKeyPair());
|
|
||||||
p2pNode.bootstrap(bootstrapListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutDown() {
|
public void shutDown() {
|
||||||
|
@ -19,7 +19,6 @@ package io.bitsquare.msg.tomp2p;
|
|||||||
|
|
||||||
import io.bitsquare.BitsquareException;
|
import io.bitsquare.BitsquareException;
|
||||||
import io.bitsquare.msg.MessageBroker;
|
import io.bitsquare.msg.MessageBroker;
|
||||||
import io.bitsquare.msg.listeners.BootstrapListener;
|
|
||||||
import io.bitsquare.network.BootstrapState;
|
import io.bitsquare.network.BootstrapState;
|
||||||
import io.bitsquare.network.ClientNode;
|
import io.bitsquare.network.ClientNode;
|
||||||
import io.bitsquare.network.ConnectionType;
|
import io.bitsquare.network.ConnectionType;
|
||||||
@ -43,8 +42,6 @@ import javax.annotation.Nullable;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
|
||||||
|
|
||||||
import net.tomp2p.dht.FutureGet;
|
import net.tomp2p.dht.FutureGet;
|
||||||
import net.tomp2p.dht.FuturePut;
|
import net.tomp2p.dht.FuturePut;
|
||||||
import net.tomp2p.dht.FutureRemove;
|
import net.tomp2p.dht.FutureRemove;
|
||||||
@ -62,6 +59,10 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import rx.Observable;
|
||||||
|
import rx.subjects.BehaviorSubject;
|
||||||
|
import rx.subjects.Subject;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,21 +106,17 @@ public class TomP2PNode implements ClientNode {
|
|||||||
// Public methods
|
// Public methods
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void setMessageBroker(MessageBroker messageBroker) {
|
public Observable<BootstrapState> bootstrap(MessageBroker messageBroker, KeyPair keyPair) {
|
||||||
this.messageBroker = messageBroker;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKeyPair(@NotNull KeyPair keyPair) {
|
|
||||||
this.keyPair = keyPair;
|
|
||||||
bootstrappedPeerFactory.setKeyPair(keyPair);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bootstrap(BootstrapListener bootstrapListener) {
|
|
||||||
checkNotNull(keyPair, "keyPair must not be null.");
|
checkNotNull(keyPair, "keyPair must not be null.");
|
||||||
checkNotNull(messageBroker, "messageBroker must not be null.");
|
checkNotNull(messageBroker, "messageBroker must not be null.");
|
||||||
|
|
||||||
bootstrappedPeerFactory.getBootstrapState().addListener((ov, oldValue, newValue) ->
|
this.messageBroker = messageBroker;
|
||||||
bootstrapListener.onBootstrapStateChanged(newValue));
|
this.keyPair = keyPair;
|
||||||
|
bootstrappedPeerFactory.setKeyPair(keyPair);
|
||||||
|
|
||||||
|
Subject<BootstrapState, BootstrapState> bootstrapState = BehaviorSubject.create();
|
||||||
|
|
||||||
|
bootstrappedPeerFactory.getBootstrapState().addListener((ov, oldValue, newValue) -> bootstrapState.onNext(newValue));
|
||||||
|
|
||||||
SettableFuture<PeerDHT> bootstrapFuture = bootstrappedPeerFactory.start();
|
SettableFuture<PeerDHT> bootstrapFuture = bootstrappedPeerFactory.start();
|
||||||
Futures.addCallback(bootstrapFuture, new FutureCallback<PeerDHT>() {
|
Futures.addCallback(bootstrapFuture, new FutureCallback<PeerDHT>() {
|
||||||
@ -132,23 +129,24 @@ public class TomP2PNode implements ClientNode {
|
|||||||
try {
|
try {
|
||||||
storeAddress();
|
storeAddress();
|
||||||
} catch (NetworkException e) {
|
} catch (NetworkException e) {
|
||||||
Platform.runLater(() -> bootstrapListener.onFailed(e));
|
bootstrapState.onError(e);
|
||||||
}
|
}
|
||||||
Platform.runLater(bootstrapListener::onCompleted);
|
bootstrapState.onCompleted();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.error("Error at bootstrap: peerDHT = null");
|
log.error("Error at bootstrap: peerDHT = null");
|
||||||
Platform.runLater(() -> bootstrapListener.onFailed(
|
bootstrapState.onError(new BitsquareException("Error at bootstrap: peerDHT = null"));
|
||||||
new BitsquareException("Error at bootstrap: peerDHT = null")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(@NotNull Throwable t) {
|
public void onFailure(@NotNull Throwable t) {
|
||||||
log.error("Exception at bootstrap " + t.getMessage());
|
log.error("Exception at bootstrap " + t.getMessage());
|
||||||
Platform.runLater(() -> bootstrapListener.onFailed(t));
|
bootstrapState.onError(t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return bootstrapState.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutDown() {
|
public void shutDown() {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package io.bitsquare.trade;
|
package io.bitsquare.trade;
|
||||||
|
|
||||||
import io.bitsquare.account.AccountSettings;
|
import io.bitsquare.account.AccountSettings;
|
||||||
|
import io.bitsquare.bank.BankAccount;
|
||||||
import io.bitsquare.btc.BlockChainService;
|
import io.bitsquare.btc.BlockChainService;
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.btc.WalletService;
|
||||||
import io.bitsquare.crypto.SignatureService;
|
import io.bitsquare.crypto.SignatureService;
|
||||||
@ -55,6 +56,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
@ -152,16 +154,17 @@ public class TradeManager {
|
|||||||
TransactionResultHandler resultHandler,
|
TransactionResultHandler resultHandler,
|
||||||
ErrorMessageHandler errorMessageHandler) {
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
|
|
||||||
|
BankAccount currentBankAccount = user.getCurrentBankAccount().get();
|
||||||
Offer offer = new Offer(id,
|
Offer offer = new Offer(id,
|
||||||
user.getMessagePublicKey(),
|
user.getMessagePublicKey(),
|
||||||
direction,
|
direction,
|
||||||
price.getValue(),
|
price.getValue(),
|
||||||
amount,
|
amount,
|
||||||
minAmount,
|
minAmount,
|
||||||
user.getCurrentBankAccount().getBankAccountType(),
|
currentBankAccount.getBankAccountType(),
|
||||||
user.getCurrentBankAccount().getCurrency(),
|
currentBankAccount.getCurrency(),
|
||||||
user.getCurrentBankAccount().getCountry(),
|
currentBankAccount.getCountry(),
|
||||||
user.getCurrentBankAccount().getUid(),
|
currentBankAccount.getUid(),
|
||||||
accountSettings.getAcceptedArbitrators(),
|
accountSettings.getAcceptedArbitrators(),
|
||||||
accountSettings.getSecurityDeposit(),
|
accountSettings.getSecurityDeposit(),
|
||||||
accountSettings.getAcceptedCountries(),
|
accountSettings.getAcceptedCountries(),
|
||||||
|
@ -154,7 +154,7 @@ public class SellerTakesOfferProtocol {
|
|||||||
|
|
||||||
peersMessagePublicKey = offer.getMessagePublicKey();
|
peersMessagePublicKey = offer.getMessagePublicKey();
|
||||||
|
|
||||||
bankAccount = user.getCurrentBankAccount();
|
bankAccount = user.getCurrentBankAccount().get();
|
||||||
accountId = user.getAccountId();
|
accountId = user.getAccountId();
|
||||||
messagePublicKey = user.getMessagePublicKey();
|
messagePublicKey = user.getMessagePublicKey();
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ public class User implements Serializable {
|
|||||||
return bankAccounts;
|
return bankAccounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BankAccount getCurrentBankAccount() {
|
public ObjectProperty<BankAccount> getCurrentBankAccount() {
|
||||||
return currentBankAccount.get();
|
return currentBankAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BankAccount getBankAccount(String bankAccountId) {
|
public BankAccount getBankAccount(String bankAccountId) {
|
||||||
|
Loading…
Reference in New Issue
Block a user