Support opening wallet
MODIFY
WalletWasabi.Gui/Global.cs
WalletWasabi.Gui/Global.cs
@@ -58,7 +58,6 @@ namespace WalletWasabi.Gui
public WasabiSynchronizer Synchronizer { get; private set; }
public FeeProviders FeeProviders { get; private set; }
public WalletManager WalletManager { get; }
- public Wallet Wallet => WalletManager?.GetFirstOrDefaultWallet();
public TransactionBroadcaster TransactionBroadcaster { get; set; }
public CoinJoinProcessor CoinJoinProcessor { get; set; }
public Node RegTestMempoolServingNode { get; private set; }

MODIFY
WalletWasabi.Gui/Rpc/WasabiJsonRpcService.cs
WalletWasabi.Gui/Rpc/WasabiJsonRpcService.cs
using System;
+using System.Collections.Generic;
using System.Linq;
-using System.Threading;
using System.Threading.Tasks;
using NBitcoin;
using WalletWasabi.Blockchain.Analysis.Clustering;
@@ -11,23 +11,32 @@ using WalletWasabi.Blockchain.Transactions;
using WalletWasabi.CoinJoin.Client.Clients.Queuing;
using WalletWasabi.Helpers;
using WalletWasabi.Models;
+using WalletWasabi.Wallets;
namespace WalletWasabi.Gui.Rpc
{
public partial class WasabiJsonRpcService
{
private Global Global { get; }
+ private Wallet ActiveWallet { get; set; }
+ private Dictionary<string, Wallet> WalletsCache { get; } = new Dictionary<string, Wallet>();
+
public WasabiJsonRpcService(Global global)
{
Global = global;
+ ActiveWallet = Global.WalletManager?.GetFirstOrDefaultWallet();
+ if (ActiveWallet is {})
+ {
+ WalletsCache.Add(ActiveWallet.WalletName, ActiveWallet);
+ }
}
[JsonRpcMethod("listunspentcoins")]
public object[] GetUnspentCoinList()
{
AssertWalletIsLoaded();
- return Global.Wallet.Coins.Where(x => x.Unspent).Select(x => new
+ return ActiveWallet.Coins.Where(x => x.Unspent).Select(x => new
{
txid = x.TransactionId.ToString(),
index = x.Index,
@@ -54,15 +63,16 @@ namespace WalletWasabi.Gui.Rpc
public object WalletInfo()
{
AssertWalletIsLoaded();
- var km = Global.Wallet.KeyManager;
+ var km = ActiveWallet.KeyManager;
return new
{
- walletFile = Global.Wallet.KeyManager.FilePath,
+ walletName = ActiveWallet.WalletName,
+ walletFile = km.FilePath,
extendedAccountPublicKey = km.ExtPubKey.ToString(Global.Network),
extendedAccountZpub = km.ExtPubKey.ToZpub(Global.Network),
accountKeyPath = $"m/{km.AccountKeyPath.ToString()}",
masterKeyFingerprint = km.MasterFingerprint?.ToString() ?? "",
- balance = Global.Wallet.Coins
+ balance = ActiveWallet.Coins
.Where(c => c.Unspent && !c.SpentAccordingToBackend)
.Sum(c => c.Amount.Satoshi)
};
@@ -74,7 +84,7 @@ namespace WalletWasabi.Gui.Rpc
AssertWalletIsLoaded();
label = Guard.NotNullOrEmptyOrWhitespace(nameof(label), label, true);
- var hdkey = Global.Wallet.KeyManager
+ var hdkey = ActiveWallet.KeyManager
.GenerateNewKey(new SmartLabel(label), KeyState.Clean, isInternal: false);
return new
{
@@ -93,7 +103,12 @@ namespace WalletWasabi.Gui.Rpc
return new
{
- torStatus = sync.TorStatus == TorStatus.NotRunning ? "Not running" : (sync.TorStatus == TorStatus.Running ? "Running" : "Turned off"),
+ torStatus = sync.TorStatus switch
+ {
+ TorStatus.NotRunning => "Not running",
+ TorStatus.Running => "Running",
+ _ => "Turned off"
+ },
backendStatus = sync.BackendStatus == BackendStatus.Connected ? "Connected" : "Disconnected",
bestBlockchainHeight = sync.BitcoinStore.SmartHeaderChain.TipHeight.ToString(),
bestBlockchainHash = sync.BitcoinStore.SmartHeaderChain.TipHash.ToString(),
@@ -124,7 +139,7 @@ namespace WalletWasabi.Gui.Rpc
var payment = new PaymentIntent(payments.Select(p =>
new DestinationRequest(p.Sendto.ScriptPubKey, MoneyRequest.Create(p.Amount, p.SubtractFee), new SmartLabel(p.Label))));
var feeStrategy = FeeStrategy.CreateFromConfirmationTarget(feeTarget);
- var result = Global.Wallet.BuildTransaction(
+ var result = ActiveWallet.BuildTransaction(
password,
payment,
feeStrategy,
@@ -142,12 +157,12 @@ namespace WalletWasabi.Gui.Rpc
var smartTx = new SmartTransaction(Transaction.Parse(txHex, Global.Network), Height.Mempool);
// dequeue the coins we are going to spend
- var toDequeue = Global.Wallet.Coins
+ var toDequeue = ActiveWallet.Coins
.Where(x => x.CoinJoinInProgress && coins.Contains(x.GetTxoRef()))
.ToArray();
if (toDequeue.Any())
{
- await Global.Wallet.ChaumianClient.DequeueCoinsFromMixAsync(toDequeue, DequeueReason.TransactionBuilding).ConfigureAwait(false);
+ await ActiveWallet.ChaumianClient.DequeueCoinsFromMixAsync(toDequeue, DequeueReason.TransactionBuilding).ConfigureAwait(false);
}
await Global.TransactionBroadcaster.SendTransactionAsync(smartTx).ConfigureAwait(false);
@@ -162,7 +177,7 @@ namespace WalletWasabi.Gui.Rpc
public object[] GetHistory()
{
AssertWalletIsLoaded();
- var txHistoryBuilder = new TransactionHistoryBuilder(Global.Wallet);
+ var txHistoryBuilder = new TransactionHistoryBuilder(ActiveWallet);
var summary = txHistoryBuilder.BuildHistorySummary();
return summary.Select(x => new
{
@@ -178,7 +193,7 @@ namespace WalletWasabi.Gui.Rpc
public object[] GetAllKeys()
{
AssertWalletIsLoaded();
- var keys = Global.Wallet.KeyManager.GetKeys(null);
+ var keys = ActiveWallet.KeyManager.GetKeys(null);
return keys.Select(x => new
{
fullKeyPath = x.FullKeyPath.ToString(),
@@ -197,8 +212,8 @@ namespace WalletWasabi.Gui.Rpc
Guard.NotNull(nameof(coins), coins);
AssertWalletIsLoaded();
- var coinsToMix = Global.Wallet.Coins.Where(x => coins.Any(y => y.TransactionId == x.TransactionId && y.Index == x.Index));
- await Global.Wallet.ChaumianClient.QueueCoinsToMixAsync(coinsToMix.ToArray()).ConfigureAwait(false);
+ var coinsToMix = ActiveWallet.Coins.Where(x => coins.Any(y => y.TransactionId == x.TransactionId && y.Index == x.Index));
+ await ActiveWallet.ChaumianClient.QueueCoinsToMixAsync(coinsToMix.ToArray()).ConfigureAwait(false);
}
[JsonRpcMethod("dequeue")]
@@ -207,8 +222,24 @@ namespace WalletWasabi.Gui.Rpc
Guard.NotNull(nameof(coins), coins);
AssertWalletIsLoaded();
- var coinsToDequeue = Global.Wallet.Coins.Where(x => coins.Any(y => y.TransactionId == x.TransactionId && y.Index == x.Index));
- await Global.Wallet.ChaumianClient.DequeueCoinsFromMixAsync(coinsToDequeue, DequeueReason.UserRequested).ConfigureAwait(false);
+ var coinsToDequeue = ActiveWallet.Coins.Where(x => coins.Any(y => y.TransactionId == x.TransactionId && y.Index == x.Index));
+ await ActiveWallet.ChaumianClient.DequeueCoinsFromMixAsync(coinsToDequeue, DequeueReason.UserRequested).ConfigureAwait(false);
+ }
+
+ [JsonRpcMethod("selectwallet")]
+ public async Task SelectWalletAsync(string walletName)
+ {
+ walletName = Guard.NotNullOrEmptyOrWhitespace(nameof(walletName), walletName);
+ if (WalletsCache.TryGetValue(walletName, out var wallet))
+ {
+ ActiveWallet = wallet;
+ }
+ else
+ {
+ var km = Global.LoadKeyManager(walletName);
+ ActiveWallet = await Global.WalletManager.CreateAndStartWalletAsync(km);
+ WalletsCache.Add(walletName, ActiveWallet);
+ }
}
[JsonRpcMethod("stop")]
@@ -219,7 +250,7 @@ namespace WalletWasabi.Gui.Rpc
private void AssertWalletIsLoaded()
{
- if (Global.Wallet is null)
+ if (ActiveWallet is null || ActiveWallet.State != WalletState.Started)
{
throw new InvalidOperationException("There is no wallet loaded.");
}

Support opening wallet