mirror of
https://github.com/boldsuck/haveno.git
synced 2024-12-22 20:19:21 +00:00
app fully initialized before daemon connection or wallet by default
wallet initializes when first connected to get correct height connect to local node if available and last connection offline use only one internal daemon in monero node service
This commit is contained in:
parent
9dfbb0d5a6
commit
fdddc87477
6 changed files with 176 additions and 140 deletions
|
@ -243,7 +243,7 @@ public final class CoreMoneroConnectionsService {
|
|||
|
||||
/**
|
||||
* Signals that both the daemon and wallet have synced.
|
||||
*
|
||||
*
|
||||
* TODO: separate daemon and wallet download/done listeners
|
||||
*/
|
||||
public void doneDownload() {
|
||||
|
@ -268,15 +268,9 @@ public final class CoreMoneroConnectionsService {
|
|||
addConnection(connection);
|
||||
}
|
||||
|
||||
// restore last used connection
|
||||
var currentConnection = connectionList.getCurrentConnectionUri();
|
||||
currentConnection.ifPresentOrElse(connectionManager::setConnection, () -> {
|
||||
connectionManager.setConnection(DEFAULT_CONNECTIONS.get(0).getUri()); // default to localhost
|
||||
});
|
||||
|
||||
// initialize daemon
|
||||
daemon = new MoneroDaemonRpc(connectionManager.getConnection());
|
||||
updateDaemonInfo();
|
||||
// restore last used connection if present
|
||||
var currentConnectionUri = connectionList.getCurrentConnectionUri();
|
||||
if (currentConnectionUri.isPresent()) connectionManager.setConnection(currentConnectionUri.get());
|
||||
|
||||
// restore configuration
|
||||
connectionManager.setAutoSwitch(connectionList.getAutoSwitch());
|
||||
|
@ -288,11 +282,15 @@ public final class CoreMoneroConnectionsService {
|
|||
// run once
|
||||
if (!isInitialized) {
|
||||
|
||||
// initialize local monero node
|
||||
// register connection change listener
|
||||
connectionManager.addListener(this::onConnectionChanged);
|
||||
|
||||
// register local node listener
|
||||
nodeService.addListener(new MoneroNodeServiceListener() {
|
||||
@Override
|
||||
public void onNodeStarted(MoneroDaemonRpc daemon) {
|
||||
log.info(getClass() + ".onNodeStarted() called");
|
||||
daemon.getRpcConnection().checkConnection(connectionManager.getTimeout());
|
||||
setConnection(daemon.getRpcConnection());
|
||||
}
|
||||
|
||||
|
@ -303,10 +301,10 @@ public final class CoreMoneroConnectionsService {
|
|||
}
|
||||
});
|
||||
|
||||
// start local node if the last connection is local and not running
|
||||
currentConnection.ifPresent(connection -> {
|
||||
// start local node if last connection is local and offline
|
||||
currentConnectionUri.ifPresent(uri -> {
|
||||
try {
|
||||
if (nodeService.isMoneroNodeConnection(connection) && !nodeService.isMoneroNodeRunning()) {
|
||||
if (CoreMoneroNodeService.isLocalHost(uri) && !nodeService.isMoneroNodeRunning()) {
|
||||
nodeService.startMoneroNode();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -314,13 +312,22 @@ public final class CoreMoneroConnectionsService {
|
|||
}
|
||||
});
|
||||
|
||||
// register connection change listener
|
||||
connectionManager.addListener(this::onConnectionChanged);
|
||||
|
||||
// poll daemon periodically
|
||||
startPollingDaemon();
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
// if offline, connect to local node if available
|
||||
if (!connectionManager.isConnected() && nodeService.isMoneroNodeRunning()) {
|
||||
MoneroRpcConnection connection = connectionManager.getConnectionByUri(nodeService.getDaemon().getRpcConnection().getUri());
|
||||
if (connection == null) connection = nodeService.getDaemon().getRpcConnection();
|
||||
connection.checkConnection(connectionManager.getTimeout());
|
||||
setConnection(connection);
|
||||
}
|
||||
|
||||
// set the daemon based on the connection
|
||||
if (getConnection() != null) daemon = new MoneroDaemonRpc(connectionManager.getConnection());
|
||||
updateDaemonInfo();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,17 +36,17 @@ import java.util.List;
|
|||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import monero.common.MoneroRpcConnection;
|
||||
import monero.daemon.MoneroDaemonRpc;
|
||||
|
||||
/**
|
||||
* Manages a Monero node instance or connection to an instance.
|
||||
* Start and stop or connect to a local Monero node.
|
||||
*/
|
||||
@Slf4j
|
||||
@Singleton
|
||||
public class CoreMoneroNodeService {
|
||||
|
||||
public static final String LOCAL_NODE_ADDRESS = "127.0.0.1"; // expected connection from local MoneroDaemonRpc
|
||||
private static final String LOOPBACK_HOST = "127.0.0.1"; // local loopback address to host Monero node
|
||||
private static final String LOCALHOST = "localhost";
|
||||
private static final String MONERO_NETWORK_TYPE = Config.baseCurrencyNetwork().getNetwork().toLowerCase();
|
||||
private static final String MONEROD_PATH = System.getProperty("user.dir") + File.separator + ".localnet" + File.separator + "monerod";
|
||||
private static final String MONEROD_DATADIR = System.getProperty("user.dir") + File.separator + ".localnet" + File.separator + MONERO_NETWORK_TYPE;
|
||||
|
@ -63,15 +63,11 @@ public class CoreMoneroNodeService {
|
|||
"--rpc-login", "superuser:abctesting123" // TODO: remove authentication
|
||||
);
|
||||
|
||||
// local monero node owned by this process
|
||||
// client to the local Monero node
|
||||
private MoneroDaemonRpc daemon;
|
||||
|
||||
// local monero node for detecting running node not owned by this process
|
||||
private MoneroDaemonRpc defaultMoneroDaemon;
|
||||
|
||||
@Inject
|
||||
public CoreMoneroNodeService(Preferences preferences) {
|
||||
this.daemon = null;
|
||||
this.preferences = preferences;
|
||||
int rpcPort = 18081; // mainnet
|
||||
if (Config.baseCurrencyNetwork().isTestnet()) {
|
||||
|
@ -79,9 +75,15 @@ public class CoreMoneroNodeService {
|
|||
} else if (Config.baseCurrencyNetwork().isStagenet()) {
|
||||
rpcPort = 38081;
|
||||
}
|
||||
// TODO: remove authentication
|
||||
var defaultMoneroConnection = new MoneroRpcConnection("http://" + LOCAL_NODE_ADDRESS + ":" + rpcPort, "superuser", "abctesting123").setPriority(1); // localhost is first priority
|
||||
defaultMoneroDaemon = new MoneroDaemonRpc(defaultMoneroConnection);
|
||||
this.daemon = new MoneroDaemonRpc("http://" + LOOPBACK_HOST + ":" + rpcPort, "superuser", "abctesting123"); // TODO: remove authentication
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given URI is on local host. // TODO: move to utils
|
||||
*/
|
||||
public static boolean isLocalHost(String uri) throws URISyntaxException {
|
||||
String host = new URI(uri).getHost();
|
||||
return host.equals(CoreMoneroNodeService.LOOPBACK_HOST) || host.equals(CoreMoneroNodeService.LOCALHOST);
|
||||
}
|
||||
|
||||
public void addListener(MoneroNodeServiceListener listener) {
|
||||
|
@ -93,18 +95,17 @@ public class CoreMoneroNodeService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns whether a connection string URI is a local monero node.
|
||||
* Returns the client of the local monero node.
|
||||
*/
|
||||
public boolean isMoneroNodeConnection(String connection) throws URISyntaxException {
|
||||
var uri = new URI(connection);
|
||||
return CoreMoneroNodeService.LOCAL_NODE_ADDRESS.equals(uri.getHost());
|
||||
public MoneroDaemonRpc getDaemon() {
|
||||
return daemon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the local monero node is running or local daemon connection is running
|
||||
* Returns whether a local monero node is running.
|
||||
*/
|
||||
public boolean isMoneroNodeRunning() {
|
||||
return daemon != null || defaultMoneroDaemon.isConnected();
|
||||
return daemon.isConnected();
|
||||
}
|
||||
|
||||
public MoneroNodeSettings getMoneroNodeSettings() {
|
||||
|
@ -124,7 +125,7 @@ public class CoreMoneroNodeService {
|
|||
* Persists the settings to preferences if the node started successfully.
|
||||
*/
|
||||
public void startMoneroNode(MoneroNodeSettings settings) throws IOException {
|
||||
if (isMoneroNodeRunning()) throw new IllegalStateException("Monero node already running");
|
||||
if (isMoneroNodeRunning()) throw new IllegalStateException("Local Monero node already running");
|
||||
|
||||
log.info("Starting local Monero node: " + settings);
|
||||
|
||||
|
@ -146,23 +147,19 @@ public class CoreMoneroNodeService {
|
|||
args.addAll(flags);
|
||||
}
|
||||
|
||||
daemon = new MoneroDaemonRpc(args);
|
||||
daemon = new MoneroDaemonRpc(args); // start daemon as process and re-assign client
|
||||
preferences.setMoneroNodeSettings(settings);
|
||||
for (var listener : listeners) listener.onNodeStarted(daemon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the current local monero node if owned by this process.
|
||||
* Stops the current local monero node if we own its process.
|
||||
* Does not remove the last MoneroNodeSettings.
|
||||
*/
|
||||
public void stopMoneroNode() {
|
||||
if (!isMoneroNodeRunning()) throw new IllegalStateException("Monero node is not running");
|
||||
if (daemon != null) {
|
||||
daemon.stopProcess();
|
||||
daemon = null;
|
||||
for (var listener : listeners) listener.onNodeStopped();
|
||||
} else {
|
||||
defaultMoneroDaemon.stopProcess(); // throws MoneroError
|
||||
}
|
||||
if (!isMoneroNodeRunning()) throw new IllegalStateException("Local Monero node is not running");
|
||||
if (daemon.getProcess() == null || !daemon.getProcess().isAlive()) throw new IllegalStateException("Cannot stop local Monero node because we don't own its process"); // TODO (woodser): remove isAlive() check after monero-java 0.5.4 which nullifies internal process
|
||||
daemon.stopProcess();
|
||||
for (var listener : listeners) listener.onNodeStopped();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ public class AppStartupState {
|
|||
if (a && b && c) {
|
||||
walletAndNetworkReady.set(true);
|
||||
}
|
||||
return a && b && c && d;
|
||||
return a && d; // app fully initialized before daemon connection and wallet by default
|
||||
});
|
||||
p2pNetworkAndWalletInitialized.subscribe((observable, oldValue, newValue) -> {
|
||||
if (newValue) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package bisq.core.app;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.core.api.CoreMoneroConnectionsService;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.provider.price.PriceFeedService;
|
||||
|
@ -109,7 +110,7 @@ public class P2PNetworkSetup {
|
|||
return result;
|
||||
});
|
||||
p2PNetworkInfoBinding.subscribe((observable, oldValue, newValue) -> {
|
||||
p2PNetworkInfo.set(newValue);
|
||||
UserThread.execute(() -> p2PNetworkInfo.set(newValue));
|
||||
});
|
||||
|
||||
bootstrapState.set(Res.get("mainView.bootstrapState.connectionToTorNetwork"));
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package bisq.core.btc;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.core.btc.listeners.XmrBalanceListener;
|
||||
import bisq.core.btc.wallet.XmrWalletService;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
import bisq.core.offer.OpenOffer;
|
||||
|
@ -41,7 +42,6 @@ import lombok.Getter;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
import monero.wallet.model.MoneroOutputQuery;
|
||||
import monero.wallet.model.MoneroOutputWallet;
|
||||
import monero.wallet.model.MoneroWalletListener;
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
@Slf4j
|
||||
|
@ -80,18 +80,19 @@ public class Balances {
|
|||
}
|
||||
|
||||
public void onAllServicesInitialized() {
|
||||
openOfferManager.getObservableList().addListener((ListChangeListener<OpenOffer>) c -> updateBalance());
|
||||
tradeManager.getObservableList().addListener((ListChangeListener<Trade>) change -> updateBalance());
|
||||
refundManager.getDisputesAsObservableList().addListener((ListChangeListener<Dispute>) c -> updateBalance());
|
||||
xmrWalletService.getWallet().addListener(new MoneroWalletListener() {
|
||||
@Override public void onBalancesChanged(BigInteger newBalance, BigInteger newUnlockedBalance) { updateBalance(); }
|
||||
@Override public void onOutputReceived(MoneroOutputWallet output) { updateBalance(); }
|
||||
@Override public void onOutputSpent(MoneroOutputWallet output) { updateBalance(); }
|
||||
openOfferManager.getObservableList().addListener((ListChangeListener<OpenOffer>) c -> updatedBalances());
|
||||
tradeManager.getObservableList().addListener((ListChangeListener<Trade>) change -> updatedBalances());
|
||||
refundManager.getDisputesAsObservableList().addListener((ListChangeListener<Dispute>) c -> updatedBalances());
|
||||
xmrWalletService.addBalanceListener(new XmrBalanceListener() {
|
||||
@Override
|
||||
public void onBalanceChanged(BigInteger balance) {
|
||||
updatedBalances();
|
||||
}
|
||||
});
|
||||
updateBalance();
|
||||
updatedBalances();
|
||||
}
|
||||
|
||||
private void updateBalance() {
|
||||
private void updatedBalances() {
|
||||
// Need to delay a bit to get the balances correct
|
||||
UserThread.execute(() -> {
|
||||
updateAvailableBalance();
|
||||
|
@ -105,19 +106,21 @@ public class Balances {
|
|||
// TODO (woodser): balances being set as Coin from BigInteger.longValue(), which can lose precision. should be in centineros for consistency with the rest of the application
|
||||
|
||||
private void updateAvailableBalance() {
|
||||
availableBalance.set(Coin.valueOf(xmrWalletService.getWallet().getUnlockedBalance(0).longValueExact()));
|
||||
availableBalance.set(Coin.valueOf(xmrWalletService.getWallet() == null ? 0 : xmrWalletService.getWallet().getUnlockedBalance(0).longValueExact()));
|
||||
}
|
||||
|
||||
private void updateLockedBalance() {
|
||||
BigInteger balance = xmrWalletService.getWallet().getBalance(0);
|
||||
BigInteger unlockedBalance = xmrWalletService.getWallet().getUnlockedBalance(0);
|
||||
BigInteger balance = xmrWalletService.getWallet() == null ? new BigInteger("0") : xmrWalletService.getWallet().getBalance(0);
|
||||
BigInteger unlockedBalance = xmrWalletService.getWallet() == null ? new BigInteger("0") : xmrWalletService.getWallet().getUnlockedBalance(0);
|
||||
lockedBalance.set(Coin.valueOf(balance.subtract(unlockedBalance).longValueExact()));
|
||||
}
|
||||
|
||||
private void updateReservedOfferBalance() {
|
||||
Coin sum = Coin.valueOf(0);
|
||||
List<MoneroOutputWallet> frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false));
|
||||
for (MoneroOutputWallet frozenOutput : frozenOutputs) sum = sum.add(Coin.valueOf(frozenOutput.getAmount().longValueExact()));
|
||||
if (xmrWalletService.getWallet() != null) {
|
||||
List<MoneroOutputWallet> frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false));
|
||||
for (MoneroOutputWallet frozenOutput : frozenOutputs) sum = sum.add(Coin.valueOf(frozenOutput.getAmount().longValueExact()));
|
||||
}
|
||||
reservedOfferBalance.set(sum);
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class XmrWalletService {
|
|||
protected final CopyOnWriteArraySet<MoneroWalletListenerI> walletListeners = new CopyOnWriteArraySet<>();
|
||||
|
||||
private TradeManager tradeManager;
|
||||
private MoneroWallet wallet;
|
||||
private MoneroWalletRpc wallet;
|
||||
private Map<String, MoneroWallet> multisigWallets;
|
||||
|
||||
@Inject
|
||||
|
@ -159,64 +159,6 @@ public class XmrWalletService {
|
|||
return new File(path + ".keys").exists();
|
||||
}
|
||||
|
||||
public MoneroWalletRpc createWallet(MoneroWalletConfig config, Integer port) {
|
||||
|
||||
// start monero-wallet-rpc instance
|
||||
MoneroWalletRpc walletRpc = startWalletRpcInstance(port);
|
||||
|
||||
// create wallet
|
||||
try {
|
||||
walletRpc.createWallet(config);
|
||||
walletRpc.startSyncing(MONERO_WALLET_SYNC_RATE);
|
||||
return walletRpc;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
MONERO_WALLET_RPC_MANAGER.stopInstance(walletRpc, false);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public MoneroWalletRpc openWallet(MoneroWalletConfig config, Integer port) {
|
||||
|
||||
// start monero-wallet-rpc instance
|
||||
MoneroWalletRpc walletRpc = startWalletRpcInstance(port);
|
||||
|
||||
// open wallet
|
||||
try {
|
||||
walletRpc.openWallet(config);
|
||||
walletRpc.startSyncing(MONERO_WALLET_SYNC_RATE);
|
||||
return walletRpc;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
MONERO_WALLET_RPC_MANAGER.stopInstance(walletRpc, false);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private MoneroWalletRpc startWalletRpcInstance(Integer port) {
|
||||
|
||||
// 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
|
||||
+ "; copy monero-wallet-rpc to the project root or set WalletConfig.java MONERO_WALLET_RPC_PATH for your system");
|
||||
|
||||
// get app's current daemon connection
|
||||
MoneroRpcConnection connection = connectionsService.getConnection();
|
||||
|
||||
// start monero-wallet-rpc instance and return connected client
|
||||
List<String> cmd = new ArrayList<>(Arrays.asList( // modifiable list
|
||||
MONERO_WALLET_RPC_PATH, "--" + MONERO_NETWORK_TYPE.toString().toLowerCase(), "--daemon-address", connection.getUri(), "--rpc-login",
|
||||
MONERO_WALLET_RPC_USERNAME + ":" + getWalletPassword(), "--wallet-dir", walletDir.toString()));
|
||||
if (connection.getUsername() != null) {
|
||||
cmd.add("--daemon-login");
|
||||
cmd.add(connection.getUsername() + ":" + connection.getPassword());
|
||||
}
|
||||
if (port != null && port > 0) {
|
||||
cmd.add("--rpc-bind-port");
|
||||
cmd.add(Integer.toString(port));
|
||||
}
|
||||
return MONERO_WALLET_RPC_MANAGER.startInstance(cmd);
|
||||
}
|
||||
|
||||
public void closeWallet(MoneroWallet walletRpc, boolean save) {
|
||||
log.info("{}.closeWallet({}, {})", getClass(), walletRpc.getPath(), save);
|
||||
MONERO_WALLET_RPC_MANAGER.stopInstance((MoneroWalletRpc) walletRpc, save);
|
||||
|
@ -290,30 +232,114 @@ public class XmrWalletService {
|
|||
// backup wallet files
|
||||
backupWallets();
|
||||
|
||||
// initialize main wallet
|
||||
MoneroWalletConfig walletConfig = new MoneroWalletConfig().setPath(MONERO_WALLET_NAME).setPassword(getWalletPassword());
|
||||
wallet = MoneroUtils.walletExists(xmrWalletFile.getPath()) ? openWallet(walletConfig, rpcBindPort) : createWallet(walletConfig, rpcBindPort);
|
||||
System.out.println("Monero wallet path: " + wallet.getPath());
|
||||
System.out.println("Monero wallet address: " + wallet.getPrimaryAddress());
|
||||
System.out.println("Monero wallet uri: " + ((MoneroWalletRpc) wallet).getRpcConnection().getUri());
|
||||
wallet.sync(); // blocking
|
||||
connectionsService.doneDownload(); // TODO: using this to signify both daemon and wallet synced, refactor sync handling of both
|
||||
wallet.save();
|
||||
System.out.println("Loaded wallet balance: " + wallet.getBalance(0));
|
||||
System.out.println("Loaded wallet unlocked balance: " + wallet.getUnlockedBalance(0));
|
||||
|
||||
// initialize main wallet if connected or previously created
|
||||
tryInitMainWallet();
|
||||
|
||||
// update wallet connections on change
|
||||
connectionsService.addListener(newConnection -> {
|
||||
setWalletDaemonConnections(newConnection);
|
||||
});
|
||||
}
|
||||
|
||||
// notify on balance changes
|
||||
wallet.addListener(new MoneroWalletListener() {
|
||||
@Override
|
||||
public void onBalancesChanged(BigInteger newBalance, BigInteger newUnlockedBalance) {
|
||||
notifyBalanceListeners();
|
||||
private void tryInitMainWallet() {
|
||||
MoneroWalletConfig walletConfig = new MoneroWalletConfig().setPath(MONERO_WALLET_NAME).setPassword(getWalletPassword());
|
||||
if (MoneroUtils.walletExists(xmrWalletFile.getPath())) {
|
||||
wallet = openWallet(walletConfig, rpcBindPort);
|
||||
} else if (connectionsService.getConnection() != null && Boolean.TRUE.equals(connectionsService.getConnection().isConnected())) {
|
||||
wallet = createWallet(walletConfig, rpcBindPort); // wallet requires connection to daemon to correctly set height
|
||||
}
|
||||
|
||||
// wallet is not initialized until connected to a daemon
|
||||
if (wallet != null) {
|
||||
try {
|
||||
wallet.sync(); // blocking
|
||||
connectionsService.doneDownload(); // TODO: using this to signify both daemon and wallet synced, refactor sync handling of both
|
||||
wallet.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
System.out.println("Monero wallet path: " + wallet.getPath());
|
||||
System.out.println("Monero wallet address: " + wallet.getPrimaryAddress());
|
||||
System.out.println("Monero wallet uri: " + wallet.getRpcConnection().getUri());
|
||||
System.out.println("Monero wallet height: " + wallet.getHeight());
|
||||
System.out.println("Monero wallet balance: " + wallet.getBalance(0));
|
||||
System.out.println("Monero wallet unlocked balance: " + wallet.getUnlockedBalance(0));
|
||||
|
||||
// notify on balance changes
|
||||
wallet.addListener(new MoneroWalletListener() {
|
||||
@Override
|
||||
public void onBalancesChanged(BigInteger newBalance, BigInteger newUnlockedBalance) {
|
||||
notifyBalanceListeners();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private MoneroWalletRpc createWallet(MoneroWalletConfig config, Integer port) {
|
||||
|
||||
// start monero-wallet-rpc instance
|
||||
MoneroWalletRpc walletRpc = startWalletRpcInstance(port);
|
||||
|
||||
// must be connected to daemon
|
||||
MoneroRpcConnection connection = connectionsService.getConnection();
|
||||
if (connection == null || !Boolean.TRUE.equals(connection.isConnected())) throw new RuntimeException("Must be connected to daemon before creating wallet");
|
||||
|
||||
// create wallet
|
||||
try {
|
||||
walletRpc.createWallet(config);
|
||||
walletRpc.startSyncing(MONERO_WALLET_SYNC_RATE);
|
||||
return walletRpc;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
MONERO_WALLET_RPC_MANAGER.stopInstance(walletRpc, false);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private MoneroWalletRpc openWallet(MoneroWalletConfig config, Integer port) {
|
||||
|
||||
// start monero-wallet-rpc instance
|
||||
MoneroWalletRpc walletRpc = startWalletRpcInstance(port);
|
||||
|
||||
// open wallet
|
||||
try {
|
||||
walletRpc.openWallet(config);
|
||||
walletRpc.startSyncing(MONERO_WALLET_SYNC_RATE);
|
||||
return walletRpc;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
MONERO_WALLET_RPC_MANAGER.stopInstance(walletRpc, false);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private MoneroWalletRpc startWalletRpcInstance(Integer port) {
|
||||
|
||||
// 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
|
||||
+ "; copy monero-wallet-rpc to the project root or set WalletConfig.java MONERO_WALLET_RPC_PATH for your system");
|
||||
|
||||
// build command to start monero-wallet-rpc
|
||||
List<String> cmd = new ArrayList<>(Arrays.asList( // modifiable list
|
||||
MONERO_WALLET_RPC_PATH, "--" + MONERO_NETWORK_TYPE.toString().toLowerCase(), "--rpc-login",
|
||||
MONERO_WALLET_RPC_USERNAME + ":" + getWalletPassword(), "--wallet-dir", walletDir.toString()));
|
||||
MoneroRpcConnection connection = connectionsService.getConnection();
|
||||
if (connection != null) {
|
||||
cmd.add("--daemon-address");
|
||||
cmd.add(connection.getUri());
|
||||
if (connection.getUsername() != null) {
|
||||
cmd.add("--daemon-login");
|
||||
cmd.add(connection.getUsername() + ":" + connection.getPassword());
|
||||
}
|
||||
}
|
||||
if (port != null && port > 0) {
|
||||
cmd.add("--rpc-bind-port");
|
||||
cmd.add(Integer.toString(port));
|
||||
}
|
||||
|
||||
// start monero-wallet-rpc instance and return connected client
|
||||
return MONERO_WALLET_RPC_MANAGER.startInstance(cmd);
|
||||
}
|
||||
|
||||
private void backupWallets() {
|
||||
|
@ -324,6 +350,7 @@ public class XmrWalletService {
|
|||
|
||||
private void setWalletDaemonConnections(MoneroRpcConnection connection) {
|
||||
log.info("Setting wallet daemon connections: " + (connection == null ? null : connection.getUri()));
|
||||
if (wallet == null) tryInitMainWallet();
|
||||
if (wallet != null) wallet.setDaemonConnection(connection);
|
||||
for (MoneroWallet multisigWallet : multisigWallets.values()) multisigWallet.setDaemonConnection(connection);
|
||||
}
|
||||
|
@ -333,7 +360,7 @@ public class XmrWalletService {
|
|||
Coin balance;
|
||||
if (balanceListener.getSubaddressIndex() != null && balanceListener.getSubaddressIndex() != 0) balance = getBalanceForSubaddress(balanceListener.getSubaddressIndex());
|
||||
else balance = getAvailableConfirmedBalance();
|
||||
UserThread.execute(new Runnable() {
|
||||
UserThread.execute(new Runnable() { // TODO (woodser): don't execute on UserThread
|
||||
@Override
|
||||
public void run() {
|
||||
balanceListener.onBalanceChanged(BigInteger.valueOf(balance.value));
|
||||
|
@ -549,6 +576,7 @@ public class XmrWalletService {
|
|||
return available.filter(addressEntry -> getBalanceForSubaddress(addressEntry.getSubaddressIndex()).isPositive());
|
||||
}
|
||||
|
||||
// TODO (woodser): update balance and other listening
|
||||
public void addBalanceListener(XmrBalanceListener listener) {
|
||||
balanceListeners.add(listener);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue