refactor monero connection initialization

re-prioritize default connections
monero network status turns red on connection error
remove popup on connection error
remove popup on 0 monero peers which aren't reported
increase main wallet max sync attempts on startup
renames from btc to xmr
This commit is contained in:
woodser 2023-07-30 09:14:22 -04:00
parent 12b6585779
commit 473100620e
23 changed files with 283 additions and 325 deletions

View File

@ -36,7 +36,6 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Slf4j @Slf4j
@ -368,67 +367,6 @@ public final class CoreMoneroConnectionsService {
connectionManager.reset(); connectionManager.reset();
connectionManager.setTimeout(REFRESH_PERIOD_HTTP_MS); connectionManager.setTimeout(REFRESH_PERIOD_HTTP_MS);
// load previous or default connections
if (coreContext.isApiUser()) {
// load previous connections
for (MoneroRpcConnection connection : connectionList.getConnections()) connectionManager.addConnection(connection);
log.info("Read " + connectionList.getConnections().size() + " previous connections from disk");
// add default connections
for (XmrNode node : xmrNodes.getAllXmrNodes()) {
if (node.hasClearNetAddress()) {
MoneroRpcConnection connection = new MoneroRpcConnection(node.getAddress() + ":" + node.getPort()).setPriority(node.getPriority());
if (!connectionList.hasConnection(connection.getUri())) addConnection(connection);
}
if (node.hasOnionAddress()) {
MoneroRpcConnection connection = new MoneroRpcConnection(node.getOnionAddress() + ":" + node.getPort()).setPriority(node.getPriority());
if (!connectionList.hasConnection(connection.getUri())) addConnection(connection);
}
}
} else {
// add default connections
for (XmrNode node : xmrNodes.selectPreferredNodes(new XmrNodesSetupPreferences(preferences))) {
if (node.hasClearNetAddress()) {
MoneroRpcConnection connection = new MoneroRpcConnection(node.getAddress() + ":" + node.getPort()).setPriority(node.getPriority());
addConnection(connection);
}
if (node.hasOnionAddress()) {
MoneroRpcConnection connection = new MoneroRpcConnection(node.getOnionAddress() + ":" + node.getPort()).setPriority(node.getPriority());
addConnection(connection);
}
}
}
// set current connection
Optional<String> currentConnectionUri = Optional.empty();
if ("".equals(config.xmrNode)) {
if (coreContext.isApiUser() && connectionList.getCurrentConnectionUri().isPresent()) {
currentConnectionUri = connectionList.getCurrentConnectionUri();
connectionManager.setConnection(currentConnectionUri.get());
}
} else if (!isInitialized) {
// set monero connection from startup arguments
MoneroRpcConnection connection = new MoneroRpcConnection(config.xmrNode, config.xmrNodeUsername, config.xmrNodePassword).setPriority(1);
if (useProxy(connection)) connection.setProxyUri(getProxyUri());
connectionManager.setConnection(connection);
currentConnectionUri = Optional.of(connection.getUri());
}
// set connection proxies
log.info("TOR proxy URI: " + getProxyUri());
for (MoneroRpcConnection connection : connectionManager.getConnections()) {
if (useProxy(connection)) connection.setProxyUri(getProxyUri());
}
// restore configuration
if ("".equals(config.xmrNode)) connectionManager.setAutoSwitch(connectionList.getAutoSwitch());
// check connection
checkConnection();
// run once // run once
if (!isInitialized) { if (!isInitialized) {
@ -439,6 +377,7 @@ public final class CoreMoneroConnectionsService {
log.info(getClass() + ".onNodeStarted() called"); log.info(getClass() + ".onNodeStarted() called");
daemon.getRpcConnection().checkConnection(connectionManager.getTimeout()); daemon.getRpcConnection().checkConnection(connectionManager.getTimeout());
setConnection(daemon.getRpcConnection()); setConnection(daemon.getRpcConnection());
checkConnection();
} }
@Override @Override
@ -449,43 +388,88 @@ public final class CoreMoneroConnectionsService {
}); });
} }
// if offline and last connection is local node, start local node if it's offline // restore connections
currentConnectionUri.ifPresent(uri -> { if ("".equals(config.xmrNode)) {
try {
if (!connectionManager.isConnected() && nodeService.equalsUri(uri) && !nodeService.isOnline()) { // load previous or default connections
if (coreContext.isApiUser()) {
// load previous connections
for (MoneroRpcConnection connection : connectionList.getConnections()) connectionManager.addConnection(connection);
log.info("Read " + connectionList.getConnections().size() + " previous connections from disk");
// add default connections
for (XmrNode node : xmrNodes.getAllXmrNodes()) {
if (node.hasClearNetAddress()) {
MoneroRpcConnection connection = new MoneroRpcConnection(node.getAddress() + ":" + node.getPort()).setPriority(node.getPriority());
if (!connectionList.hasConnection(connection.getUri())) addConnection(connection);
}
if (node.hasOnionAddress()) {
MoneroRpcConnection connection = new MoneroRpcConnection(node.getOnionAddress() + ":" + node.getPort()).setPriority(node.getPriority());
if (!connectionList.hasConnection(connection.getUri())) addConnection(connection);
}
}
} else {
// add default connections
for (XmrNode node : xmrNodes.selectPreferredNodes(new XmrNodesSetupPreferences(preferences))) {
if (node.hasClearNetAddress()) {
MoneroRpcConnection connection = new MoneroRpcConnection(node.getAddress() + ":" + node.getPort()).setPriority(node.getPriority());
addConnection(connection);
}
if (node.hasOnionAddress()) {
MoneroRpcConnection connection = new MoneroRpcConnection(node.getOnionAddress() + ":" + node.getPort()).setPriority(node.getPriority());
addConnection(connection);
}
}
}
// restore last connection
if (connectionList.getCurrentConnectionUri().isPresent()) {
connectionManager.setConnection(connectionList.getCurrentConnectionUri().get());
}
// set connection proxies
log.info("TOR proxy URI: " + getProxyUri());
for (MoneroRpcConnection connection : connectionManager.getConnections()) {
if (useProxy(connection)) connection.setProxyUri(getProxyUri());
}
// restore auto switch
if (coreContext.isApiUser()) connectionManager.setAutoSwitch(connectionList.getAutoSwitch());
else connectionManager.setAutoSwitch(true);
// start local node if used as last connection and currently offline
if (connectionManager.getConnection() != null && nodeService.equalsUri(connectionManager.getConnection().getUri()) && !nodeService.isOnline()) {
try {
log.info("Starting local node"); log.info("Starting local node");
nodeService.startMoneroNode(); nodeService.startMoneroNode();
} catch (Exception e) {
log.warn("Unable to start local monero node: " + e.getMessage());
e.printStackTrace();
} }
} catch (Exception e) {
log.warn("Unable to start local monero node: " + e.getMessage());
e.printStackTrace();
} }
});
// prefer to connect to local node unless prevented by configuration // update connection
if ("".equals(config.xmrNode) && if (connectionManager.getConnection() == null || connectionManager.getAutoSwitch()) {
(!connectionManager.isConnected() || connectionManager.getAutoSwitch()) && setConnection(getBestAvailableConnection());
nodeService.isConnected()) { } else {
MoneroRpcConnection connection = connectionManager.getConnectionByUri(nodeService.getDaemon().getRpcConnection().getUri()); checkConnection();
if (connection != null) {
connection.checkConnection(connectionManager.getTimeout());
setConnection(connection);
} }
} else if (!isInitialized) {
// set connection from startup argument if given
connectionManager.setAutoSwitch(false);
MoneroRpcConnection connection = new MoneroRpcConnection(config.xmrNode, config.xmrNodeUsername, config.xmrNodePassword).setPriority(1);
if (useProxy(connection)) connection.setProxyUri(getProxyUri());
connectionManager.setConnection(connection);
} }
// if using legacy desktop app, connect to best available connection // register connection listener
if (!coreContext.isApiUser() && "".equals(config.xmrNode)) {
connectionManager.setAutoSwitch(true);
MoneroRpcConnection bestConnection = connectionManager.getBestAvailableConnection();
log.info("Setting best available connection for monerod: " + (bestConnection == null ? null : bestConnection.getUri()));
connectionManager.setConnection(bestConnection);
}
// register connection change listener
connectionManager.addListener(this::onConnectionChanged); connectionManager.addListener(this::onConnectionChanged);
isInitialized = true;
// update connection state // notify final connection
isInitialized = true;
onConnectionChanged(connectionManager.getConnection()); onConnectionChanged(connectionManager.getConnection());
} }
} }
@ -556,10 +540,11 @@ public final class CoreMoneroConnectionsService {
numPeers.set(lastInfo.getNumOutgoingConnections() + lastInfo.getNumIncomingConnections()); numPeers.set(lastInfo.getNumOutgoingConnections() + lastInfo.getNumIncomingConnections());
peers.set(new ArrayList<MoneroPeer>()); peers.set(new ArrayList<MoneroPeer>());
// log recovery message // handle error recovery
if (lastErrorTimestamp != null) { if (lastErrorTimestamp != null) {
log.info("Successfully fetched daemon info after previous error"); log.info("Successfully fetched daemon info after previous error");
lastErrorTimestamp = null; lastErrorTimestamp = null;
HavenoUtils.havenoSetup.getWalletServiceErrorMsg().set(null);
} }
// update and notify connected state // update and notify connected state
@ -575,6 +560,9 @@ public final class CoreMoneroConnectionsService {
if (DevEnv.isDevMode()) e.printStackTrace(); if (DevEnv.isDevMode()) e.printStackTrace();
} }
// notify error message
HavenoUtils.havenoSetup.getWalletServiceErrorMsg().set(e.getMessage());
// check connection which notifies of changes // check connection which notifies of changes
synchronized (this) { synchronized (this) {
if (connectionManager.getAutoSwitch()) connectionManager.setConnection(connectionManager.getBestAvailableConnection()); if (connectionManager.getAutoSwitch()) connectionManager.setConnection(connectionManager.getBestAvailableConnection());

View File

@ -727,24 +727,24 @@ public class HavenoSetup {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Wallet // Wallet
public StringProperty getBtcInfo() { public StringProperty getXmrInfo() {
return walletAppSetup.getBtcInfo(); return walletAppSetup.getXmrInfo();
} }
public DoubleProperty getBtcSyncProgress() { public DoubleProperty getXmrSyncProgress() {
return walletAppSetup.getBtcSyncProgress(); return walletAppSetup.getXmrSyncProgress();
} }
public StringProperty getWalletServiceErrorMsg() { public StringProperty getWalletServiceErrorMsg() {
return walletAppSetup.getWalletServiceErrorMsg(); return walletAppSetup.getWalletServiceErrorMsg();
} }
public StringProperty getBtcSplashSyncIconId() { public StringProperty getXmrSplashSyncIconId() {
return walletAppSetup.getBtcSplashSyncIconId(); return walletAppSetup.getXmrSplashSyncIconId();
} }
public BooleanProperty getUseTorForBTC() { public BooleanProperty getUseTorForXMR() {
return walletAppSetup.getUseTorForBTC(); return walletAppSetup.getUseTorForXMR();
} }
// P2P // P2P

View File

@ -67,20 +67,20 @@ public class WalletAppSetup {
private final Preferences preferences; private final Preferences preferences;
@SuppressWarnings("FieldCanBeLocal") @SuppressWarnings("FieldCanBeLocal")
private MonadicBinding<String> btcInfoBinding; private MonadicBinding<String> xmrInfoBinding;
@Getter @Getter
private final DoubleProperty btcSyncProgress = new SimpleDoubleProperty(-1); private final DoubleProperty xmrSyncProgress = new SimpleDoubleProperty(-1);
@Getter @Getter
private final StringProperty walletServiceErrorMsg = new SimpleStringProperty(); private final StringProperty walletServiceErrorMsg = new SimpleStringProperty();
@Getter @Getter
private final StringProperty btcSplashSyncIconId = new SimpleStringProperty(); private final StringProperty xmrSplashSyncIconId = new SimpleStringProperty();
@Getter @Getter
private final StringProperty btcInfo = new SimpleStringProperty(Res.get("mainView.footer.btcInfo.initializing")); private final StringProperty xmrInfo = new SimpleStringProperty(Res.get("mainView.footer.xmrInfo.initializing"));
@Getter @Getter
private final ObjectProperty<RejectedTxException> rejectedTxException = new SimpleObjectProperty<>(); private final ObjectProperty<RejectedTxException> rejectedTxException = new SimpleObjectProperty<>();
@Getter @Getter
private final BooleanProperty useTorForBTC = new SimpleBooleanProperty(); private final BooleanProperty useTorForXMR = new SimpleBooleanProperty();
@Inject @Inject
public WalletAppSetup(CoreContext coreContext, public WalletAppSetup(CoreContext coreContext,
@ -95,7 +95,7 @@ public class WalletAppSetup {
this.connectionService = connectionService; this.connectionService = connectionService;
this.config = config; this.config = config;
this.preferences = preferences; this.preferences = preferences;
this.useTorForBTC.set(preferences.getUseTorForMonero()); this.useTorForXMR.set(preferences.getUseTorForMonero());
} }
void init(@Nullable Consumer<String> chainFileLockedExceptionHandler, void init(@Nullable Consumer<String> chainFileLockedExceptionHandler,
@ -107,58 +107,59 @@ public class WalletAppSetup {
VersionMessage.BITCOINJ_VERSION, "2a80db4"); VersionMessage.BITCOINJ_VERSION, "2a80db4");
ObjectProperty<Throwable> walletServiceException = new SimpleObjectProperty<>(); ObjectProperty<Throwable> walletServiceException = new SimpleObjectProperty<>();
btcInfoBinding = EasyBind.combine(connectionService.downloadPercentageProperty(), // TODO (woodser): update to XMR xmrInfoBinding = EasyBind.combine(connectionService.downloadPercentageProperty(), // TODO (woodser): update to XMR
connectionService.chainHeightProperty(), connectionService.chainHeightProperty(),
walletServiceException, walletServiceException,
(downloadPercentage, chainHeight, exception) -> { getWalletServiceErrorMsg(),
(downloadPercentage, chainHeight, exception, errorMsg) -> {
String result; String result;
if (exception == null) { if (exception == null && errorMsg == null) {
double percentage = (double) downloadPercentage; double percentage = (double) downloadPercentage;
btcSyncProgress.set(percentage); xmrSyncProgress.set(percentage);
MoneroDaemonInfo lastInfo = connectionService.getLastInfo(); MoneroDaemonInfo lastInfo = connectionService.getLastInfo();
Long bestChainHeight = lastInfo == null ? null : lastInfo.getHeight(); Long bestChainHeight = lastInfo == null ? null : lastInfo.getHeight();
String chainHeightAsString = bestChainHeight != null && bestChainHeight > 0 ? String chainHeightAsString = bestChainHeight != null && bestChainHeight > 0 ?
String.valueOf(bestChainHeight) : String.valueOf(bestChainHeight) :
""; "";
if (percentage == 1) { if (percentage == 1) {
String synchronizedWith = Res.get("mainView.footer.btcInfo.synchronizedWith", String synchronizedWith = Res.get("mainView.footer.xmrInfo.synchronizedWith",
getBtcNetworkAsString(), chainHeightAsString); getXmrNetworkAsString(), chainHeightAsString);
String feeInfo = ""; // TODO: feeService.isFeeAvailable() returns true, disable String feeInfo = ""; // TODO: feeService.isFeeAvailable() returns true, disable
result = Res.get("mainView.footer.btcInfo", synchronizedWith, feeInfo); result = Res.get("mainView.footer.xmrInfo", synchronizedWith, feeInfo);
getBtcSplashSyncIconId().set("image-connection-synced"); getXmrSplashSyncIconId().set("image-connection-synced");
downloadCompleteHandler.run(); downloadCompleteHandler.run();
} else if (percentage > 0.0) { } else if (percentage > 0.0) {
String synchronizingWith = Res.get("mainView.footer.btcInfo.synchronizingWith", String synchronizingWith = Res.get("mainView.footer.xmrInfo.synchronizingWith",
getBtcNetworkAsString(), chainHeightAsString, getXmrNetworkAsString(), chainHeightAsString,
FormattingUtils.formatToPercentWithSymbol(percentage)); FormattingUtils.formatToPercentWithSymbol(percentage));
result = Res.get("mainView.footer.btcInfo", synchronizingWith, ""); result = Res.get("mainView.footer.xmrInfo", synchronizingWith, "");
} else { } else {
result = Res.get("mainView.footer.btcInfo", result = Res.get("mainView.footer.xmrInfo",
Res.get("mainView.footer.btcInfo.connectingTo"), Res.get("mainView.footer.xmrInfo.connectingTo"),
getBtcNetworkAsString()); getXmrNetworkAsString());
} }
} else { } else {
result = Res.get("mainView.footer.btcInfo", result = Res.get("mainView.footer.xmrInfo",
Res.get("mainView.footer.btcInfo.connectionFailed"), Res.get("mainView.footer.xmrInfo.connectionFailed"),
getBtcNetworkAsString()); getXmrNetworkAsString());
log.error(exception.toString()); if (exception != null) {
if (exception instanceof TimeoutException) { if (exception instanceof TimeoutException) {
getWalletServiceErrorMsg().set(Res.get("mainView.walletServiceErrorMsg.timeout")); getWalletServiceErrorMsg().set(Res.get("mainView.walletServiceErrorMsg.timeout"));
} else if (exception.getCause() instanceof BlockStoreException) { } else if (exception.getCause() instanceof BlockStoreException) {
if (exception.getCause().getCause() instanceof ChainFileLockedException && chainFileLockedExceptionHandler != null) { if (exception.getCause().getCause() instanceof ChainFileLockedException && chainFileLockedExceptionHandler != null) {
chainFileLockedExceptionHandler.accept(Res.get("popup.warning.startupFailed.twoInstances")); chainFileLockedExceptionHandler.accept(Res.get("popup.warning.startupFailed.twoInstances"));
}
} else if (exception instanceof RejectedTxException) {
rejectedTxException.set((RejectedTxException) exception);
getWalletServiceErrorMsg().set(Res.get("mainView.walletServiceErrorMsg.rejectedTxException", exception.getMessage()));
} else {
getWalletServiceErrorMsg().set(Res.get("mainView.walletServiceErrorMsg.connectionError", exception.getMessage()));
} }
} else if (exception instanceof RejectedTxException) {
rejectedTxException.set((RejectedTxException) exception);
getWalletServiceErrorMsg().set(Res.get("mainView.walletServiceErrorMsg.rejectedTxException", exception.getMessage()));
} else {
getWalletServiceErrorMsg().set(Res.get("mainView.walletServiceErrorMsg.connectionError", exception.getMessage()));
} }
} }
return result; return result;
}); });
btcInfoBinding.subscribe((observable, oldValue, newValue) -> UserThread.execute(() -> btcInfo.set(newValue))); xmrInfoBinding.subscribe((observable, oldValue, newValue) -> UserThread.execute(() -> xmrInfo.set(newValue)));
walletsSetup.initialize(null, walletsSetup.initialize(null,
() -> { () -> {
@ -253,7 +254,7 @@ public class WalletAppSetup {
}); });
} }
private String getBtcNetworkAsString() { private String getXmrNetworkAsString() {
String postFix; String postFix;
if (config.ignoreLocalXmrNode) if (config.ignoreLocalXmrNode)
postFix = " " + Res.get("mainView.footer.localhostBitcoinNode"); postFix = " " + Res.get("mainView.footer.localhostBitcoinNode");

View File

@ -56,22 +56,22 @@ public class XmrNodes {
return Arrays.asList( return Arrays.asList(
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "127.0.0.1", 38081, 1, "@local"), new XmrNode(MoneroNodesOption.PROVIDED, null, null, "127.0.0.1", 38081, 1, "@local"),
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "127.0.0.1", 39081, 1, "@local"), new XmrNode(MoneroNodesOption.PROVIDED, null, null, "127.0.0.1", 39081, 1, "@local"),
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "45.63.8.26", 38081, 1, "@haveno"), new XmrNode(MoneroNodesOption.PROVIDED, null, null, "45.63.8.26", 38081, 2, "@haveno"),
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "stagenet.community.rino.io", 38081, 2, "@RINOwallet"), new XmrNode(MoneroNodesOption.PROVIDED, null, null, "stagenet.community.rino.io", 38081, 3, "@RINOwallet"),
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "stagenet.melo.tools", 38081, 2, null), new XmrNode(MoneroNodesOption.PUBLIC, null, null, "stagenet.melo.tools", 38081, 3, null),
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node.sethforprivacy.com", 38089, 2, null), new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node.sethforprivacy.com", 38089, 3, null),
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node2.sethforprivacy.com", 38089, 2, null), new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node2.sethforprivacy.com", 38089, 3, null),
new XmrNode(MoneroNodesOption.PUBLIC, null, "plowsof3t5hogddwabaeiyrno25efmzfxyro2vligremt7sxpsclfaid.onion", null, 38089, 2, null) new XmrNode(MoneroNodesOption.PUBLIC, null, "plowsof3t5hogddwabaeiyrno25efmzfxyro2vligremt7sxpsclfaid.onion", null, 38089, 2, null)
); );
case XMR_MAINNET: case XMR_MAINNET:
return Arrays.asList( return Arrays.asList(
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "127.0.0.1", 18081, 1, "@local"), new XmrNode(MoneroNodesOption.PROVIDED, null, null, "127.0.0.1", 18081, 1, "@local"),
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "xmr-node.cakewallet.com", 18081, 1, "@cakewallet"), new XmrNode(MoneroNodesOption.PROVIDED, null, null, "xmr-node.cakewallet.com", 18081, 2, "@cakewallet"),
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "xmr-node-eu.cakewallet.com", 18081, 2, "@cakewallet"),
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "xmr-node-usa-east.cakewallet.com", 18081, 2, "@cakewallet"),
new XmrNode(MoneroNodesOption.PROVIDED, null, null, "xmr-node-uk.cakewallet.com", 18081, 2, "@cakewallet"),
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node.community.rino.io", 18081, 2, "@RINOwallet"), new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node.community.rino.io", 18081, 2, "@RINOwallet"),
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "xmr-node-eu.cakewallet.com", 18081, 2, "@cakewallet"), new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node.sethforprivacy.com", 18089, 3, "@sethforprivacy")
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "xmr-node-usa-east.cakewallet.com", 18081, 2, "@cakewallet"),
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "xmr-node-uk.cakewallet.com", 18081, 2, "@cakewallet"),
new XmrNode(MoneroNodesOption.PUBLIC, null, null, "node.sethforprivacy.com", 18089, 2, "@sethforprivacy")
); );
default: default:
throw new IllegalStateException("Unexpected base currency network: " + Config.baseCurrencyNetwork()); throw new IllegalStateException("Unexpected base currency network: " + Config.baseCurrencyNetwork());

View File

@ -42,8 +42,8 @@ public class XmrNodesSetupPreferences {
XmrNodes.MoneroNodesOption nodesOption = XmrNodes.MoneroNodesOption.values()[preferences.getMoneroNodesOptionOrdinal()]; XmrNodes.MoneroNodesOption nodesOption = XmrNodes.MoneroNodesOption.values()[preferences.getMoneroNodesOptionOrdinal()];
switch (nodesOption) { switch (nodesOption) {
case CUSTOM: case CUSTOM:
String bitcoinNodes = preferences.getMoneroNodes(); String moneroNodes = preferences.getMoneroNodes();
Set<String> distinctNodes = Utilities.commaSeparatedListToSet(bitcoinNodes, false); Set<String> distinctNodes = Utilities.commaSeparatedListToSet(moneroNodes, false);
result = XmrNodes.toCustomXmrNodesList(distinctNodes); result = XmrNodes.toCustomXmrNodesList(distinctNodes);
if (result.isEmpty()) { if (result.isEmpty()) {
log.warn("Custom nodes is set but no valid nodes are provided. " + log.warn("Custom nodes is set but no valid nodes are provided. " +

View File

@ -675,7 +675,7 @@ public class XmrWalletService {
if (wallet != null) { if (wallet != null) {
log.info("Monero wallet uri={}, path={}", wallet.getRpcConnection().getUri(), wallet.getPath()); log.info("Monero wallet uri={}, path={}", wallet.getRpcConnection().getUri(), wallet.getPath());
int numAttempts = 0; int numAttempts = 0;
int maxAttempts = 2; int maxAttempts = 3;
while (!HavenoUtils.havenoSetup.getWalletInitialized().get()) { while (!HavenoUtils.havenoSetup.getWalletInitialized().get()) {
try { try {

View File

@ -265,13 +265,13 @@ mainView.balance.pending.short=Pending
mainView.footer.usingTor=(via Tor) mainView.footer.usingTor=(via Tor)
mainView.footer.localhostBitcoinNode=(localhost) mainView.footer.localhostBitcoinNode=(localhost)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB
mainView.footer.btcInfo.initializing=Connecting to Monero network mainView.footer.xmrInfo.initializing=Connecting to Monero network
mainView.footer.btcInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synced with {0} at block {1} mainView.footer.xmrInfo.synchronizedWith=Synced with {0} at block {1}
mainView.footer.btcInfo.connectingTo=Connecting to mainView.footer.xmrInfo.connectingTo=Connecting to
mainView.footer.btcInfo.connectionFailed=Connection failed to mainView.footer.xmrInfo.connectionFailed=Connection failed to
mainView.footer.xmrPeers=Monero network peers: {0} mainView.footer.xmrPeers=Monero network peers: {0}
mainView.footer.p2pPeers=Haveno network peers: {0} mainView.footer.p2pPeers=Haveno network peers: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=Zamčeno
mainView.footer.usingTor=(přes Tor) mainView.footer.usingTor=(přes Tor)
mainView.footer.localhostBitcoinNode=(localhost) mainView.footer.localhostBitcoinNode=(localhost)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Aktuální poplatek: {0} sat/vB mainView.footer.btcFeeRate=/ Aktuální poplatek: {0} sat/vB
mainView.footer.btcInfo.initializing=Připojování do Bitcoinové sítě mainView.footer.xmrInfo.initializing=Připojování do Bitcoinové sítě
mainView.footer.btcInfo.synchronizingWith=Synchronizace s {0} v bloku: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronizace s {0} v bloku: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synchronizováno s {0} v bloku {1} mainView.footer.xmrInfo.synchronizedWith=Synchronizováno s {0} v bloku {1}
mainView.footer.btcInfo.connectingTo=Připojování mainView.footer.xmrInfo.connectingTo=Připojování
mainView.footer.btcInfo.connectionFailed=Připojení se nezdařilo mainView.footer.xmrInfo.connectionFailed=Připojení se nezdařilo
mainView.footer.xmrPeers=Monero síťové nody: {0} mainView.footer.xmrPeers=Monero síťové nody: {0}
mainView.footer.p2pPeers=Haveno síťové nody: {0} mainView.footer.p2pPeers=Haveno síťové nody: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=Gesperrt
mainView.footer.usingTor=(über Tor) mainView.footer.usingTor=(über Tor)
mainView.footer.localhostBitcoinNode=(localhost) mainView.footer.localhostBitcoinNode=(localhost)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Aktuelle Gebühr: {0} sat/vB mainView.footer.btcFeeRate=/ Aktuelle Gebühr: {0} sat/vB
mainView.footer.btcInfo.initializing=Verbindung mit Bitcoin-Netzwerk wird hergestellt mainView.footer.xmrInfo.initializing=Verbindung mit Bitcoin-Netzwerk wird hergestellt
mainView.footer.btcInfo.synchronizingWith=Synchronisierung mit {0} bei Block: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronisierung mit {0} bei Block: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synchronisierung mit {0} bei Block {1} mainView.footer.xmrInfo.synchronizedWith=Synchronisierung mit {0} bei Block {1}
mainView.footer.btcInfo.connectingTo=Verbinde mit mainView.footer.xmrInfo.connectingTo=Verbinde mit
mainView.footer.btcInfo.connectionFailed=Verbindung fehlgeschlagen zu mainView.footer.xmrInfo.connectionFailed=Verbindung fehlgeschlagen zu
mainView.footer.xmrPeers=Monero Netzwerk Peers: {0} mainView.footer.xmrPeers=Monero Netzwerk Peers: {0}
mainView.footer.p2pPeers=Haveno Netzwerk Peers: {0} mainView.footer.p2pPeers=Haveno Netzwerk Peers: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=Bloqueado
mainView.footer.usingTor=(via Tor) mainView.footer.usingTor=(via Tor)
mainView.footer.localhostBitcoinNode=(localhost) mainView.footer.localhostBitcoinNode=(localhost)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/Tasas actuales: {0} sat/vB mainView.footer.btcFeeRate=/Tasas actuales: {0} sat/vB
mainView.footer.btcInfo.initializing=Conectando a la red Bitcoin mainView.footer.xmrInfo.initializing=Conectando a la red Bitcoin
mainView.footer.btcInfo.synchronizingWith=Sincronizando con {0} en el bloque: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Sincronizando con {0} en el bloque: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Sincronizado con {0} en el bloque {1} mainView.footer.xmrInfo.synchronizedWith=Sincronizado con {0} en el bloque {1}
mainView.footer.btcInfo.connectingTo=Conectando a mainView.footer.xmrInfo.connectingTo=Conectando a
mainView.footer.btcInfo.connectionFailed=Conexión fallida a mainView.footer.xmrInfo.connectionFailed=Conexión fallida a
mainView.footer.xmrPeers=Pares de Monero: {0} mainView.footer.xmrPeers=Pares de Monero: {0}
mainView.footer.p2pPeers=Pares de la red de Haveno: {0} mainView.footer.p2pPeers=Pares de la red de Haveno: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=قفل شده
mainView.footer.usingTor=(via Tor) mainView.footer.usingTor=(via Tor)
mainView.footer.localhostBitcoinNode=(لوکال هاست) mainView.footer.localhostBitcoinNode=(لوکال هاست)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB
mainView.footer.btcInfo.initializing=در حال ارتباط با شبکه بیت‌کوین mainView.footer.xmrInfo.initializing=در حال ارتباط با شبکه بیت‌کوین
mainView.footer.btcInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synced with {0} at block {1} mainView.footer.xmrInfo.synchronizedWith=Synced with {0} at block {1}
mainView.footer.btcInfo.connectingTo=در حال ایجاد ارتباط با mainView.footer.xmrInfo.connectingTo=در حال ایجاد ارتباط با
mainView.footer.btcInfo.connectionFailed=Connection failed to mainView.footer.xmrInfo.connectionFailed=Connection failed to
mainView.footer.xmrPeers=Monero network peers: {0} mainView.footer.xmrPeers=Monero network peers: {0}
mainView.footer.p2pPeers=Haveno network peers: {0} mainView.footer.p2pPeers=Haveno network peers: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=Vérouillé
mainView.footer.usingTor=(à travers Tor) mainView.footer.usingTor=(à travers Tor)
mainView.footer.localhostBitcoinNode=(localhost) mainView.footer.localhostBitcoinNode=(localhost)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Taux des frais: {0} sat/vB mainView.footer.btcFeeRate=/ Taux des frais: {0} sat/vB
mainView.footer.btcInfo.initializing=Connexion au réseau Bitcoin en cours mainView.footer.xmrInfo.initializing=Connexion au réseau Bitcoin en cours
mainView.footer.btcInfo.synchronizingWith=Synchronisation avec {0} au block: {1}/ {2} mainView.footer.xmrInfo.synchronizingWith=Synchronisation avec {0} au block: {1}/ {2}
mainView.footer.btcInfo.synchronizedWith=Synchronisé avec {0} au block {1} mainView.footer.xmrInfo.synchronizedWith=Synchronisé avec {0} au block {1}
mainView.footer.btcInfo.connectingTo=Se connecte à mainView.footer.xmrInfo.connectingTo=Se connecte à
mainView.footer.btcInfo.connectionFailed=Échec de la connexion à mainView.footer.xmrInfo.connectionFailed=Échec de la connexion à
mainView.footer.xmrPeers=Pairs du réseau Monero: {0} mainView.footer.xmrPeers=Pairs du réseau Monero: {0}
mainView.footer.p2pPeers=Pairs du réseau Haveno: {0} mainView.footer.p2pPeers=Pairs du réseau Haveno: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=Bloccati
mainView.footer.usingTor=(via Tor) mainView.footer.usingTor=(via Tor)
mainView.footer.localhostBitcoinNode=(localhost) mainView.footer.localhostBitcoinNode=(localhost)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB
mainView.footer.btcInfo.initializing=Connessione alla rete Bitcoin mainView.footer.xmrInfo.initializing=Connessione alla rete Bitcoin
mainView.footer.btcInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synced with {0} at block {1} mainView.footer.xmrInfo.synchronizedWith=Synced with {0} at block {1}
mainView.footer.btcInfo.connectingTo=Connessione a mainView.footer.xmrInfo.connectingTo=Connessione a
mainView.footer.btcInfo.connectionFailed=Connessione fallita mainView.footer.xmrInfo.connectionFailed=Connessione fallita
mainView.footer.xmrPeers=Monero network peers: {0} mainView.footer.xmrPeers=Monero network peers: {0}
mainView.footer.p2pPeers=Haveno network peers: {0} mainView.footer.p2pPeers=Haveno network peers: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=ロック中
mainView.footer.usingTor=(Tor経由で) mainView.footer.usingTor=(Tor経由で)
mainView.footer.localhostBitcoinNode=(ローカルホスト) mainView.footer.localhostBitcoinNode=(ローカルホスト)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ 手数料率: {0} サトシ/vB mainView.footer.btcFeeRate=/ 手数料率: {0} サトシ/vB
mainView.footer.btcInfo.initializing=ビットコインネットワークに接続中 mainView.footer.xmrInfo.initializing=ビットコインネットワークに接続中
mainView.footer.btcInfo.synchronizingWith={0}と同期中、ブロック: {1} / {2} mainView.footer.xmrInfo.synchronizingWith={0}と同期中、ブロック: {1} / {2}
mainView.footer.btcInfo.synchronizedWith={0}と同期されています、ブロック{1}に mainView.footer.xmrInfo.synchronizedWith={0}と同期されています、ブロック{1}に
mainView.footer.btcInfo.connectingTo=接続中: mainView.footer.xmrInfo.connectingTo=接続中:
mainView.footer.btcInfo.connectionFailed=接続失敗 mainView.footer.xmrInfo.connectionFailed=接続失敗
mainView.footer.xmrPeers=Moneroネットワークピア: {0} mainView.footer.xmrPeers=Moneroネットワークピア: {0}
mainView.footer.p2pPeers=Havenoネットワークピア: {0} mainView.footer.p2pPeers=Havenoネットワークピア: {0}

View File

@ -249,13 +249,13 @@ mainView.balance.pending.short=Travado
mainView.footer.usingTor=(via Tor) mainView.footer.usingTor=(via Tor)
mainView.footer.localhostBitcoinNode=(localhost) mainView.footer.localhostBitcoinNode=(localhost)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB
mainView.footer.btcInfo.initializing=Conectando-se à rede Bitcoin mainView.footer.xmrInfo.initializing=Conectando-se à rede Bitcoin
mainView.footer.btcInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synced with {0} at block {1} mainView.footer.xmrInfo.synchronizedWith=Synced with {0} at block {1}
mainView.footer.btcInfo.connectingTo=Conectando-se a mainView.footer.xmrInfo.connectingTo=Conectando-se a
mainView.footer.btcInfo.connectionFailed=Falha na conexão à mainView.footer.xmrInfo.connectionFailed=Falha na conexão à
mainView.footer.xmrPeers=Monero network peers: {0} mainView.footer.xmrPeers=Monero network peers: {0}
mainView.footer.p2pPeers=Haveno network peers: {0} mainView.footer.p2pPeers=Haveno network peers: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=Bloqueado
mainView.footer.usingTor=(via Tor) mainView.footer.usingTor=(via Tor)
mainView.footer.localhostBitcoinNode=(localhost) mainView.footer.localhostBitcoinNode=(localhost)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB
mainView.footer.btcInfo.initializing=Conectando à rede Bitcoin mainView.footer.xmrInfo.initializing=Conectando à rede Bitcoin
mainView.footer.btcInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synced with {0} at block {1} mainView.footer.xmrInfo.synchronizedWith=Synced with {0} at block {1}
mainView.footer.btcInfo.connectingTo=Conectando à mainView.footer.xmrInfo.connectingTo=Conectando à
mainView.footer.btcInfo.connectionFailed=Connection failed to mainView.footer.xmrInfo.connectionFailed=Connection failed to
mainView.footer.xmrPeers=Monero network peers: {0} mainView.footer.xmrPeers=Monero network peers: {0}
mainView.footer.p2pPeers=Haveno network peers: {0} mainView.footer.p2pPeers=Haveno network peers: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=В сделках
mainView.footer.usingTor=(via Tor) mainView.footer.usingTor=(via Tor)
mainView.footer.localhostBitcoinNode=(локальный узел) mainView.footer.localhostBitcoinNode=(локальный узел)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB
mainView.footer.btcInfo.initializing=Подключение к сети Биткойн mainView.footer.xmrInfo.initializing=Подключение к сети Биткойн
mainView.footer.btcInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synced with {0} at block {1} mainView.footer.xmrInfo.synchronizedWith=Synced with {0} at block {1}
mainView.footer.btcInfo.connectingTo=Подключение к mainView.footer.xmrInfo.connectingTo=Подключение к
mainView.footer.btcInfo.connectionFailed=Connection failed to mainView.footer.xmrInfo.connectionFailed=Connection failed to
mainView.footer.xmrPeers=Monero network peers: {0} mainView.footer.xmrPeers=Monero network peers: {0}
mainView.footer.p2pPeers=Haveno network peers: {0} mainView.footer.p2pPeers=Haveno network peers: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=ถูกล็อคไว้
mainView.footer.usingTor=(via Tor) mainView.footer.usingTor=(via Tor)
mainView.footer.localhostBitcoinNode=(แม่ข่ายเฉพาะที่) mainView.footer.localhostBitcoinNode=(แม่ข่ายเฉพาะที่)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB
mainView.footer.btcInfo.initializing=Connecting to Bitcoin network mainView.footer.xmrInfo.initializing=Connecting to Bitcoin network
mainView.footer.btcInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synced with {0} at block {1} mainView.footer.xmrInfo.synchronizedWith=Synced with {0} at block {1}
mainView.footer.btcInfo.connectingTo=Connecting to mainView.footer.xmrInfo.connectingTo=Connecting to
mainView.footer.btcInfo.connectionFailed=Connection failed to mainView.footer.xmrInfo.connectionFailed=Connection failed to
mainView.footer.xmrPeers=Monero network peers: {0} mainView.footer.xmrPeers=Monero network peers: {0}
mainView.footer.p2pPeers=Haveno network peers: {0} mainView.footer.p2pPeers=Haveno network peers: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=Bị khóa
mainView.footer.usingTor=(via Tor) mainView.footer.usingTor=(via Tor)
mainView.footer.localhostBitcoinNode=(Máy chủ nội bộ) mainView.footer.localhostBitcoinNode=(Máy chủ nội bộ)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB
mainView.footer.btcInfo.initializing=Đang kết nối với mạng Bitcoin mainView.footer.xmrInfo.initializing=Đang kết nối với mạng Bitcoin
mainView.footer.btcInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synced with {0} at block {1} mainView.footer.xmrInfo.synchronizedWith=Synced with {0} at block {1}
mainView.footer.btcInfo.connectingTo=Đang kết nối với mainView.footer.xmrInfo.connectingTo=Đang kết nối với
mainView.footer.btcInfo.connectionFailed=Connection failed to mainView.footer.xmrInfo.connectionFailed=Connection failed to
mainView.footer.xmrPeers=Monero network peers: {0} mainView.footer.xmrPeers=Monero network peers: {0}
mainView.footer.p2pPeers=Haveno network peers: {0} mainView.footer.p2pPeers=Haveno network peers: {0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=冻结
mainView.footer.usingTor=(通过 Tor mainView.footer.usingTor=(通过 Tor
mainView.footer.localhostBitcoinNode=(本地主机) mainView.footer.localhostBitcoinNode=(本地主机)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ 矿工手费率:{0} 聪/字节 mainView.footer.btcFeeRate=/ 矿工手费率:{0} 聪/字节
mainView.footer.btcInfo.initializing=连接至比特币网络 mainView.footer.xmrInfo.initializing=连接至比特币网络
mainView.footer.btcInfo.synchronizingWith=正在通过{0}同步区块:{1}/{2} mainView.footer.xmrInfo.synchronizingWith=正在通过{0}同步区块:{1}/{2}
mainView.footer.btcInfo.synchronizedWith=已通过{0}同步至区块{1} mainView.footer.xmrInfo.synchronizedWith=已通过{0}同步至区块{1}
mainView.footer.btcInfo.connectingTo=连接至 mainView.footer.xmrInfo.connectingTo=连接至
mainView.footer.btcInfo.connectionFailed=连接失败: mainView.footer.xmrInfo.connectionFailed=连接失败:
mainView.footer.xmrPeers=Monero网络节点{0} mainView.footer.xmrPeers=Monero网络节点{0}
mainView.footer.p2pPeers=Haveno 网络节点:{0} mainView.footer.p2pPeers=Haveno 网络节点:{0}

View File

@ -246,13 +246,13 @@ mainView.balance.pending.short=凍結
mainView.footer.usingTor=(via Tor) mainView.footer.usingTor=(via Tor)
mainView.footer.localhostBitcoinNode=(本地主機) mainView.footer.localhostBitcoinNode=(本地主機)
mainView.footer.btcInfo={0} {1} mainView.footer.xmrInfo={0} {1}
mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB mainView.footer.btcFeeRate=/ Fee rate: {0} sat/vB
mainView.footer.btcInfo.initializing=連接至比特幣網絡 mainView.footer.xmrInfo.initializing=連接至比特幣網絡
mainView.footer.btcInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2}
mainView.footer.btcInfo.synchronizedWith=Synced with {0} at block {1} mainView.footer.xmrInfo.synchronizedWith=Synced with {0} at block {1}
mainView.footer.btcInfo.connectingTo=連接至 mainView.footer.xmrInfo.connectingTo=連接至
mainView.footer.btcInfo.connectionFailed=連接失敗: mainView.footer.xmrInfo.connectionFailed=連接失敗:
mainView.footer.xmrPeers=Monero網絡節點{0} mainView.footer.xmrPeers=Monero網絡節點{0}
mainView.footer.p2pPeers=Haveno 網絡節點:{0} mainView.footer.p2pPeers=Haveno 網絡節點:{0}

View File

@ -117,15 +117,15 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
private final Navigation navigation; private final Navigation navigation;
private final ToggleGroup navButtons = new ToggleGroup(); private final ToggleGroup navButtons = new ToggleGroup();
private ChangeListener<String> walletServiceErrorMsgListener; private ChangeListener<String> walletServiceErrorMsgListener;
private ChangeListener<String> btcSyncIconIdListener; private ChangeListener<String> xmrSyncIconIdListener;
private ChangeListener<String> splashP2PNetworkErrorMsgListener; private ChangeListener<String> splashP2PNetworkErrorMsgListener;
private ChangeListener<String> splashP2PNetworkIconIdListener; private ChangeListener<String> splashP2PNetworkIconIdListener;
private ChangeListener<Boolean> splashP2PNetworkVisibleListener; private ChangeListener<Boolean> splashP2PNetworkVisibleListener;
private BusyAnimation splashP2PNetworkBusyAnimation; private BusyAnimation splashP2PNetworkBusyAnimation;
private Label splashP2PNetworkLabel; private Label splashP2PNetworkLabel;
private ProgressBar btcSyncIndicator, p2pNetworkProgressBar; private ProgressBar xmrSyncIndicator, p2pNetworkProgressBar;
private Label btcSplashInfo; private Label xmrSplashInfo;
private Popup p2PNetworkWarnMsgPopup, btcNetworkWarnMsgPopup; private Popup p2PNetworkWarnMsgPopup, xmrNetworkWarnMsgPopup;
private final TorNetworkSettingsWindow torNetworkSettingsWindow; private final TorNetworkSettingsWindow torNetworkSettingsWindow;
public static StackPane getRootContainer() { public static StackPane getRootContainer() {
@ -515,31 +515,31 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
logo.setId(Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_MAINNET ? "image-splash-logo" : "image-splash-testnet-logo"); logo.setId(Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_MAINNET ? "image-splash-logo" : "image-splash-testnet-logo");
// createBitcoinInfoBox // createBitcoinInfoBox
btcSplashInfo = new AutoTooltipLabel(); xmrSplashInfo = new AutoTooltipLabel();
btcSplashInfo.textProperty().bind(model.getBtcInfo()); xmrSplashInfo.textProperty().bind(model.getXmrInfo());
walletServiceErrorMsgListener = (ov, oldValue, newValue) -> { walletServiceErrorMsgListener = (ov, oldValue, newValue) -> {
btcSplashInfo.setId("splash-error-state-msg"); xmrSplashInfo.setId("splash-error-state-msg");
btcSplashInfo.getStyleClass().add("error-text"); xmrSplashInfo.getStyleClass().add("error-text");
}; };
model.getWalletServiceErrorMsg().addListener(walletServiceErrorMsgListener); model.getWalletServiceErrorMsg().addListener(walletServiceErrorMsgListener);
btcSyncIndicator = new JFXProgressBar(); xmrSyncIndicator = new JFXProgressBar();
btcSyncIndicator.setPrefWidth(305); xmrSyncIndicator.setPrefWidth(305);
btcSyncIndicator.progressProperty().bind(model.getCombinedSyncProgress()); xmrSyncIndicator.progressProperty().bind(model.getCombinedSyncProgress());
ImageView btcSyncIcon = new ImageView(); ImageView xmrSyncIcon = new ImageView();
btcSyncIcon.setVisible(false); xmrSyncIcon.setVisible(false);
btcSyncIcon.setManaged(false); xmrSyncIcon.setManaged(false);
btcSyncIconIdListener = (ov, oldValue, newValue) -> { xmrSyncIconIdListener = (ov, oldValue, newValue) -> {
btcSyncIcon.setId(newValue); xmrSyncIcon.setId(newValue);
btcSyncIcon.setVisible(true); xmrSyncIcon.setVisible(true);
btcSyncIcon.setManaged(true); xmrSyncIcon.setManaged(true);
btcSyncIndicator.setVisible(false); xmrSyncIndicator.setVisible(false);
btcSyncIndicator.setManaged(false); xmrSyncIndicator.setManaged(false);
}; };
model.getBtcSplashSyncIconId().addListener(btcSyncIconIdListener); model.getXmrSplashSyncIconId().addListener(xmrSyncIconIdListener);
HBox blockchainSyncBox = new HBox(); HBox blockchainSyncBox = new HBox();
@ -547,7 +547,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
blockchainSyncBox.setAlignment(Pos.CENTER); blockchainSyncBox.setAlignment(Pos.CENTER);
blockchainSyncBox.setPadding(new Insets(40, 0, 0, 0)); blockchainSyncBox.setPadding(new Insets(40, 0, 0, 0));
blockchainSyncBox.setPrefHeight(50); blockchainSyncBox.setPrefHeight(50);
blockchainSyncBox.getChildren().addAll(btcSplashInfo, btcSyncIcon); blockchainSyncBox.getChildren().addAll(xmrSplashInfo, xmrSyncIcon);
// create P2PNetworkBox // create P2PNetworkBox
@ -574,10 +574,10 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
splashP2PNetworkBusyAnimation.stop(); splashP2PNetworkBusyAnimation.stop();
showTorNetworkSettingsButton.setVisible(true); showTorNetworkSettingsButton.setVisible(true);
showTorNetworkSettingsButton.setManaged(true); showTorNetworkSettingsButton.setManaged(true);
if (model.getUseTorForBTC().get()) { if (model.getUseTorForXMR().get()) {
// If using tor for BTC, hide the BTC status since tor is not working // If using tor for XMR, hide the XMR status since tor is not working
btcSyncIndicator.setVisible(false); xmrSyncIndicator.setVisible(false);
btcSplashInfo.setVisible(false); xmrSplashInfo.setVisible(false);
} }
} else if (model.getSplashP2PNetworkAnimationVisible().get()) { } else if (model.getSplashP2PNetworkAnimationVisible().get()) {
splashP2PNetworkBusyAnimation.setDisable(false); splashP2PNetworkBusyAnimation.setDisable(false);
@ -623,20 +623,20 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
splashP2PNetworkBox.setPrefHeight(40); splashP2PNetworkBox.setPrefHeight(40);
splashP2PNetworkBox.getChildren().addAll(splashP2PNetworkLabel, splashP2PNetworkBusyAnimation, splashP2PNetworkIcon, showTorNetworkSettingsButton); splashP2PNetworkBox.getChildren().addAll(splashP2PNetworkLabel, splashP2PNetworkBusyAnimation, splashP2PNetworkIcon, showTorNetworkSettingsButton);
vBox.getChildren().addAll(logo, blockchainSyncBox, btcSyncIndicator, splashP2PNetworkBox); vBox.getChildren().addAll(logo, blockchainSyncBox, xmrSyncIndicator, splashP2PNetworkBox);
return vBox; return vBox;
} }
private void disposeSplashScreen() { private void disposeSplashScreen() {
model.getWalletServiceErrorMsg().removeListener(walletServiceErrorMsgListener); model.getWalletServiceErrorMsg().removeListener(walletServiceErrorMsgListener);
model.getBtcSplashSyncIconId().removeListener(btcSyncIconIdListener); model.getXmrSplashSyncIconId().removeListener(xmrSyncIconIdListener);
model.getP2pNetworkWarnMsg().removeListener(splashP2PNetworkErrorMsgListener); model.getP2pNetworkWarnMsg().removeListener(splashP2PNetworkErrorMsgListener);
model.getP2PNetworkIconId().removeListener(splashP2PNetworkIconIdListener); model.getP2PNetworkIconId().removeListener(splashP2PNetworkIconIdListener);
model.getSplashP2PNetworkAnimationVisible().removeListener(splashP2PNetworkVisibleListener); model.getSplashP2PNetworkAnimationVisible().removeListener(splashP2PNetworkVisibleListener);
btcSplashInfo.textProperty().unbind(); xmrSplashInfo.textProperty().unbind();
btcSyncIndicator.progressProperty().unbind(); xmrSyncIndicator.progressProperty().unbind();
splashP2PNetworkLabel.textProperty().unbind(); splashP2PNetworkLabel.textProperty().unbind();
@ -653,12 +653,12 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
setRightAnchor(separator, 0d); setRightAnchor(separator, 0d);
setTopAnchor(separator, 0d); setTopAnchor(separator, 0d);
// BTC // XMR
Label btcInfoLabel = new AutoTooltipLabel(); Label xmrInfoLabel = new AutoTooltipLabel();
btcInfoLabel.setId("footer-pane"); xmrInfoLabel.setId("footer-pane");
btcInfoLabel.textProperty().bind(model.getBtcInfo()); xmrInfoLabel.textProperty().bind(model.getXmrInfo());
setLeftAnchor(btcInfoLabel, 10d); setLeftAnchor(xmrInfoLabel, 10d);
setBottomAnchor(btcInfoLabel, 7d); setBottomAnchor(xmrInfoLabel, 7d);
// temporarily disabled due to high CPU usage (per issue #4649) // temporarily disabled due to high CPU usage (per issue #4649)
//ProgressBar blockchainSyncIndicator = new JFXProgressBar(-1); //ProgressBar blockchainSyncIndicator = new JFXProgressBar(-1);
@ -668,16 +668,16 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
model.getWalletServiceErrorMsg().addListener((ov, oldValue, newValue) -> { model.getWalletServiceErrorMsg().addListener((ov, oldValue, newValue) -> {
if (newValue != null) { if (newValue != null) {
btcInfoLabel.setId("splash-error-state-msg"); xmrInfoLabel.setId("splash-error-state-msg");
btcInfoLabel.getStyleClass().add("error-text"); xmrInfoLabel.getStyleClass().add("error-text");
if (btcNetworkWarnMsgPopup == null) { // if (xmrNetworkWarnMsgPopup == null) {
btcNetworkWarnMsgPopup = new Popup().warning(newValue); // xmrNetworkWarnMsgPopup = new Popup().warning(newValue);
btcNetworkWarnMsgPopup.show(); // xmrNetworkWarnMsgPopup.show();
} // }
} else { } else {
btcInfoLabel.setId("footer-pane"); xmrInfoLabel.setId("footer-pane");
if (btcNetworkWarnMsgPopup != null) // if (xmrNetworkWarnMsgPopup != null)
btcNetworkWarnMsgPopup.hide(); // xmrNetworkWarnMsgPopup.hide();
} }
}); });
@ -787,7 +787,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
setRightAnchor(vBox, 53d); setRightAnchor(vBox, 53d);
setBottomAnchor(vBox, 5d); setBottomAnchor(vBox, 5d);
return new AnchorPane(separator, btcInfoLabel, versionBox, vBox, p2PNetworkStatusIcon, p2PNetworkIcon) {{ return new AnchorPane(separator, xmrInfoLabel, versionBox, vBox, p2PNetworkStatusIcon, p2PNetworkIcon) {{
setId("footer-pane"); setId("footer-pane");
setMinHeight(30); setMinHeight(30);
setMaxHeight(30); setMaxHeight(30);

View File

@ -260,7 +260,6 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener
}); });
setupP2PNumPeersWatcher(); setupP2PNumPeersWatcher();
setupXmrNumPeersWatcher();
marketPricePresentation.setup(); marketPricePresentation.setup();
accountPresentation.setup(); accountPresentation.setup();
@ -421,7 +420,7 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener
.warning(Res.get("popup.error.takeOfferRequestFailed", errorMessage)) .warning(Res.get("popup.error.takeOfferRequestFailed", errorMessage))
.show()); .show());
havenoSetup.getBtcSyncProgress().addListener((observable, oldValue, newValue) -> updateBtcSyncProgress()); havenoSetup.getXmrSyncProgress().addListener((observable, oldValue, newValue) -> updateXmrSyncProgress());
havenoSetup.setFilterWarningHandler(warning -> new Popup().warning(warning).show()); havenoSetup.setFilterWarningHandler(warning -> new Popup().warning(warning).show());
@ -496,36 +495,6 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener
}); });
} }
private void setupXmrNumPeersWatcher() {
connectionService.numPeersProperty().addListener((observable, oldValue, newValue) -> {
int numPeers = (int) newValue;
if ((int) oldValue > 0 && numPeers == 0) {
if (checkNumberOfXmrPeersTimer != null)
checkNumberOfXmrPeersTimer.stop();
checkNumberOfXmrPeersTimer = UserThread.runAfter(() -> {
// check again numPeers
if (connectionService.numPeersProperty().get() == 0) {
if (localBitcoinNode.shouldBeUsed())
getWalletServiceErrorMsg().set(
Res.get("mainView.networkWarning.localhostBitcoinLost", // TODO: update error message for XMR
Res.getBaseCurrencyName().toLowerCase()));
else
getWalletServiceErrorMsg().set(
Res.get("mainView.networkWarning.allConnectionsLost",
Res.getBaseCurrencyName().toLowerCase()));
} else {
getWalletServiceErrorMsg().set(null);
}
}, 5);
} else if ((int) oldValue == 0 && numPeers > 0) {
if (checkNumberOfXmrPeersTimer != null)
checkNumberOfXmrPeersTimer.stop();
getWalletServiceErrorMsg().set(null);
}
});
}
private void showPopupIfInvalidBtcConfig() { private void showPopupIfInvalidBtcConfig() {
preferences.setMoneroNodesOptionOrdinal(0); preferences.setMoneroNodesOptionOrdinal(0);
new Popup().warning(Res.get("settings.net.warn.invalidBtcConfig")) new Popup().warning(Res.get("settings.net.warn.invalidBtcConfig"))
@ -564,10 +533,10 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener
} }
} }
private void updateBtcSyncProgress() { private void updateXmrSyncProgress() {
final DoubleProperty btcSyncProgress = havenoSetup.getBtcSyncProgress(); final DoubleProperty xmrSyncProgress = havenoSetup.getXmrSyncProgress();
combinedSyncProgress.set(btcSyncProgress.doubleValue()); combinedSyncProgress.set(xmrSyncProgress.doubleValue());
} }
private void setupInvalidOpenOffersHandler() { private void setupInvalidOpenOffersHandler() {
@ -637,9 +606,9 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener
// Wallet // Wallet
StringProperty getBtcInfo() { StringProperty getXmrInfo() {
final StringProperty combinedInfo = new SimpleStringProperty(); final StringProperty combinedInfo = new SimpleStringProperty();
combinedInfo.bind(havenoSetup.getBtcInfo()); combinedInfo.bind(havenoSetup.getXmrInfo());
return combinedInfo; return combinedInfo;
} }
@ -657,12 +626,12 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener
return havenoSetup.getWalletServiceErrorMsg(); return havenoSetup.getWalletServiceErrorMsg();
} }
StringProperty getBtcSplashSyncIconId() { StringProperty getXmrSplashSyncIconId() {
return havenoSetup.getBtcSplashSyncIconId(); return havenoSetup.getXmrSplashSyncIconId();
} }
BooleanProperty getUseTorForBTC() { BooleanProperty getUseTorForXMR() {
return havenoSetup.getUseTorForBTC(); return havenoSetup.getUseTorForXMR();
} }
// P2P // P2P