mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-11-17 00:07:49 +00:00
show daemon sync progress on startup then sync wallet
This commit is contained in:
parent
846b278b5d
commit
d094997666
17 changed files with 119 additions and 86 deletions
|
@ -2,6 +2,7 @@ package haveno.core.api;
|
||||||
|
|
||||||
import haveno.common.UserThread;
|
import haveno.common.UserThread;
|
||||||
import haveno.common.app.DevEnv;
|
import haveno.common.app.DevEnv;
|
||||||
|
import haveno.common.config.BaseCurrencyNetwork;
|
||||||
import haveno.common.config.Config;
|
import haveno.common.config.Config;
|
||||||
import haveno.core.trade.HavenoUtils;
|
import haveno.core.trade.HavenoUtils;
|
||||||
import haveno.core.user.Preferences;
|
import haveno.core.user.Preferences;
|
||||||
|
@ -69,6 +70,7 @@ public final class CoreMoneroConnectionsService {
|
||||||
private MoneroDaemonRpc daemon;
|
private MoneroDaemonRpc daemon;
|
||||||
@Getter
|
@Getter
|
||||||
private MoneroDaemonInfo lastInfo;
|
private MoneroDaemonInfo lastInfo;
|
||||||
|
private Long syncStartHeight = null;
|
||||||
private TaskLooper daemonPollLooper;
|
private TaskLooper daemonPollLooper;
|
||||||
private boolean isShutDownStarted;
|
private boolean isShutDownStarted;
|
||||||
private List<MoneroConnectionManagerListener> listeners = new ArrayList<>();
|
private List<MoneroConnectionManagerListener> listeners = new ArrayList<>();
|
||||||
|
@ -299,17 +301,12 @@ public final class CoreMoneroConnectionsService {
|
||||||
return downloadPercentageProperty().get() == 1d;
|
return downloadPercentageProperty().get() == 1d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ------------------------------- HELPERS --------------------------------
|
||||||
* Signals that both the daemon and wallet have synced.
|
|
||||||
*
|
private void doneDownload() {
|
||||||
* TODO: separate daemon and wallet download/done listeners
|
|
||||||
*/
|
|
||||||
public void doneDownload() {
|
|
||||||
downloadListener.doneDownload();
|
downloadListener.doneDownload();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------- HELPERS --------------------------------
|
|
||||||
|
|
||||||
private boolean isConnectionLocal(MoneroRpcConnection connection) {
|
private boolean isConnectionLocal(MoneroRpcConnection connection) {
|
||||||
return connection != null && HavenoUtils.isLocalHost(connection.getUri());
|
return connection != null && HavenoUtils.isLocalHost(connection.getUri());
|
||||||
}
|
}
|
||||||
|
@ -555,11 +552,26 @@ public final class CoreMoneroConnectionsService {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (isShutDownStarted) return;
|
if (isShutDownStarted) return;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// poll daemon
|
||||||
log.debug("Polling daemon info");
|
log.debug("Polling daemon info");
|
||||||
if (daemon == null) throw new RuntimeException("No daemon connection");
|
if (daemon == null) throw new RuntimeException("No daemon connection");
|
||||||
lastInfo = daemon.getInfo();
|
lastInfo = daemon.getInfo();
|
||||||
|
|
||||||
|
// set chain height
|
||||||
chainHeight.set(lastInfo.getHeight());
|
chainHeight.set(lastInfo.getHeight());
|
||||||
|
|
||||||
|
// update sync progress
|
||||||
|
boolean isTestnet = Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_LOCAL;
|
||||||
|
if (lastInfo.isSynchronized() || isTestnet) doneDownload(); // TODO: skipping synchronized check for testnet because tests cannot sync 3rd local node, see "Can manage Monero daemon connections"
|
||||||
|
else if (lastInfo.isBusySyncing()) {
|
||||||
|
long targetHeight = lastInfo.getTargetHeight();
|
||||||
|
long blocksLeft = targetHeight - lastInfo.getHeight();
|
||||||
|
if (syncStartHeight == null) syncStartHeight = lastInfo.getHeight();
|
||||||
|
double percent = ((double) Math.max(1, lastInfo.getHeight() - syncStartHeight) / (double) (targetHeight - syncStartHeight)) * 100d; // grant at least 1 block to show progress
|
||||||
|
downloadListener.progress(percent, blocksLeft, null);
|
||||||
|
}
|
||||||
|
|
||||||
// set peer connections
|
// set peer connections
|
||||||
// TODO: peers often uknown due to restricted RPC call, skipping call to get peer connections
|
// TODO: peers often uknown due to restricted RPC call, skipping call to get peer connections
|
||||||
// try {
|
// try {
|
||||||
|
|
|
@ -19,6 +19,7 @@ package haveno.core.app;
|
||||||
|
|
||||||
import haveno.core.api.CoreMoneroConnectionsService;
|
import haveno.core.api.CoreMoneroConnectionsService;
|
||||||
import haveno.core.api.CoreNotificationService;
|
import haveno.core.api.CoreNotificationService;
|
||||||
|
import haveno.core.xmr.wallet.XmrWalletService;
|
||||||
import haveno.network.p2p.BootstrapListener;
|
import haveno.network.p2p.BootstrapListener;
|
||||||
import haveno.network.p2p.P2PService;
|
import haveno.network.p2p.P2PService;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
|
@ -47,11 +48,13 @@ public class AppStartupState {
|
||||||
private final BooleanProperty applicationFullyInitialized = new SimpleBooleanProperty();
|
private final BooleanProperty applicationFullyInitialized = new SimpleBooleanProperty();
|
||||||
private final BooleanProperty updatedDataReceived = new SimpleBooleanProperty();
|
private final BooleanProperty updatedDataReceived = new SimpleBooleanProperty();
|
||||||
private final BooleanProperty isBlockDownloadComplete = new SimpleBooleanProperty();
|
private final BooleanProperty isBlockDownloadComplete = new SimpleBooleanProperty();
|
||||||
|
private final BooleanProperty isWalletSynced = new SimpleBooleanProperty();
|
||||||
private final BooleanProperty hasSufficientPeersForBroadcast = new SimpleBooleanProperty();
|
private final BooleanProperty hasSufficientPeersForBroadcast = new SimpleBooleanProperty();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AppStartupState(CoreNotificationService notificationService,
|
public AppStartupState(CoreNotificationService notificationService,
|
||||||
CoreMoneroConnectionsService connectionsService,
|
CoreMoneroConnectionsService connectionsService,
|
||||||
|
XmrWalletService xmrWalletService,
|
||||||
P2PService p2PService) {
|
P2PService p2PService) {
|
||||||
|
|
||||||
p2PService.addP2PServiceListener(new BootstrapListener() {
|
p2PService.addP2PServiceListener(new BootstrapListener() {
|
||||||
|
@ -66,6 +69,11 @@ public class AppStartupState {
|
||||||
isBlockDownloadComplete.set(true);
|
isBlockDownloadComplete.set(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
xmrWalletService.downloadPercentageProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
if (xmrWalletService.isWalletSynced())
|
||||||
|
isWalletSynced.set(true);
|
||||||
|
});
|
||||||
|
|
||||||
connectionsService.numPeersProperty().addListener((observable, oldValue, newValue) -> {
|
connectionsService.numPeersProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
if (connectionsService.hasSufficientPeersForBroadcast())
|
if (connectionsService.hasSufficientPeersForBroadcast())
|
||||||
hasSufficientPeersForBroadcast.set(true);
|
hasSufficientPeersForBroadcast.set(true);
|
||||||
|
@ -73,14 +81,15 @@ public class AppStartupState {
|
||||||
|
|
||||||
p2pNetworkAndWalletInitialized = EasyBind.combine(updatedDataReceived,
|
p2pNetworkAndWalletInitialized = EasyBind.combine(updatedDataReceived,
|
||||||
isBlockDownloadComplete,
|
isBlockDownloadComplete,
|
||||||
|
isWalletSynced,
|
||||||
hasSufficientPeersForBroadcast, // TODO: consider sufficient number of peers?
|
hasSufficientPeersForBroadcast, // TODO: consider sufficient number of peers?
|
||||||
allDomainServicesInitialized,
|
allDomainServicesInitialized,
|
||||||
(a, b, c, d) -> {
|
(a, b, c, d, e) -> {
|
||||||
log.info("Combined initialized state = {} = updatedDataReceived={} && isBlockDownloadComplete={} && hasSufficientPeersForBroadcast={} && allDomainServicesInitialized={}", (a && b && c && d), updatedDataReceived.get(), isBlockDownloadComplete.get(), hasSufficientPeersForBroadcast.get(), allDomainServicesInitialized.get());
|
log.info("Combined initialized state = {} = updatedDataReceived={} && isBlockDownloadComplete={} && isWalletSynced={} && hasSufficientPeersForBroadcast={} && allDomainServicesInitialized={}", (a && b && c && d && e), updatedDataReceived.get(), isBlockDownloadComplete.get(), isWalletSynced.get(), hasSufficientPeersForBroadcast.get(), allDomainServicesInitialized.get());
|
||||||
if (a && b) {
|
if (a && b && c) {
|
||||||
walletAndNetworkReady.set(true);
|
walletAndNetworkReady.set(true);
|
||||||
}
|
}
|
||||||
return a && d; // app fully initialized before daemon connection and wallet by default // TODO: rename variable
|
return a && e; // app fully initialized before daemon connection and wallet by default
|
||||||
});
|
});
|
||||||
p2pNetworkAndWalletInitialized.subscribe((observable, oldValue, newValue) -> {
|
p2pNetworkAndWalletInitialized.subscribe((observable, oldValue, newValue) -> {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
|
@ -136,6 +145,10 @@ public class AppStartupState {
|
||||||
return isBlockDownloadComplete.get();
|
return isBlockDownloadComplete.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isWalletSynced() {
|
||||||
|
return isWalletSynced.get();
|
||||||
|
}
|
||||||
|
|
||||||
public ReadOnlyBooleanProperty isBlockDownloadCompleteProperty() {
|
public ReadOnlyBooleanProperty isBlockDownloadCompleteProperty() {
|
||||||
return isBlockDownloadComplete;
|
return isBlockDownloadComplete;
|
||||||
}
|
}
|
||||||
|
|
|
@ -438,7 +438,7 @@ public class HavenoSetup {
|
||||||
revolutAccountsUpdateHandler,
|
revolutAccountsUpdateHandler,
|
||||||
amazonGiftCardAccountsUpdateHandler);
|
amazonGiftCardAccountsUpdateHandler);
|
||||||
|
|
||||||
if (walletsSetup.downloadPercentageProperty().get() == 1) { // TODO: update for XMR
|
if (xmrWalletService.downloadPercentageProperty().get() == 1) {
|
||||||
checkForLockedUpFunds();
|
checkForLockedUpFunds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import haveno.core.xmr.exceptions.InvalidHostException;
|
||||||
import haveno.core.xmr.exceptions.RejectedTxException;
|
import haveno.core.xmr.exceptions.RejectedTxException;
|
||||||
import haveno.core.xmr.setup.WalletsSetup;
|
import haveno.core.xmr.setup.WalletsSetup;
|
||||||
import haveno.core.xmr.wallet.WalletsManager;
|
import haveno.core.xmr.wallet.WalletsManager;
|
||||||
|
import haveno.core.xmr.wallet.XmrWalletService;
|
||||||
import javafx.beans.property.DoubleProperty;
|
import javafx.beans.property.DoubleProperty;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleDoubleProperty;
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
|
@ -39,9 +40,8 @@ import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import monero.common.MoneroUtils;
|
||||||
import org.bitcoinj.core.RejectMessage;
|
import org.bitcoinj.core.RejectMessage;
|
||||||
import org.bitcoinj.core.VersionMessage;
|
|
||||||
import org.bitcoinj.store.BlockStoreException;
|
import org.bitcoinj.store.BlockStoreException;
|
||||||
import org.bitcoinj.store.ChainFileLockedException;
|
import org.bitcoinj.store.ChainFileLockedException;
|
||||||
import org.fxmisc.easybind.EasyBind;
|
import org.fxmisc.easybind.EasyBind;
|
||||||
|
@ -61,6 +61,7 @@ public class WalletAppSetup {
|
||||||
private final WalletsManager walletsManager;
|
private final WalletsManager walletsManager;
|
||||||
private final WalletsSetup walletsSetup;
|
private final WalletsSetup walletsSetup;
|
||||||
private final CoreMoneroConnectionsService connectionService;
|
private final CoreMoneroConnectionsService connectionService;
|
||||||
|
private final XmrWalletService xmrWalletService;
|
||||||
private final Config config;
|
private final Config config;
|
||||||
private final Preferences preferences;
|
private final Preferences preferences;
|
||||||
|
|
||||||
|
@ -85,12 +86,14 @@ public class WalletAppSetup {
|
||||||
WalletsManager walletsManager,
|
WalletsManager walletsManager,
|
||||||
WalletsSetup walletsSetup,
|
WalletsSetup walletsSetup,
|
||||||
CoreMoneroConnectionsService connectionService,
|
CoreMoneroConnectionsService connectionService,
|
||||||
|
XmrWalletService xmrWalletService,
|
||||||
Config config,
|
Config config,
|
||||||
Preferences preferences) {
|
Preferences preferences) {
|
||||||
this.coreContext = coreContext;
|
this.coreContext = coreContext;
|
||||||
this.walletsManager = walletsManager;
|
this.walletsManager = walletsManager;
|
||||||
this.walletsSetup = walletsSetup;
|
this.walletsSetup = walletsSetup;
|
||||||
this.connectionService = connectionService;
|
this.connectionService = connectionService;
|
||||||
|
this.xmrWalletService = xmrWalletService;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.preferences = preferences;
|
this.preferences = preferences;
|
||||||
this.useTorForXmr.set(preferences.getUseTorForXmr());
|
this.useTorForXmr.set(preferences.getUseTorForXmr());
|
||||||
|
@ -101,18 +104,21 @@ public class WalletAppSetup {
|
||||||
@Nullable Runnable showPopupIfInvalidBtcConfigHandler,
|
@Nullable Runnable showPopupIfInvalidBtcConfigHandler,
|
||||||
Runnable downloadCompleteHandler,
|
Runnable downloadCompleteHandler,
|
||||||
Runnable walletInitializedHandler) {
|
Runnable walletInitializedHandler) {
|
||||||
log.info("Initialize WalletAppSetup with BitcoinJ version {} and hash of BitcoinJ commit {}",
|
log.info("Initialize WalletAppSetup with monero-java version {}", MoneroUtils.getVersion());
|
||||||
VersionMessage.BITCOINJ_VERSION, "2a80db4");
|
|
||||||
|
|
||||||
ObjectProperty<Throwable> walletServiceException = new SimpleObjectProperty<>();
|
ObjectProperty<Throwable> walletServiceException = new SimpleObjectProperty<>();
|
||||||
xmrInfoBinding = EasyBind.combine(connectionService.downloadPercentageProperty(), // TODO (woodser): update to XMR
|
xmrInfoBinding = EasyBind.combine(connectionService.downloadPercentageProperty(),
|
||||||
connectionService.chainHeightProperty(),
|
connectionService.chainHeightProperty(),
|
||||||
|
xmrWalletService.downloadPercentageProperty(),
|
||||||
|
xmrWalletService.walletHeightProperty(),
|
||||||
walletServiceException,
|
walletServiceException,
|
||||||
getWalletServiceErrorMsg(),
|
getWalletServiceErrorMsg(),
|
||||||
(downloadPercentage, chainHeight, exception, errorMsg) -> {
|
(chainDownloadPercentage, chainHeight, walletDownloadPercentage, walletHeight, exception, errorMsg) -> {
|
||||||
String result;
|
String result;
|
||||||
if (exception == null && errorMsg == null) {
|
if (exception == null && errorMsg == null) {
|
||||||
double percentage = (double) downloadPercentage;
|
|
||||||
|
// TODO: update for daemon and wallet sync progress
|
||||||
|
double percentage = (double) chainDownloadPercentage;
|
||||||
xmrSyncProgress.set(percentage);
|
xmrSyncProgress.set(percentage);
|
||||||
Long bestChainHeight = chainHeight == null ? null : (Long) chainHeight;
|
Long bestChainHeight = chainHeight == null ? null : (Long) chainHeight;
|
||||||
String chainHeightAsString = bestChainHeight != null && bestChainHeight > 0 ?
|
String chainHeightAsString = bestChainHeight != null && bestChainHeight > 0 ?
|
||||||
|
|
|
@ -120,8 +120,10 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
private final KeyRing keyRing;
|
private final KeyRing keyRing;
|
||||||
private final User user;
|
private final User user;
|
||||||
private final P2PService p2PService;
|
private final P2PService p2PService;
|
||||||
|
@Getter
|
||||||
private final CoreMoneroConnectionsService connectionsService;
|
private final CoreMoneroConnectionsService connectionsService;
|
||||||
private final BtcWalletService btcWalletService;
|
private final BtcWalletService btcWalletService;
|
||||||
|
@Getter
|
||||||
private final XmrWalletService xmrWalletService;
|
private final XmrWalletService xmrWalletService;
|
||||||
private final TradeWalletService tradeWalletService;
|
private final TradeWalletService tradeWalletService;
|
||||||
private final OfferBookService offerBookService;
|
private final OfferBookService offerBookService;
|
||||||
|
|
|
@ -31,6 +31,7 @@ import haveno.core.trade.Trade;
|
||||||
import haveno.core.trade.TradeManager;
|
import haveno.core.trade.TradeManager;
|
||||||
import haveno.core.trade.protocol.TradeProtocol;
|
import haveno.core.trade.protocol.TradeProtocol;
|
||||||
import haveno.core.trade.protocol.TradeProtocol.MailboxMessageComparator;
|
import haveno.core.trade.protocol.TradeProtocol.MailboxMessageComparator;
|
||||||
|
import haveno.core.xmr.wallet.XmrWalletService;
|
||||||
import haveno.network.p2p.AckMessage;
|
import haveno.network.p2p.AckMessage;
|
||||||
import haveno.network.p2p.AckMessageSourceType;
|
import haveno.network.p2p.AckMessageSourceType;
|
||||||
import haveno.network.p2p.DecryptedMessageWithPubKey;
|
import haveno.network.p2p.DecryptedMessageWithPubKey;
|
||||||
|
@ -53,6 +54,7 @@ public abstract class SupportManager {
|
||||||
protected final P2PService p2PService;
|
protected final P2PService p2PService;
|
||||||
protected final TradeManager tradeManager;
|
protected final TradeManager tradeManager;
|
||||||
protected final CoreMoneroConnectionsService connectionService;
|
protected final CoreMoneroConnectionsService connectionService;
|
||||||
|
protected final XmrWalletService xmrWalletService;
|
||||||
protected final CoreNotificationService notificationService;
|
protected final CoreNotificationService notificationService;
|
||||||
protected final Map<String, Timer> delayMsgMap = new HashMap<>();
|
protected final Map<String, Timer> delayMsgMap = new HashMap<>();
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
|
@ -68,10 +70,12 @@ public abstract class SupportManager {
|
||||||
|
|
||||||
public SupportManager(P2PService p2PService,
|
public SupportManager(P2PService p2PService,
|
||||||
CoreMoneroConnectionsService connectionService,
|
CoreMoneroConnectionsService connectionService,
|
||||||
|
XmrWalletService xmrWalletService,
|
||||||
CoreNotificationService notificationService,
|
CoreNotificationService notificationService,
|
||||||
TradeManager tradeManager) {
|
TradeManager tradeManager) {
|
||||||
this.p2PService = p2PService;
|
this.p2PService = p2PService;
|
||||||
this.connectionService = connectionService;
|
this.connectionService = connectionService;
|
||||||
|
this.xmrWalletService = xmrWalletService;
|
||||||
this.mailboxMessageService = p2PService.getMailboxMessageService();
|
this.mailboxMessageService = p2PService.getMailboxMessageService();
|
||||||
this.notificationService = notificationService;
|
this.notificationService = notificationService;
|
||||||
this.tradeManager = tradeManager;
|
this.tradeManager = tradeManager;
|
||||||
|
@ -333,7 +337,8 @@ public abstract class SupportManager {
|
||||||
return allServicesInitialized &&
|
return allServicesInitialized &&
|
||||||
p2PService.isBootstrapped() &&
|
p2PService.isBootstrapped() &&
|
||||||
connectionService.isDownloadComplete() &&
|
connectionService.isDownloadComplete() &&
|
||||||
connectionService.hasSufficientPeersForBroadcast();
|
connectionService.hasSufficientPeersForBroadcast() &&
|
||||||
|
xmrWalletService.isWalletSynced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
||||||
DisputeListService<T> disputeListService,
|
DisputeListService<T> disputeListService,
|
||||||
Config config,
|
Config config,
|
||||||
PriceFeedService priceFeedService) {
|
PriceFeedService priceFeedService) {
|
||||||
super(p2PService, connectionService, notificationService, tradeManager);
|
super(p2PService, connectionService, xmrWalletService, notificationService, tradeManager);
|
||||||
|
|
||||||
this.tradeWalletService = tradeWalletService;
|
this.tradeWalletService = tradeWalletService;
|
||||||
this.xmrWalletService = xmrWalletService;
|
this.xmrWalletService = xmrWalletService;
|
||||||
|
@ -257,6 +257,11 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
||||||
tryApplyMessages();
|
tryApplyMessages();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
xmrWalletService.downloadPercentageProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
if (xmrWalletService.isWalletSynced())
|
||||||
|
tryApplyMessages();
|
||||||
|
});
|
||||||
|
|
||||||
connectionService.numPeersProperty().addListener((observable, oldValue, newValue) -> {
|
connectionService.numPeersProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
if (connectionService.hasSufficientPeersForBroadcast())
|
if (connectionService.hasSufficientPeersForBroadcast())
|
||||||
tryApplyMessages();
|
tryApplyMessages();
|
||||||
|
|
|
@ -28,6 +28,7 @@ import haveno.core.support.messages.ChatMessage;
|
||||||
import haveno.core.support.messages.SupportMessage;
|
import haveno.core.support.messages.SupportMessage;
|
||||||
import haveno.core.trade.Trade;
|
import haveno.core.trade.Trade;
|
||||||
import haveno.core.trade.TradeManager;
|
import haveno.core.trade.TradeManager;
|
||||||
|
import haveno.core.xmr.wallet.XmrWalletService;
|
||||||
import haveno.network.p2p.AckMessageSourceType;
|
import haveno.network.p2p.AckMessageSourceType;
|
||||||
import haveno.network.p2p.NodeAddress;
|
import haveno.network.p2p.NodeAddress;
|
||||||
import haveno.network.p2p.P2PService;
|
import haveno.network.p2p.P2PService;
|
||||||
|
@ -53,10 +54,11 @@ public class TraderChatManager extends SupportManager {
|
||||||
@Inject
|
@Inject
|
||||||
public TraderChatManager(P2PService p2PService,
|
public TraderChatManager(P2PService p2PService,
|
||||||
CoreMoneroConnectionsService connectionService,
|
CoreMoneroConnectionsService connectionService,
|
||||||
|
XmrWalletService xmrWalletService,
|
||||||
CoreNotificationService notificationService,
|
CoreNotificationService notificationService,
|
||||||
TradeManager tradeManager,
|
TradeManager tradeManager,
|
||||||
PubKeyRingProvider pubKeyRingProvider) {
|
PubKeyRingProvider pubKeyRingProvider) {
|
||||||
super(p2PService, connectionService, notificationService, tradeManager);
|
super(p2PService, connectionService, xmrWalletService, notificationService, tradeManager);
|
||||||
this.pubKeyRingProvider = pubKeyRingProvider;
|
this.pubKeyRingProvider = pubKeyRingProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ public class Balances {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateBalances() {
|
private void updateBalances() {
|
||||||
if (!xmrWalletService.isWalletReady()) return;
|
if (!xmrWalletService.isWalletAvailable()) return;
|
||||||
try {
|
try {
|
||||||
updateAvailableBalance();
|
updateAvailableBalance();
|
||||||
updatePendingBalance();
|
updatePendingBalance();
|
||||||
|
@ -94,7 +94,7 @@ public class Balances {
|
||||||
updateReservedTradeBalance();
|
updateReservedTradeBalance();
|
||||||
updateReservedBalance();
|
updateReservedBalance();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (xmrWalletService.isWalletReady()) throw e; // ignore exception if wallet isn't ready
|
if (xmrWalletService.isWalletAvailable()) throw e; // ignore exception if wallet isn't ready
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import java.util.Date;
|
||||||
public class DownloadListener {
|
public class DownloadListener {
|
||||||
private final DoubleProperty percentage = new SimpleDoubleProperty(-1);
|
private final DoubleProperty percentage = new SimpleDoubleProperty(-1);
|
||||||
|
|
||||||
public void progress(double percentage, int blocksLeft, Date date) {
|
public void progress(double percentage, long blocksLeft, Date date) {
|
||||||
UserThread.execute(() -> this.percentage.set(percentage / 100d));
|
UserThread.execute(() -> this.percentage.set(percentage / 100d));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.bitcoinj.core.Context;
|
||||||
import org.bitcoinj.core.NetworkParameters;
|
import org.bitcoinj.core.NetworkParameters;
|
||||||
import org.bitcoinj.core.PeerAddress;
|
import org.bitcoinj.core.PeerAddress;
|
||||||
import org.bitcoinj.core.PeerGroup;
|
import org.bitcoinj.core.PeerGroup;
|
||||||
import org.bitcoinj.core.listeners.DownloadProgressTracker;
|
|
||||||
import org.bitcoinj.crypto.KeyCrypter;
|
import org.bitcoinj.crypto.KeyCrypter;
|
||||||
import org.bitcoinj.net.discovery.PeerDiscovery;
|
import org.bitcoinj.net.discovery.PeerDiscovery;
|
||||||
import org.bitcoinj.script.Script;
|
import org.bitcoinj.script.Script;
|
||||||
|
@ -92,7 +91,6 @@ public class WalletConfig extends AbstractIdleService {
|
||||||
protected volatile File vBtcWalletFile;
|
protected volatile File vBtcWalletFile;
|
||||||
|
|
||||||
protected PeerAddress[] peerAddresses;
|
protected PeerAddress[] peerAddresses;
|
||||||
protected DownloadListener downloadListener;
|
|
||||||
protected InputStream checkpoints;
|
protected InputStream checkpoints;
|
||||||
protected String userAgent, version;
|
protected String userAgent, version;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -169,15 +167,6 @@ public class WalletConfig extends AbstractIdleService {
|
||||||
return setPeerNodes(new PeerAddress(params, localHost, params.getPort()));
|
return setPeerNodes(new PeerAddress(params, localHost, params.getPort()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If you want to learn about the sync process, you can provide a listener here. For instance, a
|
|
||||||
* {@link DownloadProgressTracker} is a good choice.
|
|
||||||
*/
|
|
||||||
public WalletConfig setDownloadListener(DownloadListener listener) {
|
|
||||||
this.downloadListener = listener;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set, the file is expected to contain a checkpoints file calculated with BuildCheckpoints. It makes initial
|
* If set, the file is expected to contain a checkpoints file calculated with BuildCheckpoints. It makes initial
|
||||||
* block sync faster for new users - please refer to the documentation on the bitcoinj website
|
* block sync faster for new users - please refer to the documentation on the bitcoinj website
|
||||||
|
|
|
@ -42,13 +42,7 @@ import haveno.core.xmr.nodes.XmrNodesSetupPreferences;
|
||||||
import haveno.network.Socks5MultiDiscovery;
|
import haveno.network.Socks5MultiDiscovery;
|
||||||
import haveno.network.Socks5ProxyProvider;
|
import haveno.network.Socks5ProxyProvider;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.IntegerProperty;
|
|
||||||
import javafx.beans.property.LongProperty;
|
|
||||||
import javafx.beans.property.ReadOnlyDoubleProperty;
|
|
||||||
import javafx.beans.property.ReadOnlyIntegerProperty;
|
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.property.SimpleIntegerProperty;
|
|
||||||
import javafx.beans.property.SimpleLongProperty;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -107,9 +101,6 @@ public class WalletsSetup {
|
||||||
private final NetworkParameters params;
|
private final NetworkParameters params;
|
||||||
private final File walletDir;
|
private final File walletDir;
|
||||||
private final int socks5DiscoverMode;
|
private final int socks5DiscoverMode;
|
||||||
private final IntegerProperty numPeers = new SimpleIntegerProperty(0);
|
|
||||||
private final LongProperty chainHeight = new SimpleLongProperty(0);
|
|
||||||
private final DownloadListener downloadListener = new DownloadListener();
|
|
||||||
private final List<Runnable> setupTaskHandlers = new ArrayList<>();
|
private final List<Runnable> setupTaskHandlers = new ArrayList<>();
|
||||||
private final List<Runnable> setupCompletedHandlers = new ArrayList<>();
|
private final List<Runnable> setupCompletedHandlers = new ArrayList<>();
|
||||||
public final BooleanProperty shutDownComplete = new SimpleBooleanProperty();
|
public final BooleanProperty shutDownComplete = new SimpleBooleanProperty();
|
||||||
|
@ -172,12 +163,12 @@ public class WalletsSetup {
|
||||||
backupWallets();
|
backupWallets();
|
||||||
|
|
||||||
final Socks5Proxy socks5Proxy = socks5ProxyProvider.getSocks5Proxy();
|
final Socks5Proxy socks5Proxy = socks5ProxyProvider.getSocks5Proxy();
|
||||||
log.info("Socks5Proxy for bitcoinj: socks5Proxy=" + socks5Proxy);
|
log.info("Using Socks5Proxy: " + socks5Proxy);
|
||||||
|
|
||||||
walletConfig = new WalletConfig(params, walletDir, "haveno") {
|
walletConfig = new WalletConfig(params, walletDir, "haveno") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSetupCompleted() {
|
protected void onSetupCompleted() {
|
||||||
//We are here in the btcj thread Thread[ STARTING,5,main]
|
|
||||||
super.onSetupCompleted();
|
super.onSetupCompleted();
|
||||||
|
|
||||||
// run external startup handlers
|
// run external startup handlers
|
||||||
|
@ -244,8 +235,6 @@ public class WalletsSetup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
walletConfig.setDownloadListener(downloadListener);
|
|
||||||
|
|
||||||
// If seed is non-null it means we are restoring from backup.
|
// If seed is non-null it means we are restoring from backup.
|
||||||
if (seed != null) {
|
if (seed != null) {
|
||||||
walletConfig.restoreWalletFromSeed(seed);
|
walletConfig.restoreWalletFromSeed(seed);
|
||||||
|
@ -430,26 +419,6 @@ public class WalletsSetup {
|
||||||
return walletConfig;
|
return walletConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlyIntegerProperty numPeersProperty() {
|
|
||||||
return numPeers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LongProperty chainHeightProperty() {
|
|
||||||
return chainHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReadOnlyDoubleProperty downloadPercentageProperty() {
|
|
||||||
return downloadListener.percentageProperty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDownloadComplete() {
|
|
||||||
return downloadPercentageProperty().get() == 1d;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isChainHeightSyncedWithinTolerance() {
|
|
||||||
throw new RuntimeException("WalletsSetup.isChainHeightSyncedWithinTolerance() not implemented for BTC");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Address> getAddressesByContext(@SuppressWarnings("SameParameterValue") AddressEntry.Context context) {
|
public Set<Address> getAddressesByContext(@SuppressWarnings("SameParameterValue") AddressEntry.Context context) {
|
||||||
return addressEntryList.getAddressEntriesAsListImmutable().stream()
|
return addressEntryList.getAddressEntriesAsListImmutable().stream()
|
||||||
.filter(addressEntry -> addressEntry.getContext() == context)
|
.filter(addressEntry -> addressEntry.getContext() == context)
|
||||||
|
@ -463,10 +432,6 @@ public class WalletsSetup {
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasSufficientPeersForBroadcast() {
|
|
||||||
return numPeers.get() >= getMinBroadcastConnections();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMinBroadcastConnections() {
|
public int getMinBroadcastConnections() {
|
||||||
return walletConfig.getMinBroadcastConnections();
|
return walletConfig.getMinBroadcastConnections();
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,10 @@ public class BtcWalletService extends WalletService {
|
||||||
// Overridden Methods
|
// Overridden Methods
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public boolean isWalletSyncedWithinTolerance() {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void decryptWallet(@NotNull KeyParameter key) {
|
void decryptWallet(@NotNull KeyParameter key) {
|
||||||
super.decryptWallet(key);
|
super.decryptWallet(key);
|
||||||
|
|
|
@ -538,9 +538,7 @@ public abstract class WalletService {
|
||||||
return isWalletReady() && chain != null ? chain.getBestChainHeight() : 0;
|
return isWalletReady() && chain != null ? chain.getBestChainHeight() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChainHeightSyncedWithinTolerance() {
|
public abstract boolean isWalletSyncedWithinTolerance();
|
||||||
return walletsSetup.isChainHeightSyncedWithinTolerance();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Transaction getClonedTransaction(Transaction tx) {
|
public Transaction getClonedTransaction(Transaction tx) {
|
||||||
return new Transaction(params, tx.bitcoinSerialize());
|
return new Transaction(params, tx.bitcoinSerialize());
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class WalletsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean areWalletsAvailable() {
|
public boolean areWalletsAvailable() {
|
||||||
return xmrWalletService.isWalletReady();
|
return xmrWalletService.isWalletAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyCrypterScrypt getKeyCrypterScrypt() {
|
public KeyCrypterScrypt getKeyCrypterScrypt() {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import haveno.core.user.Preferences;
|
||||||
import haveno.core.xmr.listeners.XmrBalanceListener;
|
import haveno.core.xmr.listeners.XmrBalanceListener;
|
||||||
import haveno.core.xmr.model.XmrAddressEntry;
|
import haveno.core.xmr.model.XmrAddressEntry;
|
||||||
import haveno.core.xmr.model.XmrAddressEntryList;
|
import haveno.core.xmr.model.XmrAddressEntryList;
|
||||||
|
import haveno.core.xmr.setup.DownloadListener;
|
||||||
import haveno.core.xmr.setup.MoneroWalletRpcManager;
|
import haveno.core.xmr.setup.MoneroWalletRpcManager;
|
||||||
import haveno.core.xmr.setup.WalletsSetup;
|
import haveno.core.xmr.setup.WalletsSetup;
|
||||||
import monero.common.MoneroError;
|
import monero.common.MoneroError;
|
||||||
|
@ -69,11 +70,15 @@ import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import javafx.beans.property.LongProperty;
|
||||||
|
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||||
|
import javafx.beans.property.SimpleLongProperty;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
|
@ -104,6 +109,8 @@ public class XmrWalletService {
|
||||||
private final CoreMoneroConnectionsService connectionsService;
|
private final CoreMoneroConnectionsService connectionsService;
|
||||||
private final XmrAddressEntryList xmrAddressEntryList;
|
private final XmrAddressEntryList xmrAddressEntryList;
|
||||||
private final WalletsSetup walletsSetup;
|
private final WalletsSetup walletsSetup;
|
||||||
|
private final DownloadListener downloadListener = new DownloadListener();
|
||||||
|
private final LongProperty walletHeight = new SimpleLongProperty(0);
|
||||||
|
|
||||||
private final File walletDir;
|
private final File walletDir;
|
||||||
private final File xmrWalletFile;
|
private final File xmrWalletFile;
|
||||||
|
@ -196,7 +203,7 @@ public class XmrWalletService {
|
||||||
saveWallet(getWallet(), backup);
|
saveWallet(getWallet(), backup);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWalletReady() {
|
public boolean isWalletAvailable() {
|
||||||
try {
|
try {
|
||||||
return getWallet() != null;
|
return getWallet() != null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -208,6 +215,22 @@ public class XmrWalletService {
|
||||||
return accountService.getPassword() != null;
|
return accountService.getPassword() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isWalletSynced() {
|
||||||
|
return downloadPercentageProperty().get() == 1d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyDoubleProperty downloadPercentageProperty() {
|
||||||
|
return downloadListener.percentageProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doneDownload() {
|
||||||
|
downloadListener.doneDownload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LongProperty walletHeightProperty() {
|
||||||
|
return walletHeight;
|
||||||
|
}
|
||||||
|
|
||||||
public MoneroDaemonRpc getDaemon() {
|
public MoneroDaemonRpc getDaemon() {
|
||||||
return connectionsService.getDaemon();
|
return connectionsService.getDaemon();
|
||||||
}
|
}
|
||||||
|
@ -651,12 +674,19 @@ public class XmrWalletService {
|
||||||
|
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
|
|
||||||
// set and listen to daemon connection
|
// listen for connection changes
|
||||||
connectionsService.addConnectionListener(newConnection -> {
|
connectionsService.addConnectionListener(newConnection -> onConnectionChanged(newConnection));
|
||||||
onConnectionChanged(newConnection);
|
|
||||||
});
|
|
||||||
|
|
||||||
// initialize main wallet if connected or previously created
|
// wait for monerod to sync
|
||||||
|
if (connectionsService.downloadPercentageProperty().get() != 1) {
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
connectionsService.downloadPercentageProperty().addListener((obs, oldVal, newVal) -> {
|
||||||
|
if (connectionsService.downloadPercentageProperty().get() == 1) latch.countDown();
|
||||||
|
});
|
||||||
|
HavenoUtils.awaitLatch(latch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize main wallet
|
||||||
maybeInitMainWallet(true);
|
maybeInitMainWallet(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,8 +730,8 @@ public class XmrWalletService {
|
||||||
// reapply connection after wallet synced
|
// reapply connection after wallet synced
|
||||||
onConnectionChanged(connectionsService.getConnection());
|
onConnectionChanged(connectionsService.getConnection());
|
||||||
|
|
||||||
// TODO: using this to signify both daemon and wallet synced, use separate sync handlers?
|
// signal that main wallet is synced
|
||||||
connectionsService.doneDownload();
|
doneDownload();
|
||||||
|
|
||||||
// notify setup that main wallet is initialized
|
// notify setup that main wallet is initialized
|
||||||
// TODO: app fully initializes after this is set to true, even though wallet might not be initialized if unconnected. wallet will be created when connection detected
|
// TODO: app fully initializes after this is set to true, even though wallet might not be initialized if unconnected. wallet will be created when connection detected
|
||||||
|
@ -1242,6 +1272,7 @@ public class XmrWalletService {
|
||||||
UserThread.execute(new Runnable() {
|
UserThread.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
walletHeight.set(height);
|
||||||
for (MoneroWalletListenerI listener : walletListeners) listener.onNewBlock(height);
|
for (MoneroWalletListenerI listener : walletListeners) listener.onNewBlock(height);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -553,6 +553,7 @@ abstract class OfferBookViewModel extends ActivatableViewModel {
|
||||||
|
|
||||||
boolean canCreateOrTakeOffer() {
|
boolean canCreateOrTakeOffer() {
|
||||||
return GUIUtil.canCreateOrTakeOfferOrShowPopup(user, navigation) &&
|
return GUIUtil.canCreateOrTakeOfferOrShowPopup(user, navigation) &&
|
||||||
|
GUIUtil.isChainHeightSyncedWithinToleranceOrShowPopup(openOfferManager.getConnectionsService()) &&
|
||||||
GUIUtil.isBootstrappedOrShowPopup(p2PService);
|
GUIUtil.isBootstrappedOrShowPopup(p2PService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue