mirror of
https://github.com/retoaccess1/haveno-reto.git
synced 2024-11-10 13:13:36 +01:00
monero wallets switch to tor after initial sync by default
This commit is contained in:
parent
0620bf260e
commit
f19bc2ad4b
@ -137,6 +137,12 @@ public class Config {
|
|||||||
public final boolean helpRequested;
|
public final boolean helpRequested;
|
||||||
public final File configFile;
|
public final File configFile;
|
||||||
|
|
||||||
|
public enum UseTorForXmr {
|
||||||
|
AFTER_SYNC,
|
||||||
|
OFF,
|
||||||
|
ON
|
||||||
|
}
|
||||||
|
|
||||||
// Options supported on cmd line and in the config file
|
// Options supported on cmd line and in the config file
|
||||||
public final String appName;
|
public final String appName;
|
||||||
public final File userDataDir;
|
public final File userDataDir;
|
||||||
@ -180,7 +186,7 @@ public class Config {
|
|||||||
public final String xmrNodeUsername;
|
public final String xmrNodeUsername;
|
||||||
public final String xmrNodePassword;
|
public final String xmrNodePassword;
|
||||||
public final String xmrNodes;
|
public final String xmrNodes;
|
||||||
public final boolean useTorForXmr;
|
public final UseTorForXmr useTorForXmr;
|
||||||
public final boolean useTorForXmrOptionSetExplicitly;
|
public final boolean useTorForXmrOptionSetExplicitly;
|
||||||
public final String socks5DiscoverMode;
|
public final String socks5DiscoverMode;
|
||||||
public final boolean useAllProvidedNodes;
|
public final boolean useAllProvidedNodes;
|
||||||
@ -514,16 +520,18 @@ public class Config {
|
|||||||
.defaultsTo("");
|
.defaultsTo("");
|
||||||
|
|
||||||
ArgumentAcceptingOptionSpec<String> xmrNodesOpt =
|
ArgumentAcceptingOptionSpec<String> xmrNodesOpt =
|
||||||
parser.accepts(XMR_NODES, "Custom nodes used for BitcoinJ as comma separated IP addresses.")
|
parser.accepts(XMR_NODES, "Custom nodes used for Monero as comma separated IP addresses.")
|
||||||
.withRequiredArg()
|
.withRequiredArg()
|
||||||
.describedAs("ip[,...]")
|
.describedAs("ip[,...]")
|
||||||
.defaultsTo("");
|
.defaultsTo("");
|
||||||
|
|
||||||
ArgumentAcceptingOptionSpec<Boolean> useTorForXmrOpt =
|
//noinspection rawtypes
|
||||||
parser.accepts(USE_TOR_FOR_XMR, "If set to true BitcoinJ is routed over tor (socks 5 proxy).")
|
ArgumentAcceptingOptionSpec<Enum> useTorForXmrOpt =
|
||||||
|
parser.accepts(USE_TOR_FOR_XMR, "Configure TOR for Monero connections, one of: after_sync, off, or on.")
|
||||||
.withRequiredArg()
|
.withRequiredArg()
|
||||||
.ofType(Boolean.class)
|
.ofType(UseTorForXmr.class)
|
||||||
.defaultsTo(false);
|
.withValuesConvertedBy(new EnumValueConverter(UseTorForXmr.class))
|
||||||
|
.defaultsTo(UseTorForXmr.AFTER_SYNC);
|
||||||
|
|
||||||
ArgumentAcceptingOptionSpec<String> socks5DiscoverModeOpt =
|
ArgumentAcceptingOptionSpec<String> socks5DiscoverModeOpt =
|
||||||
parser.accepts(SOCKS5_DISCOVER_MODE, "Specify discovery mode for Bitcoin nodes. " +
|
parser.accepts(SOCKS5_DISCOVER_MODE, "Specify discovery mode for Bitcoin nodes. " +
|
||||||
@ -686,7 +694,7 @@ public class Config {
|
|||||||
this.xmrNodeUsername = options.valueOf(xmrNodeUsernameOpt);
|
this.xmrNodeUsername = options.valueOf(xmrNodeUsernameOpt);
|
||||||
this.xmrNodePassword = options.valueOf(xmrNodePasswordOpt);
|
this.xmrNodePassword = options.valueOf(xmrNodePasswordOpt);
|
||||||
this.xmrNodes = options.valueOf(xmrNodesOpt);
|
this.xmrNodes = options.valueOf(xmrNodesOpt);
|
||||||
this.useTorForXmr = options.valueOf(useTorForXmrOpt);
|
this.useTorForXmr = (UseTorForXmr) options.valueOf(useTorForXmrOpt);
|
||||||
this.useTorForXmrOptionSetExplicitly = options.has(useTorForXmrOpt);
|
this.useTorForXmrOptionSetExplicitly = options.has(useTorForXmrOpt);
|
||||||
this.socks5DiscoverMode = options.valueOf(socks5DiscoverModeOpt);
|
this.socks5DiscoverMode = options.valueOf(socks5DiscoverModeOpt);
|
||||||
this.useAllProvidedNodes = options.valueOf(useAllProvidedNodesOpt);
|
this.useAllProvidedNodes = options.valueOf(useAllProvidedNodesOpt);
|
||||||
|
@ -333,7 +333,7 @@ public final class CoreMoneroConnectionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean useProxy(MoneroRpcConnection connection) {
|
private boolean useProxy(MoneroRpcConnection connection) {
|
||||||
return connection.isOnion() || (preferences.isUseTorForMonero() && !HavenoUtils.isLocalHost(connection.getUri()));
|
return connection.isOnion() || (preferences.getUseTorForXmr().isUseTorForXmr() && !HavenoUtils.isLocalHost(connection.getUri()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
|
@ -49,6 +49,7 @@ import haveno.core.trade.TradeManager;
|
|||||||
import haveno.core.trade.TradeTxException;
|
import haveno.core.trade.TradeTxException;
|
||||||
import haveno.core.user.Preferences;
|
import haveno.core.user.Preferences;
|
||||||
import haveno.core.user.User;
|
import haveno.core.user.User;
|
||||||
|
import haveno.core.user.Preferences.UseTorForXmr;
|
||||||
import haveno.core.util.FormattingUtils;
|
import haveno.core.util.FormattingUtils;
|
||||||
import haveno.core.util.coin.CoinFormatter;
|
import haveno.core.util.coin.CoinFormatter;
|
||||||
import haveno.core.xmr.model.AddressEntry;
|
import haveno.core.xmr.model.AddressEntry;
|
||||||
@ -63,6 +64,7 @@ import haveno.network.p2p.storage.payload.PersistableNetworkPayload;
|
|||||||
import haveno.network.utils.Utils;
|
import haveno.network.utils.Utils;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.DoubleProperty;
|
import javafx.beans.property.DoubleProperty;
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
@ -725,8 +727,8 @@ public class HavenoSetup {
|
|||||||
return walletAppSetup.getXmrSplashSyncIconId();
|
return walletAppSetup.getXmrSplashSyncIconId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanProperty getUseTorForXMR() {
|
public ObjectProperty<UseTorForXmr> getUseTorForXmr() {
|
||||||
return walletAppSetup.getUseTorForXMR();
|
return walletAppSetup.getUseTorForXmr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2P
|
// P2P
|
||||||
|
@ -25,15 +25,14 @@ import haveno.core.locale.Res;
|
|||||||
import haveno.core.offer.OpenOfferManager;
|
import haveno.core.offer.OpenOfferManager;
|
||||||
import haveno.core.trade.TradeManager;
|
import haveno.core.trade.TradeManager;
|
||||||
import haveno.core.user.Preferences;
|
import haveno.core.user.Preferences;
|
||||||
|
import haveno.core.user.Preferences.UseTorForXmr;
|
||||||
import haveno.core.util.FormattingUtils;
|
import haveno.core.util.FormattingUtils;
|
||||||
import haveno.core.xmr.exceptions.InvalidHostException;
|
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 javafx.beans.property.BooleanProperty;
|
|
||||||
import javafx.beans.property.DoubleProperty;
|
import javafx.beans.property.DoubleProperty;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
|
||||||
import javafx.beans.property.SimpleDoubleProperty;
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
@ -80,7 +79,7 @@ public class WalletAppSetup {
|
|||||||
@Getter
|
@Getter
|
||||||
private final ObjectProperty<RejectedTxException> rejectedTxException = new SimpleObjectProperty<>();
|
private final ObjectProperty<RejectedTxException> rejectedTxException = new SimpleObjectProperty<>();
|
||||||
@Getter
|
@Getter
|
||||||
private final BooleanProperty useTorForXMR = new SimpleBooleanProperty();
|
private final ObjectProperty<UseTorForXmr> useTorForXmr = new SimpleObjectProperty<UseTorForXmr>();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public WalletAppSetup(CoreContext coreContext,
|
public WalletAppSetup(CoreContext coreContext,
|
||||||
@ -95,7 +94,7 @@ public class WalletAppSetup {
|
|||||||
this.connectionService = connectionService;
|
this.connectionService = connectionService;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.preferences = preferences;
|
this.preferences = preferences;
|
||||||
this.useTorForXMR.set(preferences.getUseTorForMonero());
|
this.useTorForXmr.set(preferences.getUseTorForXmr());
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(@Nullable Consumer<String> chainFileLockedExceptionHandler,
|
void init(@Nullable Consumer<String> chainFileLockedExceptionHandler,
|
||||||
@ -239,7 +238,7 @@ public class WalletAppSetup {
|
|||||||
String postFix;
|
String postFix;
|
||||||
if (config.ignoreLocalXmrNode)
|
if (config.ignoreLocalXmrNode)
|
||||||
postFix = " " + Res.get("mainView.footer.localhostBitcoinNode");
|
postFix = " " + Res.get("mainView.footer.localhostBitcoinNode");
|
||||||
else if (preferences.getUseTorForMonero())
|
else if (preferences.getUseTorForXmr().isUseTorForXmr())
|
||||||
postFix = " " + Res.get("mainView.footer.usingTor");
|
postFix = " " + Res.get("mainView.footer.usingTor");
|
||||||
else
|
else
|
||||||
postFix = "";
|
postFix = "";
|
||||||
|
@ -838,7 +838,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
|||||||
trade.importMultisigHex();
|
trade.importMultisigHex();
|
||||||
|
|
||||||
// sync and save wallet
|
// sync and save wallet
|
||||||
trade.syncWallet();
|
trade.syncAndPollWallet();
|
||||||
trade.saveWallet();
|
trade.saveWallet();
|
||||||
|
|
||||||
// create unsigned dispute payout tx if not already published
|
// create unsigned dispute payout tx if not already published
|
||||||
@ -887,7 +887,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
|||||||
trade.getSelf().setUpdatedMultisigHex(trade.getWallet().exportMultisigHex());
|
trade.getSelf().setUpdatedMultisigHex(trade.getWallet().exportMultisigHex());
|
||||||
return payoutTx;
|
return payoutTx;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
trade.syncWallet();
|
trade.syncAndPollWallet();
|
||||||
if (!trade.isPayoutPublished()) throw e;
|
if (!trade.isPayoutPublished()) throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
|
|||||||
|
|
||||||
// sync and save wallet
|
// sync and save wallet
|
||||||
if (!trade.isPayoutPublished()) {
|
if (!trade.isPayoutPublished()) {
|
||||||
trade.syncWallet();
|
trade.syncAndPollWallet();
|
||||||
trade.saveWallet();
|
trade.saveWallet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +266,7 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
|
|||||||
if (disputeClosedMessage.isDeferPublishPayout()) {
|
if (disputeClosedMessage.isDeferPublishPayout()) {
|
||||||
log.info("Deferring signing and publishing dispute payout tx for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
log.info("Deferring signing and publishing dispute payout tx for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
||||||
GenUtils.waitFor(Trade.DEFER_PUBLISH_MS);
|
GenUtils.waitFor(Trade.DEFER_PUBLISH_MS);
|
||||||
if (!trade.isPayoutUnlocked()) trade.syncWallet();
|
if (!trade.isPayoutUnlocked()) trade.syncAndPollWallet();
|
||||||
}
|
}
|
||||||
|
|
||||||
// sign and publish dispute payout tx if peer still has not published
|
// sign and publish dispute payout tx if peer still has not published
|
||||||
@ -277,7 +277,7 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
||||||
// check if payout published again
|
// check if payout published again
|
||||||
trade.syncWallet();
|
trade.syncAndPollWallet();
|
||||||
if (trade.isPayoutPublished()) {
|
if (trade.isPayoutPublished()) {
|
||||||
log.info("Dispute payout tx already published for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
log.info("Dispute payout tx already published for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
||||||
} else {
|
} else {
|
||||||
|
@ -111,6 +111,7 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
private static final String MONERO_TRADE_WALLET_PREFIX = "xmr_trade_";
|
private static final String MONERO_TRADE_WALLET_PREFIX = "xmr_trade_";
|
||||||
private MoneroWallet wallet; // trade wallet
|
private MoneroWallet wallet; // trade wallet
|
||||||
private Object walletLock = new Object();
|
private Object walletLock = new Object();
|
||||||
|
boolean wasWalletSynced = false;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Enums
|
// Enums
|
||||||
@ -382,6 +383,7 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
transient final private ObjectProperty<DisputeState> disputeStateProperty = new SimpleObjectProperty<>(disputeState);
|
transient final private ObjectProperty<DisputeState> disputeStateProperty = new SimpleObjectProperty<>(disputeState);
|
||||||
transient final private ObjectProperty<TradePeriodState> tradePeriodStateProperty = new SimpleObjectProperty<>(periodState);
|
transient final private ObjectProperty<TradePeriodState> tradePeriodStateProperty = new SimpleObjectProperty<>(periodState);
|
||||||
transient final private StringProperty errorMessageProperty = new SimpleStringProperty();
|
transient final private StringProperty errorMessageProperty = new SimpleStringProperty();
|
||||||
|
transient private Subscription tradeStateSubscription;
|
||||||
transient private Subscription tradePhaseSubscription;
|
transient private Subscription tradePhaseSubscription;
|
||||||
transient private Subscription payoutStateSubscription;
|
transient private Subscription payoutStateSubscription;
|
||||||
transient private TaskLooper txPollLooper;
|
transient private TaskLooper txPollLooper;
|
||||||
@ -602,6 +604,14 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
setState(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG);
|
setState(Trade.State.BUYER_SENT_PAYMENT_SENT_MSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle trade state events
|
||||||
|
tradeStateSubscription = EasyBind.subscribe(stateProperty, newValue -> {
|
||||||
|
if (newValue == Trade.State.MULTISIG_COMPLETED) {
|
||||||
|
updateWalletRefreshPeriod();
|
||||||
|
startPolling();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// handle trade phase events
|
// handle trade phase events
|
||||||
tradePhaseSubscription = EasyBind.subscribe(phaseProperty, newValue -> {
|
tradePhaseSubscription = EasyBind.subscribe(phaseProperty, newValue -> {
|
||||||
if (isDepositsPublished() && !isPayoutUnlocked()) updateWalletRefreshPeriod();
|
if (isDepositsPublished() && !isPayoutUnlocked()) updateWalletRefreshPeriod();
|
||||||
@ -615,7 +625,7 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// handle payout state events
|
// handle payout events
|
||||||
payoutStateSubscription = EasyBind.subscribe(payoutStateProperty, newValue -> {
|
payoutStateSubscription = EasyBind.subscribe(payoutStateProperty, newValue -> {
|
||||||
if (isPayoutPublished()) updateWalletRefreshPeriod();
|
if (isPayoutPublished()) updateWalletRefreshPeriod();
|
||||||
|
|
||||||
@ -657,15 +667,13 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
xmrWalletService.addWalletListener(idlePayoutSyncer);
|
xmrWalletService.addWalletListener(idlePayoutSyncer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reprocess pending payout messages
|
// trade is initialized
|
||||||
this.getProtocol().maybeReprocessPaymentReceivedMessage(false);
|
|
||||||
HavenoUtils.arbitrationManager.maybeReprocessDisputeClosedMessage(this, false);
|
|
||||||
|
|
||||||
// trade is initialized but not synced
|
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
|
|
||||||
// sync wallet if applicable
|
// done if payout unlocked or deposit not requested
|
||||||
if (!isDepositRequested() || isPayoutUnlocked()) return;
|
if (!isDepositRequested() || isPayoutUnlocked()) return;
|
||||||
|
|
||||||
|
// done if wallet does not exist
|
||||||
if (!walletExists()) {
|
if (!walletExists()) {
|
||||||
MoneroTx payoutTx = getPayoutTx();
|
MoneroTx payoutTx = getPayoutTx();
|
||||||
if (payoutTx != null && payoutTx.getNumConfirmations() >= 10) {
|
if (payoutTx != null && payoutTx.getNumConfirmations() >= 10) {
|
||||||
@ -676,8 +684,9 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
throw new IllegalStateException("Missing trade wallet for " + getClass().getSimpleName() + " " + getId());
|
throw new IllegalStateException("Missing trade wallet for " + getClass().getSimpleName() + " " + getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xmrWalletService.getConnectionsService().getConnection() == null || Boolean.FALSE.equals(xmrWalletService.getConnectionsService().isConnected())) return;
|
|
||||||
updateSyncing();
|
// initialize syncing and polling
|
||||||
|
initSyncing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,7 +735,7 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
if (wallet != null) return wallet;
|
if (wallet != null) return wallet;
|
||||||
if (!walletExists()) return null;
|
if (!walletExists()) return null;
|
||||||
if (isShutDownStarted) throw new RuntimeException("Cannot open wallet for " + getClass().getSimpleName() + " " + getId() + " because shut down is started");
|
if (isShutDownStarted) throw new RuntimeException("Cannot open wallet for " + getClass().getSimpleName() + " " + getId() + " because shut down is started");
|
||||||
else wallet = xmrWalletService.openWallet(getWalletName());
|
else wallet = xmrWalletService.openWallet(getWalletName(), xmrWalletService.isProxyApplied(wasWalletSynced));
|
||||||
return wallet;
|
return wallet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -755,23 +764,8 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
return this instanceof ArbitratorTrade && isDepositsConfirmed() && walletExists(); // arbitrator idles trade after deposits confirm
|
return this instanceof ArbitratorTrade && isDepositsConfirmed() && walletExists(); // arbitrator idles trade after deposits confirm
|
||||||
}
|
}
|
||||||
|
|
||||||
public void syncWallet() {
|
public void syncAndPollWallet() {
|
||||||
if (getWallet() == null) throw new RuntimeException("Cannot sync trade wallet because it doesn't exist for " + getClass().getSimpleName() + ", " + getId());
|
syncWallet(true);
|
||||||
if (getWallet().getDaemonConnection() == null) throw new RuntimeException("Cannot sync trade wallet because it's not connected to a Monero daemon for " + getClass().getSimpleName() + ", " + getId());
|
|
||||||
log.info("Syncing wallet for {} {}", getClass().getSimpleName(), getId());
|
|
||||||
xmrWalletService.syncWallet(getWallet());
|
|
||||||
pollWallet();
|
|
||||||
log.info("Done syncing wallet for {} {}", getClass().getSimpleName(), getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void trySyncWallet() {
|
|
||||||
try {
|
|
||||||
syncWallet();
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (!isShutDown && walletExists()) {
|
|
||||||
log.warn("Error syncing trade wallet for {} {}: {}", getClass().getSimpleName(), getId(), e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void syncWalletNormallyForMs(long syncNormalDuration) {
|
public void syncWalletNormallyForMs(long syncNormalDuration) {
|
||||||
@ -1148,6 +1142,7 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
stopWallet();
|
stopWallet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tradeStateSubscription != null) tradeStateSubscription.unsubscribe();
|
||||||
if (tradePhaseSubscription != null) tradePhaseSubscription.unsubscribe();
|
if (tradePhaseSubscription != null) tradePhaseSubscription.unsubscribe();
|
||||||
if (payoutStateSubscription != null) payoutStateSubscription.unsubscribe();
|
if (payoutStateSubscription != null) payoutStateSubscription.unsubscribe();
|
||||||
idlePayoutSyncer = null; // main wallet removes listener itself
|
idlePayoutSyncer = null; // main wallet removes listener itself
|
||||||
@ -1697,44 +1692,76 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
// set daemon connection (must restart monero-wallet-rpc if proxy uri changed)
|
// set daemon connection (must restart monero-wallet-rpc if proxy uri changed)
|
||||||
String oldProxyUri = wallet.getDaemonConnection() == null ? null : wallet.getDaemonConnection().getProxyUri();
|
String oldProxyUri = wallet.getDaemonConnection() == null ? null : wallet.getDaemonConnection().getProxyUri();
|
||||||
String newProxyUri = connection == null ? null : connection.getProxyUri();
|
String newProxyUri = connection == null ? null : connection.getProxyUri();
|
||||||
log.info("Setting daemon connection for trade wallet {}: {}", getId() , connection == null ? null : connection.getUri());
|
log.info("Setting daemon connection for trade wallet {}: uri={}, proxyUri={}", getId() , connection == null ? null : connection.getUri(), newProxyUri);
|
||||||
if (wallet instanceof MoneroWalletRpc && !StringUtils.equals(oldProxyUri, newProxyUri)) {
|
if (xmrWalletService.isProxyApplied(wasWalletSynced) && wallet instanceof MoneroWalletRpc && !StringUtils.equals(oldProxyUri, newProxyUri)) {
|
||||||
log.info("Restarting monero-wallet-rpc for trade wallet to set proxy URI {}: {}", getId() , connection == null ? null : connection.getUri());
|
log.info("Restarting trade wallet {} because proxy URI has changed, old={}, new={}", getId(), oldProxyUri, newProxyUri);
|
||||||
closeWallet();
|
closeWallet();
|
||||||
wallet = getWallet();
|
wallet = getWallet();
|
||||||
} else {
|
} else {
|
||||||
wallet.setDaemonConnection(connection);
|
wallet.setDaemonConnection(connection);
|
||||||
}
|
}
|
||||||
updateWalletRefreshPeriod();
|
|
||||||
|
|
||||||
// sync and reprocess messages on new thread
|
// sync and reprocess messages on new thread
|
||||||
if (connection != null && !Boolean.FALSE.equals(connection.isConnected())) {
|
if (isInitialized && connection != null && !Boolean.FALSE.equals(connection.isConnected())) {
|
||||||
HavenoUtils.submitTask(() -> {
|
HavenoUtils.submitTask(() -> {
|
||||||
updateSyncing();
|
initSyncing();
|
||||||
|
|
||||||
// reprocess pending payout messages
|
|
||||||
this.getProtocol().maybeReprocessPaymentReceivedMessage(false);
|
|
||||||
HavenoUtils.arbitrationManager.maybeReprocessDisputeClosedMessage(this, false);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSyncing() {
|
private void initSyncing() {
|
||||||
if (isShutDownStarted) return;
|
if (isShutDownStarted) return;
|
||||||
if (!isIdling()) {
|
if (!isIdling()) {
|
||||||
updateWalletRefreshPeriod();
|
initSyncingAux();
|
||||||
trySyncWallet();
|
|
||||||
} else {
|
} else {
|
||||||
long startSyncingInMs = ThreadLocalRandom.current().nextLong(0, getWalletRefreshPeriod()); // random time to start syncing
|
long startSyncingInMs = ThreadLocalRandom.current().nextLong(0, getWalletRefreshPeriod()); // random time to start syncing
|
||||||
UserThread.runAfter(() -> {
|
UserThread.runAfter(() -> {
|
||||||
if (!isShutDownStarted) {
|
if (!isShutDownStarted) {
|
||||||
updateWalletRefreshPeriod();
|
initSyncingAux();
|
||||||
trySyncWallet();
|
|
||||||
}
|
}
|
||||||
}, startSyncingInMs / 1000l);
|
}, startSyncingInMs / 1000l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initSyncingAux() {
|
||||||
|
if (!wasWalletSynced) trySyncWallet(false);
|
||||||
|
updateWalletRefreshPeriod();
|
||||||
|
|
||||||
|
// reprocess pending payout messages
|
||||||
|
this.getProtocol().maybeReprocessPaymentReceivedMessage(false);
|
||||||
|
HavenoUtils.arbitrationManager.maybeReprocessDisputeClosedMessage(this, false);
|
||||||
|
|
||||||
|
startPolling();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trySyncWallet(boolean pollWallet) {
|
||||||
|
try {
|
||||||
|
syncWallet(pollWallet);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (!isShutDown && walletExists()) {
|
||||||
|
log.warn("Error syncing trade wallet for {} {}: {}", getClass().getSimpleName(), getId(), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncWallet(boolean pollWallet) {
|
||||||
|
if (getWallet() == null) throw new RuntimeException("Cannot sync trade wallet because it doesn't exist for " + getClass().getSimpleName() + ", " + getId());
|
||||||
|
if (getWallet().getDaemonConnection() == null) throw new RuntimeException("Cannot sync trade wallet because it's not connected to a Monero daemon for " + getClass().getSimpleName() + ", " + getId());
|
||||||
|
log.info("Syncing wallet for {} {}", getClass().getSimpleName(), getId());
|
||||||
|
xmrWalletService.syncWallet(getWallet());
|
||||||
|
log.info("Done syncing wallet for {} {}", getClass().getSimpleName(), getId());
|
||||||
|
|
||||||
|
// apply tor after wallet synced depending on configuration
|
||||||
|
if (!wasWalletSynced) {
|
||||||
|
wasWalletSynced = true;
|
||||||
|
if (xmrWalletService.isProxyApplied(wasWalletSynced)) {
|
||||||
|
onConnectionChanged(xmrWalletService.getConnectionsService().getConnection());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pollWallet) pollWallet();
|
||||||
|
}
|
||||||
|
|
||||||
public void updateWalletRefreshPeriod() {
|
public void updateWalletRefreshPeriod() {
|
||||||
setWalletRefreshPeriod(getWalletRefreshPeriod());
|
setWalletRefreshPeriod(getWalletRefreshPeriod());
|
||||||
@ -1749,14 +1776,16 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
log.info("Setting wallet refresh rate for {} {} to {}", getClass().getSimpleName(), getId(), walletRefreshPeriod);
|
log.info("Setting wallet refresh rate for {} {} to {}", getClass().getSimpleName(), getId(), walletRefreshPeriod);
|
||||||
getWallet().startSyncing(getWalletRefreshPeriod()); // TODO (monero-project): wallet rpc waits until last sync period finishes before starting new sync period
|
getWallet().startSyncing(getWalletRefreshPeriod()); // TODO (monero-project): wallet rpc waits until last sync period finishes before starting new sync period
|
||||||
}
|
}
|
||||||
stopPolling();
|
if (isPolling()) {
|
||||||
|
stopPolling();
|
||||||
|
startPolling();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
startPolling();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startPolling() {
|
private void startPolling() {
|
||||||
synchronized (walletLock) {
|
synchronized (walletLock) {
|
||||||
if (txPollLooper != null) return;
|
if (isPolling()) return;
|
||||||
log.info("Starting to poll wallet for {} {}", getClass().getSimpleName(), getId());
|
log.info("Starting to poll wallet for {} {}", getClass().getSimpleName(), getId());
|
||||||
txPollLooper = new TaskLooper(() -> pollWallet());
|
txPollLooper = new TaskLooper(() -> pollWallet());
|
||||||
txPollLooper.start(walletRefreshPeriod);
|
txPollLooper.start(walletRefreshPeriod);
|
||||||
@ -1765,12 +1794,18 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
|
|
||||||
private void stopPolling() {
|
private void stopPolling() {
|
||||||
synchronized (walletLock) {
|
synchronized (walletLock) {
|
||||||
if (txPollLooper != null) {
|
if (isPolling()) {
|
||||||
txPollLooper.stop();
|
txPollLooper.stop();
|
||||||
txPollLooper = null;
|
txPollLooper = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPolling() {
|
||||||
|
synchronized (walletLock) {
|
||||||
|
return txPollLooper != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void pollWallet() {
|
private void pollWallet() {
|
||||||
try {
|
try {
|
||||||
@ -1855,7 +1890,6 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private long getWalletRefreshPeriod() {
|
private long getWalletRefreshPeriod() {
|
||||||
if (isIdling()) return IDLE_SYNC_PERIOD_MS;
|
if (isIdling()) return IDLE_SYNC_PERIOD_MS;
|
||||||
return xmrWalletService.getConnectionsService().getRefreshPeriodMs();
|
return xmrWalletService.getConnectionsService().getRefreshPeriodMs();
|
||||||
@ -1924,7 +1958,7 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
long currentHeight = xmrWalletService.getDaemon().getHeight();
|
long currentHeight = xmrWalletService.getDaemon().getHeight();
|
||||||
if (!isPayoutConfirmed() || (payoutHeight != null && currentHeight >= payoutHeight + XmrWalletService.NUM_BLOCKS_UNLOCK)) {
|
if (!isPayoutConfirmed() || (payoutHeight != null && currentHeight >= payoutHeight + XmrWalletService.NUM_BLOCKS_UNLOCK)) {
|
||||||
log.info("Syncing idle trade wallet to update payout tx, tradeId={}", getId());
|
log.info("Syncing idle trade wallet to update payout tx, tradeId={}", getId());
|
||||||
syncWallet();
|
syncAndPollWallet();
|
||||||
}
|
}
|
||||||
processing = false;
|
processing = false;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -449,7 +449,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
|||||||
|
|
||||||
// sync idle trades once in background after active trades
|
// sync idle trades once in background after active trades
|
||||||
for (Trade trade : trades) {
|
for (Trade trade : trades) {
|
||||||
if (trade.isIdling()) HavenoUtils.submitTask(() -> trade.syncWallet());
|
if (trade.isIdling()) HavenoUtils.submitTask(() -> trade.syncAndPollWallet());
|
||||||
}
|
}
|
||||||
|
|
||||||
// process after all wallets initialized
|
// process after all wallets initialized
|
||||||
|
@ -112,7 +112,6 @@ public class ProcessInitMultisigRequest extends TradeTask {
|
|||||||
processModel.setMultisigAddress(result.getAddress());
|
processModel.setMultisigAddress(result.getAddress());
|
||||||
new Thread(() -> trade.saveWallet()).start(); // save multisig wallet off thread on completion
|
new Thread(() -> trade.saveWallet()).start(); // save multisig wallet off thread on completion
|
||||||
trade.setStateIfValidTransitionTo(Trade.State.MULTISIG_COMPLETED);
|
trade.setStateIfValidTransitionTo(Trade.State.MULTISIG_COMPLETED);
|
||||||
trade.updateWalletRefreshPeriod(); // starts syncing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update multisig participants if new state to communicate
|
// update multisig participants if new state to communicate
|
||||||
|
@ -105,7 +105,7 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
|
|||||||
|
|
||||||
// update wallet
|
// update wallet
|
||||||
trade.importMultisigHex();
|
trade.importMultisigHex();
|
||||||
trade.syncWallet();
|
trade.syncAndPollWallet();
|
||||||
trade.saveWallet();
|
trade.saveWallet();
|
||||||
|
|
||||||
// handle if payout tx not published
|
// handle if payout tx not published
|
||||||
@ -117,7 +117,7 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
|
|||||||
if (deferSignAndPublish) {
|
if (deferSignAndPublish) {
|
||||||
log.info("Deferring signing and publishing payout tx for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
log.info("Deferring signing and publishing payout tx for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
||||||
GenUtils.waitFor(Trade.DEFER_PUBLISH_MS);
|
GenUtils.waitFor(Trade.DEFER_PUBLISH_MS);
|
||||||
if (!trade.isPayoutUnlocked()) trade.syncWallet();
|
if (!trade.isPayoutUnlocked()) trade.syncAndPollWallet();
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify and publish payout tx
|
// verify and publish payout tx
|
||||||
@ -136,7 +136,7 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
|
|||||||
trade.verifyPayoutTx(trade.getPayoutTxHex(), false, true);
|
trade.verifyPayoutTx(trade.getPayoutTxHex(), false, true);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
trade.syncWallet();
|
trade.syncAndPollWallet();
|
||||||
if (trade.isPayoutPublished()) log.info("Payout tx already published for {} {}", trade.getClass().getName(), trade.getId());
|
if (trade.isPayoutPublished()) log.info("Payout tx already published for {} {}", trade.getClass().getName(), trade.getId());
|
||||||
else throw e;
|
else throw e;
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,16 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Singleton
|
@Singleton
|
||||||
public final class Preferences implements PersistedDataHost, BridgeAddressProvider {
|
public final class Preferences implements PersistedDataHost, BridgeAddressProvider {
|
||||||
|
|
||||||
|
public enum UseTorForXmr {
|
||||||
|
AFTER_SYNC,
|
||||||
|
OFF,
|
||||||
|
ON;
|
||||||
|
|
||||||
|
public boolean isUseTorForXmr() {
|
||||||
|
return this != UseTorForXmr.OFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final ArrayList<BlockChainExplorer> BTC_MAIN_NET_EXPLORERS = new ArrayList<>(Arrays.asList(
|
private static final ArrayList<BlockChainExplorer> BTC_MAIN_NET_EXPLORERS = new ArrayList<>(Arrays.asList(
|
||||||
new BlockChainExplorer("mempool.space (@wiz)", "https://mempool.space/tx/", "https://mempool.space/address/"),
|
new BlockChainExplorer("mempool.space (@wiz)", "https://mempool.space/tx/", "https://mempool.space/address/"),
|
||||||
@ -300,7 +310,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||||||
|
|
||||||
// Override settings with options if set
|
// Override settings with options if set
|
||||||
if (config.useTorForXmrOptionSetExplicitly)
|
if (config.useTorForXmrOptionSetExplicitly)
|
||||||
setUseTorForMonero(config.useTorForXmr);
|
setUseTorForXmr(config.useTorForXmr);
|
||||||
|
|
||||||
if (xmrNodesFromOptions != null && !xmrNodesFromOptions.isEmpty()) {
|
if (xmrNodesFromOptions != null && !xmrNodesFromOptions.isEmpty()) {
|
||||||
if (getMoneroNodes() != null && !getMoneroNodes().equals(xmrNodesFromOptions)) {
|
if (getMoneroNodes() != null && !getMoneroNodes().equals(xmrNodesFromOptions)) {
|
||||||
@ -488,9 +498,20 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUseTorForMonero(boolean useTorForMonero) {
|
public void setUseTorForXmr(Config.UseTorForXmr useTorForXmr) {
|
||||||
prefPayload.setUseTorForMonero(useTorForMonero);
|
switch (useTorForXmr) {
|
||||||
requestPersistence();
|
case AFTER_SYNC:
|
||||||
|
setUseTorForXmrOrdinal(Preferences.UseTorForXmr.AFTER_SYNC.ordinal());
|
||||||
|
break;
|
||||||
|
case OFF:
|
||||||
|
setUseTorForXmrOrdinal(Preferences.UseTorForXmr.OFF.ordinal());
|
||||||
|
break;
|
||||||
|
case ON:
|
||||||
|
setUseTorForXmrOrdinal(Preferences.UseTorForXmr.ON.ordinal());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unexpected case: " + useTorForXmr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSplitOfferOutput(boolean splitOfferOutput) {
|
public void setSplitOfferOutput(boolean splitOfferOutput) {
|
||||||
@ -663,6 +684,11 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||||||
prefPayload.setCustomBridges(customBridges);
|
prefPayload.setCustomBridges(customBridges);
|
||||||
persistenceManager.forcePersistNow();
|
persistenceManager.forcePersistNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setUseTorForXmrOrdinal(int useTorForXmrOrdinal) {
|
||||||
|
prefPayload.setUseTorForXmrOrdinal(useTorForXmrOrdinal);
|
||||||
|
requestPersistence();
|
||||||
|
}
|
||||||
|
|
||||||
public void setMoneroNodesOptionOrdinal(int bitcoinNodesOptionOrdinal) {
|
public void setMoneroNodesOptionOrdinal(int bitcoinNodesOptionOrdinal) {
|
||||||
prefPayload.setMoneroNodesOptionOrdinal(bitcoinNodesOptionOrdinal);
|
prefPayload.setMoneroNodesOptionOrdinal(bitcoinNodesOptionOrdinal);
|
||||||
@ -794,8 +820,12 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||||||
return !prefPayload.getDontShowAgainMap().containsKey(key) || !prefPayload.getDontShowAgainMap().get(key);
|
return !prefPayload.getDontShowAgainMap().containsKey(key) || !prefPayload.getDontShowAgainMap().get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getUseTorForMonero() {
|
public UseTorForXmr getUseTorForXmr() {
|
||||||
return prefPayload.isUseTorForMonero();
|
return UseTorForXmr.class.getEnumConstants()[prefPayload.getUseTorForXmrOrdinal()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isProxyApplied(boolean wasWalletSynced) {
|
||||||
|
return getUseTorForXmr() == UseTorForXmr.ON || (getUseTorForXmr() == UseTorForXmr.AFTER_SYNC && wasWalletSynced);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getSplitOfferOutput() {
|
public boolean getSplitOfferOutput() {
|
||||||
@ -864,8 +894,6 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||||||
|
|
||||||
void setPreferredTradeCurrency(TradeCurrency preferredTradeCurrency);
|
void setPreferredTradeCurrency(TradeCurrency preferredTradeCurrency);
|
||||||
|
|
||||||
void setUseTorForMonero(boolean useTorForMonero);
|
|
||||||
|
|
||||||
void setSplitOfferOutput(boolean splitOfferOutput);
|
void setSplitOfferOutput(boolean splitOfferOutput);
|
||||||
|
|
||||||
void setShowOwnOffersInOfferBook(boolean showOwnOffersInOfferBook);
|
void setShowOwnOffersInOfferBook(boolean showOwnOffersInOfferBook);
|
||||||
@ -927,6 +955,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||||||
void setTorTransportOrdinal(int torTransportOrdinal);
|
void setTorTransportOrdinal(int torTransportOrdinal);
|
||||||
|
|
||||||
void setCustomBridges(String customBridges);
|
void setCustomBridges(String customBridges);
|
||||||
|
|
||||||
|
void setUseTorForXmrOrdinal(int useTorForXmrOrdinal);
|
||||||
|
|
||||||
void setMoneroNodesOptionOrdinal(int bitcoinNodesOption);
|
void setMoneroNodesOptionOrdinal(int bitcoinNodesOption);
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||||||
private boolean autoSelectArbitrators = true;
|
private boolean autoSelectArbitrators = true;
|
||||||
private Map<String, Boolean> dontShowAgainMap = new HashMap<>();
|
private Map<String, Boolean> dontShowAgainMap = new HashMap<>();
|
||||||
private boolean tacAccepted;
|
private boolean tacAccepted;
|
||||||
private boolean useTorForMonero = false;
|
|
||||||
private boolean splitOfferOutput = false;
|
private boolean splitOfferOutput = false;
|
||||||
private boolean showOwnOffersInOfferBook = true;
|
private boolean showOwnOffersInOfferBook = true;
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -98,6 +97,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||||||
private int torTransportOrdinal;
|
private int torTransportOrdinal;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String customBridges;
|
private String customBridges;
|
||||||
|
private int useTorForXmrOrdinal;
|
||||||
private int moneroNodesOptionOrdinal;
|
private int moneroNodesOptionOrdinal;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String referralId;
|
private String referralId;
|
||||||
@ -161,7 +161,6 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||||||
.setAutoSelectArbitrators(autoSelectArbitrators)
|
.setAutoSelectArbitrators(autoSelectArbitrators)
|
||||||
.putAllDontShowAgainMap(dontShowAgainMap)
|
.putAllDontShowAgainMap(dontShowAgainMap)
|
||||||
.setTacAccepted(tacAccepted)
|
.setTacAccepted(tacAccepted)
|
||||||
.setUseTorForMonero(useTorForMonero)
|
|
||||||
.setSplitOfferOutput(splitOfferOutput)
|
.setSplitOfferOutput(splitOfferOutput)
|
||||||
.setShowOwnOffersInOfferBook(showOwnOffersInOfferBook)
|
.setShowOwnOffersInOfferBook(showOwnOffersInOfferBook)
|
||||||
.setWithdrawalTxFeeInVbytes(withdrawalTxFeeInVbytes)
|
.setWithdrawalTxFeeInVbytes(withdrawalTxFeeInVbytes)
|
||||||
@ -179,6 +178,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||||||
.setCssTheme(cssTheme)
|
.setCssTheme(cssTheme)
|
||||||
.setBridgeOptionOrdinal(bridgeOptionOrdinal)
|
.setBridgeOptionOrdinal(bridgeOptionOrdinal)
|
||||||
.setTorTransportOrdinal(torTransportOrdinal)
|
.setTorTransportOrdinal(torTransportOrdinal)
|
||||||
|
.setUseTorForXmrOrdinal(useTorForXmrOrdinal)
|
||||||
.setMoneroNodesOptionOrdinal(moneroNodesOptionOrdinal)
|
.setMoneroNodesOptionOrdinal(moneroNodesOptionOrdinal)
|
||||||
.setUseSoundForMobileNotifications(useSoundForMobileNotifications)
|
.setUseSoundForMobileNotifications(useSoundForMobileNotifications)
|
||||||
.setUseTradeNotifications(useTradeNotifications)
|
.setUseTradeNotifications(useTradeNotifications)
|
||||||
@ -244,7 +244,6 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||||||
proto.getAutoSelectArbitrators(),
|
proto.getAutoSelectArbitrators(),
|
||||||
Maps.newHashMap(proto.getDontShowAgainMapMap()),
|
Maps.newHashMap(proto.getDontShowAgainMapMap()),
|
||||||
proto.getTacAccepted(),
|
proto.getTacAccepted(),
|
||||||
proto.getUseTorForMonero(),
|
|
||||||
proto.getSplitOfferOutput(),
|
proto.getSplitOfferOutput(),
|
||||||
proto.getShowOwnOffersInOfferBook(),
|
proto.getShowOwnOffersInOfferBook(),
|
||||||
proto.hasPreferredTradeCurrency() ? TradeCurrency.fromProto(proto.getPreferredTradeCurrency()) : null,
|
proto.hasPreferredTradeCurrency() ? TradeCurrency.fromProto(proto.getPreferredTradeCurrency()) : null,
|
||||||
@ -272,6 +271,7 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||||||
proto.getBridgeOptionOrdinal(),
|
proto.getBridgeOptionOrdinal(),
|
||||||
proto.getTorTransportOrdinal(),
|
proto.getTorTransportOrdinal(),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getCustomBridges()),
|
ProtoUtil.stringOrNullFromProto(proto.getCustomBridges()),
|
||||||
|
proto.getUseTorForXmrOrdinal(),
|
||||||
proto.getMoneroNodesOptionOrdinal(),
|
proto.getMoneroNodesOptionOrdinal(),
|
||||||
proto.getReferralId().isEmpty() ? null : proto.getReferralId(),
|
proto.getReferralId().isEmpty() ? null : proto.getReferralId(),
|
||||||
proto.getPhoneKeyAndToken().isEmpty() ? null : proto.getPhoneKeyAndToken(),
|
proto.getPhoneKeyAndToken().isEmpty() ? null : proto.getPhoneKeyAndToken(),
|
||||||
|
@ -171,7 +171,7 @@ public class WalletsSetup {
|
|||||||
|
|
||||||
backupWallets();
|
backupWallets();
|
||||||
|
|
||||||
final Socks5Proxy socks5Proxy = preferences.getUseTorForMonero() ? socks5ProxyProvider.getSocks5Proxy() : null;
|
final Socks5Proxy socks5Proxy = socks5ProxyProvider.getSocks5Proxy();
|
||||||
log.info("Socks5Proxy for bitcoinj: socks5Proxy=" + socks5Proxy);
|
log.info("Socks5Proxy for bitcoinj: socks5Proxy=" + socks5Proxy);
|
||||||
|
|
||||||
walletConfig = new WalletConfig(params, walletDir, "haveno") {
|
walletConfig = new WalletConfig(params, walletDir, "haveno") {
|
||||||
|
@ -19,6 +19,7 @@ import haveno.core.trade.HavenoUtils;
|
|||||||
import haveno.core.trade.MakerTrade;
|
import haveno.core.trade.MakerTrade;
|
||||||
import haveno.core.trade.Trade;
|
import haveno.core.trade.Trade;
|
||||||
import haveno.core.trade.TradeManager;
|
import haveno.core.trade.TradeManager;
|
||||||
|
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;
|
||||||
@ -54,7 +55,6 @@ import monero.wallet.model.MoneroWalletListenerI;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@ -100,6 +100,7 @@ public class XmrWalletService {
|
|||||||
private static final int MONERO_LOG_LEVEL = 0;
|
private static final int MONERO_LOG_LEVEL = 0;
|
||||||
private static final boolean PRINT_STACK_TRACE = false;
|
private static final boolean PRINT_STACK_TRACE = false;
|
||||||
|
|
||||||
|
private final Preferences preferences;
|
||||||
private final CoreAccountService accountService;
|
private final CoreAccountService accountService;
|
||||||
private final CoreMoneroConnectionsService connectionsService;
|
private final CoreMoneroConnectionsService connectionsService;
|
||||||
private final XmrAddressEntryList xmrAddressEntryList;
|
private final XmrAddressEntryList xmrAddressEntryList;
|
||||||
@ -114,17 +115,20 @@ public class XmrWalletService {
|
|||||||
private TradeManager tradeManager;
|
private TradeManager tradeManager;
|
||||||
private MoneroWalletRpc wallet;
|
private MoneroWalletRpc wallet;
|
||||||
private Object walletLock = new Object();
|
private Object walletLock = new Object();
|
||||||
|
private boolean wasWalletSynced = false;
|
||||||
private final Map<String, Optional<MoneroTx>> txCache = new HashMap<String, Optional<MoneroTx>>();
|
private final Map<String, Optional<MoneroTx>> txCache = new HashMap<String, Optional<MoneroTx>>();
|
||||||
private boolean isShutDownStarted = false;
|
private boolean isShutDownStarted = false;
|
||||||
private ExecutorService syncWalletThreadPool = Executors.newFixedThreadPool(10); // TODO: adjust based on connection type
|
private ExecutorService syncWalletThreadPool = Executors.newFixedThreadPool(10); // TODO: adjust based on connection type
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
XmrWalletService(CoreAccountService accountService,
|
XmrWalletService(Preferences preferences,
|
||||||
|
CoreAccountService accountService,
|
||||||
CoreMoneroConnectionsService connectionsService,
|
CoreMoneroConnectionsService connectionsService,
|
||||||
WalletsSetup walletsSetup,
|
WalletsSetup walletsSetup,
|
||||||
XmrAddressEntryList xmrAddressEntryList,
|
XmrAddressEntryList xmrAddressEntryList,
|
||||||
@Named(Config.WALLET_DIR) File walletDir,
|
@Named(Config.WALLET_DIR) File walletDir,
|
||||||
@Named(Config.WALLET_RPC_BIND_PORT) int rpcBindPort) {
|
@Named(Config.WALLET_RPC_BIND_PORT) int rpcBindPort) {
|
||||||
|
this.preferences = preferences;
|
||||||
this.accountService = accountService;
|
this.accountService = accountService;
|
||||||
this.connectionsService = connectionsService;
|
this.connectionsService = connectionsService;
|
||||||
this.walletsSetup = walletsSetup;
|
this.walletsSetup = walletsSetup;
|
||||||
@ -212,6 +216,10 @@ public class XmrWalletService {
|
|||||||
public CoreMoneroConnectionsService getConnectionsService() {
|
public CoreMoneroConnectionsService getConnectionsService() {
|
||||||
return connectionsService;
|
return connectionsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isProxyApplied(boolean wasWalletSynced) {
|
||||||
|
return preferences.isProxyApplied(wasWalletSynced);
|
||||||
|
}
|
||||||
|
|
||||||
public String getWalletPassword() {
|
public String getWalletPassword() {
|
||||||
return accountService.getPassword() == null ? MONERO_WALLET_RPC_DEFAULT_PASSWORD : accountService.getPassword();
|
return accountService.getPassword() == null ? MONERO_WALLET_RPC_DEFAULT_PASSWORD : accountService.getPassword();
|
||||||
@ -231,13 +239,14 @@ public class XmrWalletService {
|
|||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MoneroWalletRpc openWallet(String walletName) {
|
public MoneroWalletRpc openWallet(String walletName, boolean applyProxyUri) {
|
||||||
log.info("{}.openWallet({})", getClass().getSimpleName(), walletName);
|
log.info("{}.openWallet({})", getClass().getSimpleName(), walletName);
|
||||||
if (isShutDownStarted) throw new IllegalStateException("Cannot open wallet because shutting down");
|
if (isShutDownStarted) throw new IllegalStateException("Cannot open wallet because shutting down");
|
||||||
return openWalletRpc(new MoneroWalletConfig()
|
return openWalletRpc(new MoneroWalletConfig()
|
||||||
.setPath(walletName)
|
.setPath(walletName)
|
||||||
.setPassword(getWalletPassword()),
|
.setPassword(getWalletPassword()),
|
||||||
null);
|
null,
|
||||||
|
applyProxyUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -670,7 +679,7 @@ public class XmrWalletService {
|
|||||||
log.info("Initializing main wallet with monerod=" + (daemon == null ? "null" : daemon.getRpcConnection().getUri()));
|
log.info("Initializing main wallet with monerod=" + (daemon == null ? "null" : daemon.getRpcConnection().getUri()));
|
||||||
MoneroWalletConfig walletConfig = new MoneroWalletConfig().setPath(MONERO_WALLET_NAME).setPassword(getWalletPassword());
|
MoneroWalletConfig walletConfig = new MoneroWalletConfig().setPath(MONERO_WALLET_NAME).setPassword(getWalletPassword());
|
||||||
if (MoneroUtils.walletExists(xmrWalletFile.getPath())) {
|
if (MoneroUtils.walletExists(xmrWalletFile.getPath())) {
|
||||||
wallet = openWalletRpc(walletConfig, rpcBindPort);
|
wallet = openWalletRpc(walletConfig, rpcBindPort, isProxyApplied(wasWalletSynced));
|
||||||
} else if (connectionsService.getConnection() != null && Boolean.TRUE.equals(connectionsService.getConnection().isConnected())) {
|
} else if (connectionsService.getConnection() != null && Boolean.TRUE.equals(connectionsService.getConnection().isConnected())) {
|
||||||
wallet = createWalletRpc(walletConfig, rpcBindPort);
|
wallet = createWalletRpc(walletConfig, rpcBindPort);
|
||||||
}
|
}
|
||||||
@ -688,9 +697,13 @@ public class XmrWalletService {
|
|||||||
log.info("Syncing main wallet");
|
log.info("Syncing main wallet");
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
wallet.sync(); // blocking
|
wallet.sync(); // blocking
|
||||||
|
wasWalletSynced = true;
|
||||||
log.info("Done syncing main wallet in " + (System.currentTimeMillis() - time) + " ms");
|
log.info("Done syncing main wallet in " + (System.currentTimeMillis() - time) + " ms");
|
||||||
wallet.startSyncing(connectionsService.getRefreshPeriodMs());
|
wallet.startSyncing(connectionsService.getRefreshPeriodMs());
|
||||||
if (getMoneroNetworkType() != MoneroNetworkType.MAINNET) log.info("Monero wallet balance={}, unlocked balance={}", wallet.getBalance(0), wallet.getUnlockedBalance(0));
|
if (getMoneroNetworkType() != MoneroNetworkType.MAINNET) log.info("Monero wallet balance={}, unlocked balance={}", wallet.getBalance(0), wallet.getUnlockedBalance(0));
|
||||||
|
|
||||||
|
// reapply connection after wallet synced
|
||||||
|
onConnectionChanged(connectionsService.getConnection());
|
||||||
|
|
||||||
// TODO: using this to signify both daemon and wallet synced, use separate sync handlers?
|
// TODO: using this to signify both daemon and wallet synced, use separate sync handlers?
|
||||||
connectionsService.doneDownload();
|
connectionsService.doneDownload();
|
||||||
@ -742,7 +755,7 @@ public class XmrWalletService {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
// start monero-wallet-rpc instance
|
// start monero-wallet-rpc instance
|
||||||
walletRpc = startWalletRpcInstance(port);
|
walletRpc = startWalletRpcInstance(port, isProxyApplied(false));
|
||||||
walletRpc.getRpcConnection().setPrintStackTrace(PRINT_STACK_TRACE);
|
walletRpc.getRpcConnection().setPrintStackTrace(PRINT_STACK_TRACE);
|
||||||
|
|
||||||
// prevent wallet rpc from syncing
|
// prevent wallet rpc from syncing
|
||||||
@ -762,20 +775,23 @@ public class XmrWalletService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MoneroWalletRpc openWalletRpc(MoneroWalletConfig config, Integer port) {
|
private MoneroWalletRpc openWalletRpc(MoneroWalletConfig config, Integer port, boolean applyProxyUri) {
|
||||||
MoneroWalletRpc walletRpc = null;
|
MoneroWalletRpc walletRpc = null;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// start monero-wallet-rpc instance
|
// start monero-wallet-rpc instance
|
||||||
walletRpc = startWalletRpcInstance(port);
|
walletRpc = startWalletRpcInstance(port, applyProxyUri);
|
||||||
walletRpc.getRpcConnection().setPrintStackTrace(PRINT_STACK_TRACE);
|
walletRpc.getRpcConnection().setPrintStackTrace(PRINT_STACK_TRACE);
|
||||||
|
|
||||||
// prevent wallet rpc from syncing
|
// prevent wallet rpc from syncing
|
||||||
walletRpc.stopSyncing();
|
walletRpc.stopSyncing();
|
||||||
|
|
||||||
|
// configure connection
|
||||||
|
MoneroRpcConnection connection = new MoneroRpcConnection(connectionsService.getConnection());
|
||||||
|
if (!applyProxyUri) connection.setProxyUri(null);
|
||||||
|
|
||||||
// open wallet
|
// open wallet
|
||||||
log.info("Opening wallet " + config.getPath());
|
walletRpc.openWallet(config.setServer(connection));
|
||||||
walletRpc.openWallet(config.setServer(connectionsService.getConnection()));
|
|
||||||
if (walletRpc.getDaemonConnection() != null) walletRpc.getDaemonConnection().setPrintStackTrace(PRINT_STACK_TRACE);
|
if (walletRpc.getDaemonConnection() != null) walletRpc.getDaemonConnection().setPrintStackTrace(PRINT_STACK_TRACE);
|
||||||
log.info("Done opening wallet " + config.getPath());
|
log.info("Done opening wallet " + config.getPath());
|
||||||
return walletRpc;
|
return walletRpc;
|
||||||
@ -786,7 +802,7 @@ public class XmrWalletService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MoneroWalletRpc startWalletRpcInstance(Integer port) {
|
private MoneroWalletRpc startWalletRpcInstance(Integer port, boolean applyProxyUri) {
|
||||||
|
|
||||||
// check if monero-wallet-rpc exists
|
// check if monero-wallet-rpc exists
|
||||||
if (!new File(MONERO_WALLET_RPC_PATH).exists()) throw new Error("monero-wallet-rpc executable doesn't exist at path " + MONERO_WALLET_RPC_PATH
|
if (!new File(MONERO_WALLET_RPC_PATH).exists()) throw new Error("monero-wallet-rpc executable doesn't exist at path " + MONERO_WALLET_RPC_PATH
|
||||||
@ -808,7 +824,7 @@ public class XmrWalletService {
|
|||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
cmd.add("--daemon-address");
|
cmd.add("--daemon-address");
|
||||||
cmd.add(connection.getUri());
|
cmd.add(connection.getUri());
|
||||||
if (connection.getProxyUri() != null) {
|
if (applyProxyUri && connection.getProxyUri() != null) { // TODO: only apply proxy if wallet is already synced, so we need a flag passed here
|
||||||
cmd.add("--proxy");
|
cmd.add("--proxy");
|
||||||
cmd.add(connection.getProxyUri());
|
cmd.add(connection.getProxyUri());
|
||||||
if (!connection.isOnion()) cmd.add("--daemon-ssl-allow-any-cert"); // necessary to use proxy with clearnet mmonerod
|
if (!connection.isOnion()) cmd.add("--daemon-ssl-allow-any-cert"); // necessary to use proxy with clearnet mmonerod
|
||||||
@ -831,13 +847,12 @@ public class XmrWalletService {
|
|||||||
synchronized (walletLock) {
|
synchronized (walletLock) {
|
||||||
if (isShutDownStarted) return;
|
if (isShutDownStarted) return;
|
||||||
if (wallet != null && HavenoUtils.connectionConfigsEqual(connection, wallet.getDaemonConnection())) return;
|
if (wallet != null && HavenoUtils.connectionConfigsEqual(connection, wallet.getDaemonConnection())) return;
|
||||||
|
|
||||||
log.info("Setting main wallet daemon connection: " + (connection == null ? null : connection.getUri()));
|
|
||||||
String oldProxyUri = wallet == null || wallet.getDaemonConnection() == null ? null : wallet.getDaemonConnection().getProxyUri();
|
String oldProxyUri = wallet == null || wallet.getDaemonConnection() == null ? null : wallet.getDaemonConnection().getProxyUri();
|
||||||
String newProxyUri = connection == null ? null : connection.getProxyUri();
|
String newProxyUri = connection == null ? null : connection.getProxyUri();
|
||||||
|
log.info("Setting daemon connection for main wallet: uri={}, proxyUri={}", connection == null ? null : connection.getUri(), newProxyUri);
|
||||||
if (wallet == null) maybeInitMainWallet(false);
|
if (wallet == null) maybeInitMainWallet(false);
|
||||||
else if (wallet instanceof MoneroWalletRpc && !StringUtils.equals(oldProxyUri, newProxyUri)) {
|
else if (wallet instanceof MoneroWalletRpc && !StringUtils.equals(oldProxyUri, newProxyUri)) {
|
||||||
log.info("Restarting main wallet because proxy URI has changed");
|
log.info("Restarting main wallet because proxy URI has changed, old={}, new={}", oldProxyUri, newProxyUri);
|
||||||
closeMainWallet(true);
|
closeMainWallet(true);
|
||||||
maybeInitMainWallet(false);
|
maybeInitMainWallet(false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1254,7 +1254,7 @@ setting.preferences.prefCurrency=Preferred currency
|
|||||||
setting.preferences.displayTraditional=Display traditional currencies
|
setting.preferences.displayTraditional=Display traditional currencies
|
||||||
setting.preferences.noTraditional=There are no traditional currencies selected
|
setting.preferences.noTraditional=There are no traditional currencies selected
|
||||||
setting.preferences.cannotRemovePrefCurrency=You cannot remove your selected preferred display currency
|
setting.preferences.cannotRemovePrefCurrency=You cannot remove your selected preferred display currency
|
||||||
setting.preferences.displayCryptos=Display cryptose
|
setting.preferences.displayCryptos=Display cryptos
|
||||||
setting.preferences.noCryptos=There are no cryptos selected
|
setting.preferences.noCryptos=There are no cryptos selected
|
||||||
setting.preferences.addTraditional=Add traditional currency
|
setting.preferences.addTraditional=Add traditional currency
|
||||||
setting.preferences.addCrypto=Add cryptocurrency
|
setting.preferences.addCrypto=Add cryptocurrency
|
||||||
@ -1284,6 +1284,9 @@ settings.net.onionAddressLabel=My onion address
|
|||||||
settings.net.xmrNodesLabel=Use custom Monero nodes
|
settings.net.xmrNodesLabel=Use custom Monero nodes
|
||||||
settings.net.moneroPeersLabel=Connected peers
|
settings.net.moneroPeersLabel=Connected peers
|
||||||
settings.net.useTorForXmrJLabel=Use Tor for Monero network
|
settings.net.useTorForXmrJLabel=Use Tor for Monero network
|
||||||
|
settings.net.useTorForXmrAfterSyncRadio=After wallet is synchronized
|
||||||
|
settings.net.useTorForXmrOffRadio=Never
|
||||||
|
settings.net.useTorForXmrOnRadio=Always
|
||||||
settings.net.moneroNodesLabel=Monero nodes to connect to
|
settings.net.moneroNodesLabel=Monero nodes to connect to
|
||||||
settings.net.useProvidedNodesRadio=Use provided Monero nodes
|
settings.net.useProvidedNodesRadio=Use provided Monero nodes
|
||||||
settings.net.usePublicNodesRadio=Use public Monero network
|
settings.net.usePublicNodesRadio=Use public Monero network
|
||||||
|
@ -574,7 +574,7 @@ 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.getUseTorForXMR().get()) {
|
if (model.getUseTorForXmr().get().isUseTorForXmr()) {
|
||||||
// If using tor for XMR, hide the XMR status since tor is not working
|
// If using tor for XMR, hide the XMR status since tor is not working
|
||||||
xmrSyncIndicator.setVisible(false);
|
xmrSyncIndicator.setVisible(false);
|
||||||
xmrSplashInfo.setVisible(false);
|
xmrSplashInfo.setVisible(false);
|
||||||
|
@ -47,6 +47,7 @@ import haveno.core.provider.price.PriceFeedService;
|
|||||||
import haveno.core.trade.TradeManager;
|
import haveno.core.trade.TradeManager;
|
||||||
import haveno.core.user.DontShowAgainLookup;
|
import haveno.core.user.DontShowAgainLookup;
|
||||||
import haveno.core.user.Preferences;
|
import haveno.core.user.Preferences;
|
||||||
|
import haveno.core.user.Preferences.UseTorForXmr;
|
||||||
import haveno.core.user.User;
|
import haveno.core.user.User;
|
||||||
import haveno.core.xmr.wallet.XmrWalletService;
|
import haveno.core.xmr.wallet.XmrWalletService;
|
||||||
import haveno.desktop.Navigation;
|
import haveno.desktop.Navigation;
|
||||||
@ -628,8 +629,8 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener
|
|||||||
return havenoSetup.getXmrSplashSyncIconId();
|
return havenoSetup.getXmrSplashSyncIconId();
|
||||||
}
|
}
|
||||||
|
|
||||||
BooleanProperty getUseTorForXMR() {
|
ObjectProperty<UseTorForXmr> getUseTorForXmr() {
|
||||||
return havenoSetup.getUseTorForXMR();
|
return havenoSetup.getUseTorForXmr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2P
|
// P2P
|
||||||
|
@ -73,7 +73,14 @@
|
|||||||
<AutoTooltipLabel fx:id="localhostXmrNodeInfoLabel" styleClass="small-text"/>
|
<AutoTooltipLabel fx:id="localhostXmrNodeInfoLabel" styleClass="small-text"/>
|
||||||
</VBox>
|
</VBox>
|
||||||
|
|
||||||
<AutoTooltipCheckBox fx:id="useTorForXmrJCheckBox" GridPane.rowIndex="1"/>
|
<VBox GridPane.rowIndex="1">
|
||||||
|
<AutoTooltipLabel fx:id="useTorForXmrLabel" styleClass="small-text"/>
|
||||||
|
<HBox spacing="10">
|
||||||
|
<AutoTooltipRadioButton fx:id="useTorForXmrAfterSyncRadio"/>
|
||||||
|
<AutoTooltipRadioButton fx:id="useTorForXmrOnRadio"/>
|
||||||
|
<AutoTooltipRadioButton fx:id="useTorForXmrOffRadio"/>
|
||||||
|
</HBox>
|
||||||
|
</VBox>
|
||||||
|
|
||||||
<VBox GridPane.rowIndex="2">
|
<VBox GridPane.rowIndex="2">
|
||||||
<AutoTooltipLabel fx:id="moneroNodesLabel" styleClass="small-text"/>
|
<AutoTooltipLabel fx:id="moneroNodesLabel" styleClass="small-text"/>
|
||||||
|
@ -49,7 +49,6 @@ import javafx.collections.transformation.SortedList;
|
|||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.VPos;
|
import javafx.geometry.VPos;
|
||||||
import javafx.scene.control.CheckBox;
|
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.RadioButton;
|
import javafx.scene.control.RadioButton;
|
||||||
import javafx.scene.control.TableColumn;
|
import javafx.scene.control.TableColumn;
|
||||||
@ -75,7 +74,7 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
|
|||||||
@FXML
|
@FXML
|
||||||
TitledGroupBg p2pHeader, btcHeader;
|
TitledGroupBg p2pHeader, btcHeader;
|
||||||
@FXML
|
@FXML
|
||||||
Label xmrNodesLabel, moneroNodesLabel, localhostXmrNodeInfoLabel;
|
Label useTorForXmrLabel, xmrNodesLabel, moneroNodesLabel, localhostXmrNodeInfoLabel;
|
||||||
@FXML
|
@FXML
|
||||||
InputTextField xmrNodesInputTextField;
|
InputTextField xmrNodesInputTextField;
|
||||||
@FXML
|
@FXML
|
||||||
@ -83,7 +82,7 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
|
|||||||
@FXML
|
@FXML
|
||||||
Label p2PPeersLabel, moneroPeersLabel;
|
Label p2PPeersLabel, moneroPeersLabel;
|
||||||
@FXML
|
@FXML
|
||||||
CheckBox useTorForXmrJCheckBox;
|
RadioButton useTorForXmrAfterSyncRadio, useTorForXmrOffRadio, useTorForXmrOnRadio;
|
||||||
@FXML
|
@FXML
|
||||||
RadioButton useProvidedNodesRadio, useCustomNodesRadio, usePublicNodesRadio;
|
RadioButton useProvidedNodesRadio, useCustomNodesRadio, usePublicNodesRadio;
|
||||||
@FXML
|
@FXML
|
||||||
@ -122,8 +121,11 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
|
|||||||
private Subscription moneroBlockHeightSubscription;
|
private Subscription moneroBlockHeightSubscription;
|
||||||
private Subscription nodeAddressSubscription;
|
private Subscription nodeAddressSubscription;
|
||||||
private ChangeListener<Boolean> xmrNodesInputTextFieldFocusListener;
|
private ChangeListener<Boolean> xmrNodesInputTextFieldFocusListener;
|
||||||
|
private ToggleGroup useTorForXmrToggleGroup;
|
||||||
private ToggleGroup moneroPeersToggleGroup;
|
private ToggleGroup moneroPeersToggleGroup;
|
||||||
|
private Preferences.UseTorForXmr selectedUseTorForXmr;
|
||||||
private XmrNodes.MoneroNodesOption selectedMoneroNodesOption;
|
private XmrNodes.MoneroNodesOption selectedMoneroNodesOption;
|
||||||
|
private ChangeListener<Toggle> useTorForXmrToggleGroupListener;
|
||||||
private ChangeListener<Toggle> moneroPeersToggleGroupListener;
|
private ChangeListener<Toggle> moneroPeersToggleGroupListener;
|
||||||
private ChangeListener<Filter> filterPropertyListener;
|
private ChangeListener<Filter> filterPropertyListener;
|
||||||
|
|
||||||
@ -156,7 +158,10 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
|
|||||||
onionAddress.setPromptText(Res.get("settings.net.onionAddressLabel"));
|
onionAddress.setPromptText(Res.get("settings.net.onionAddressLabel"));
|
||||||
xmrNodesLabel.setText(Res.get("settings.net.xmrNodesLabel"));
|
xmrNodesLabel.setText(Res.get("settings.net.xmrNodesLabel"));
|
||||||
moneroPeersLabel.setText(Res.get("settings.net.moneroPeersLabel"));
|
moneroPeersLabel.setText(Res.get("settings.net.moneroPeersLabel"));
|
||||||
useTorForXmrJCheckBox.setText(Res.get("settings.net.useTorForXmrJLabel"));
|
useTorForXmrLabel.setText(Res.get("settings.net.useTorForXmrJLabel"));
|
||||||
|
useTorForXmrAfterSyncRadio.setText(Res.get("settings.net.useTorForXmrAfterSyncRadio"));
|
||||||
|
useTorForXmrOffRadio.setText(Res.get("settings.net.useTorForXmrOffRadio"));
|
||||||
|
useTorForXmrOnRadio.setText(Res.get("settings.net.useTorForXmrOnRadio"));
|
||||||
moneroNodesLabel.setText(Res.get("settings.net.moneroNodesLabel"));
|
moneroNodesLabel.setText(Res.get("settings.net.moneroNodesLabel"));
|
||||||
moneroPeerAddressColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.onionAddressColumn")));
|
moneroPeerAddressColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.onionAddressColumn")));
|
||||||
moneroPeerAddressColumn.getStyleClass().add("first-column");
|
moneroPeerAddressColumn.getStyleClass().add("first-column");
|
||||||
@ -208,6 +213,31 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
|
|||||||
p2pPeersTableView.setPlaceholder(new AutoTooltipLabel(Res.get("table.placeholder.noData")));
|
p2pPeersTableView.setPlaceholder(new AutoTooltipLabel(Res.get("table.placeholder.noData")));
|
||||||
p2pPeersTableView.getSortOrder().add(creationDateColumn);
|
p2pPeersTableView.getSortOrder().add(creationDateColumn);
|
||||||
creationDateColumn.setSortType(TableColumn.SortType.ASCENDING);
|
creationDateColumn.setSortType(TableColumn.SortType.ASCENDING);
|
||||||
|
|
||||||
|
// use tor for xmr radio buttons
|
||||||
|
|
||||||
|
useTorForXmrToggleGroup = new ToggleGroup();
|
||||||
|
useTorForXmrAfterSyncRadio.setToggleGroup(useTorForXmrToggleGroup);
|
||||||
|
useTorForXmrOffRadio.setToggleGroup(useTorForXmrToggleGroup);
|
||||||
|
useTorForXmrOnRadio.setToggleGroup(useTorForXmrToggleGroup);
|
||||||
|
|
||||||
|
useTorForXmrAfterSyncRadio.setUserData(Preferences.UseTorForXmr.AFTER_SYNC);
|
||||||
|
useTorForXmrOffRadio.setUserData(Preferences.UseTorForXmr.OFF);
|
||||||
|
useTorForXmrOnRadio.setUserData(Preferences.UseTorForXmr.ON);
|
||||||
|
|
||||||
|
selectedUseTorForXmr = Preferences.UseTorForXmr.values()[preferences.getUseTorForXmrOrdinal()];
|
||||||
|
|
||||||
|
selectUseTorForXmrToggle();
|
||||||
|
onUseTorForXmrToggleSelected(false);
|
||||||
|
|
||||||
|
useTorForXmrToggleGroupListener = (observable, oldValue, newValue) -> {
|
||||||
|
if (newValue != null) {
|
||||||
|
selectedUseTorForXmr = (Preferences.UseTorForXmr) newValue.getUserData();
|
||||||
|
onUseTorForXmrToggleSelected(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// monero nodes radio buttons
|
||||||
|
|
||||||
moneroPeersToggleGroup = new ToggleGroup();
|
moneroPeersToggleGroup = new ToggleGroup();
|
||||||
useProvidedNodesRadio.setToggleGroup(moneroPeersToggleGroup);
|
useProvidedNodesRadio.setToggleGroup(moneroPeersToggleGroup);
|
||||||
@ -264,6 +294,7 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void activate() {
|
public void activate() {
|
||||||
|
useTorForXmrToggleGroup.selectedToggleProperty().addListener(useTorForXmrToggleGroupListener);
|
||||||
moneroPeersToggleGroup.selectedToggleProperty().addListener(moneroPeersToggleGroupListener);
|
moneroPeersToggleGroup.selectedToggleProperty().addListener(moneroPeersToggleGroupListener);
|
||||||
|
|
||||||
if (filterManager.getFilter() != null)
|
if (filterManager.getFilter() != null)
|
||||||
@ -271,22 +302,6 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
|
|||||||
|
|
||||||
filterManager.filterProperty().addListener(filterPropertyListener);
|
filterManager.filterProperty().addListener(filterPropertyListener);
|
||||||
|
|
||||||
useTorForXmrJCheckBox.setSelected(preferences.getUseTorForMonero());
|
|
||||||
useTorForXmrJCheckBox.setOnAction(event -> {
|
|
||||||
boolean selected = useTorForXmrJCheckBox.isSelected();
|
|
||||||
if (selected != preferences.getUseTorForMonero()) {
|
|
||||||
new Popup().information(Res.get("settings.net.needRestart"))
|
|
||||||
.actionButtonText(Res.get("shared.applyAndShutDown"))
|
|
||||||
.onAction(() -> {
|
|
||||||
preferences.setUseTorForMonero(selected);
|
|
||||||
UserThread.runAfter(HavenoApp.getShutDownHandler(), 500, TimeUnit.MILLISECONDS);
|
|
||||||
})
|
|
||||||
.closeButtonText(Res.get("shared.cancel"))
|
|
||||||
.onClose(() -> useTorForXmrJCheckBox.setSelected(!selected))
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
rescanOutputsButton.setOnAction(event -> GUIUtil.rescanOutputs(preferences));
|
rescanOutputsButton.setOnAction(event -> GUIUtil.rescanOutputs(preferences));
|
||||||
|
|
||||||
moneroPeersSubscription = EasyBind.subscribe(connectionManager.peerConnectionsProperty(),
|
moneroPeersSubscription = EasyBind.subscribe(connectionManager.peerConnectionsProperty(),
|
||||||
@ -328,11 +343,10 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deactivate() {
|
public void deactivate() {
|
||||||
|
useTorForXmrToggleGroup.selectedToggleProperty().removeListener(useTorForXmrToggleGroupListener);
|
||||||
moneroPeersToggleGroup.selectedToggleProperty().removeListener(moneroPeersToggleGroupListener);
|
moneroPeersToggleGroup.selectedToggleProperty().removeListener(moneroPeersToggleGroupListener);
|
||||||
filterManager.filterProperty().removeListener(filterPropertyListener);
|
filterManager.filterProperty().removeListener(filterPropertyListener);
|
||||||
|
|
||||||
useTorForXmrJCheckBox.setOnAction(null);
|
|
||||||
|
|
||||||
if (nodeAddressSubscription != null)
|
if (nodeAddressSubscription != null)
|
||||||
nodeAddressSubscription.unsubscribe();
|
nodeAddressSubscription.unsubscribe();
|
||||||
|
|
||||||
@ -360,6 +374,21 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
|
|||||||
return filterManager.getFilter() != null &&
|
return filterManager.getFilter() != null &&
|
||||||
filterManager.getFilter().isPreventPublicXmrNetwork();
|
filterManager.getFilter().isPreventPublicXmrNetwork();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void selectUseTorForXmrToggle() {
|
||||||
|
switch (selectedUseTorForXmr) {
|
||||||
|
case OFF:
|
||||||
|
useTorForXmrToggleGroup.selectToggle(useTorForXmrOffRadio);
|
||||||
|
break;
|
||||||
|
case ON:
|
||||||
|
useTorForXmrToggleGroup.selectToggle(useTorForXmrOnRadio);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case AFTER_SYNC:
|
||||||
|
useTorForXmrToggleGroup.selectToggle(useTorForXmrAfterSyncRadio);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void selectMoneroPeersToggle() {
|
private void selectMoneroPeersToggle() {
|
||||||
switch (selectedMoneroNodesOption) {
|
switch (selectedMoneroNodesOption) {
|
||||||
@ -383,10 +412,30 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
|
|||||||
.useShutDownButton()
|
.useShutDownButton()
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onUseTorForXmrToggleSelected(boolean calledFromUser) {
|
||||||
|
Preferences.UseTorForXmr currentUseTorForXmr = Preferences.UseTorForXmr.values()[preferences.getUseTorForXmrOrdinal()];
|
||||||
|
if (currentUseTorForXmr != selectedUseTorForXmr) {
|
||||||
|
if (calledFromUser) {
|
||||||
|
new Popup().information(Res.get("settings.net.needRestart"))
|
||||||
|
.actionButtonText(Res.get("shared.applyAndShutDown"))
|
||||||
|
.onAction(() -> {
|
||||||
|
preferences.setUseTorForXmrOrdinal(selectedUseTorForXmr.ordinal());
|
||||||
|
UserThread.runAfter(HavenoApp.getShutDownHandler(), 500, TimeUnit.MILLISECONDS);
|
||||||
|
})
|
||||||
|
.closeButtonText(Res.get("shared.cancel"))
|
||||||
|
.onClose(() -> {
|
||||||
|
selectedUseTorForXmr = currentUseTorForXmr;
|
||||||
|
selectUseTorForXmrToggle();
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onMoneroPeersToggleSelected(boolean calledFromUser) {
|
private void onMoneroPeersToggleSelected(boolean calledFromUser) {
|
||||||
boolean localMoneroNodeShouldBeUsed = localMoneroNode.shouldBeUsed();
|
boolean localMoneroNodeShouldBeUsed = localMoneroNode.shouldBeUsed();
|
||||||
useTorForXmrJCheckBox.setDisable(localMoneroNodeShouldBeUsed);
|
useTorForXmrLabel.setDisable(localMoneroNodeShouldBeUsed);
|
||||||
moneroNodesLabel.setDisable(localMoneroNodeShouldBeUsed);
|
moneroNodesLabel.setDisable(localMoneroNodeShouldBeUsed);
|
||||||
xmrNodesLabel.setDisable(localMoneroNodeShouldBeUsed);
|
xmrNodesLabel.setDisable(localMoneroNodeShouldBeUsed);
|
||||||
xmrNodesInputTextField.setDisable(localMoneroNodeShouldBeUsed);
|
xmrNodesInputTextField.setDisable(localMoneroNodeShouldBeUsed);
|
||||||
|
@ -1654,7 +1654,7 @@ message PreferencesPayload {
|
|||||||
bool auto_select_arbitrators = 8;
|
bool auto_select_arbitrators = 8;
|
||||||
map<string, bool> dont_show_again_map = 9;
|
map<string, bool> dont_show_again_map = 9;
|
||||||
bool tac_accepted = 10;
|
bool tac_accepted = 10;
|
||||||
bool use_tor_for_monero = 11;
|
int32 use_tor_for_xmr_ordinal = 11;
|
||||||
bool show_own_offers_in_offer_book = 12;
|
bool show_own_offers_in_offer_book = 12;
|
||||||
TradeCurrency preferred_trade_currency = 13;
|
TradeCurrency preferred_trade_currency = 13;
|
||||||
int64 withdrawal_tx_fee_in_vbytes = 14;
|
int64 withdrawal_tx_fee_in_vbytes = 14;
|
||||||
|
Loading…
Reference in New Issue
Block a user