WasabiClient is not disposable anymore.
MODIFY
WalletWasabi.Gui/ViewModels/StatusBarViewModel.cs
WalletWasabi.Gui/ViewModels/StatusBarViewModel.cs
@@ -362,7 +362,7 @@ namespace WalletWasabi.Gui.ViewModels
{
if (LegalDocuments is null || LegalDocuments.Version < x.LegalDocumentsVersion)
{
- using WasabiClient client = Synchronizer.WasabiClientFactory.NewBackendClient();
+ WasabiClient client = Synchronizer.WasabiClientFactory.SharedWasabiClient;
var versions = await client.GetVersionsAsync(CancellationToken.None);
var version = versions.LegalDocumentsVersion;
var legalFolderPath = Path.Combine(DataDir, LegalDocuments.LegalFolderName);

MODIFY
WalletWasabi.Tests/IntegrationTests/LiveServerTests.cs
WalletWasabi.Tests/IntegrationTests/LiveServerTests.cs
@@ -48,7 +48,7 @@ namespace WalletWasabi.Tests.IntegrationTests
Network network = (networkType == NetworkType.Mainnet) ? Network.Main : Network.TestNet;
using var torHttpClient = MakeTorHttpClient(networkType);
- using var client = new WasabiClient(torHttpClient);
+ var client = new WasabiClient(torHttpClient);
var filterModel = StartingFilters.GetStartingFilter(network);
@@ -75,7 +75,7 @@ namespace WalletWasabi.Tests.IntegrationTests
public async Task GetTransactionsAsync(NetworkType networkType)
{
using var torHttpClient = MakeTorHttpClient(networkType);
- using var client = new WasabiClient(torHttpClient);
+ var client = new WasabiClient(torHttpClient);
var randomTxIds = Enumerable.Range(0, 20).Select(_ => RandomUtils.GetUInt256());
var network = networkType == NetworkType.Mainnet ? Network.Main : Network.TestNet;
@@ -101,7 +101,7 @@ namespace WalletWasabi.Tests.IntegrationTests
public async Task GetExchangeRateAsync(NetworkType networkType) // xunit wtf: If this function is called GetExchangeRatesAsync, it'll stuck on 1 CPU VMs (Manjuro, Fedora)
{
using var torHttpClient = MakeTorHttpClient(networkType);
- using var client = new WasabiClient(torHttpClient);
+ var client = new WasabiClient(torHttpClient);
var exchangeRates = await client.GetExchangeRatesAsync();
@@ -118,7 +118,7 @@ namespace WalletWasabi.Tests.IntegrationTests
public async Task GetVersionsTestsAsync(NetworkType networkType)
{
using var torHttpClient = MakeTorHttpClient(networkType);
- using var client = new WasabiClient(torHttpClient);
+ var client = new WasabiClient(torHttpClient);
var versions = await client.GetVersionsAsync(CancellationToken.None);
Assert.InRange(versions.ClientVersion, new Version(1, 1, 10), new Version(1, 2));
@@ -133,7 +133,7 @@ namespace WalletWasabi.Tests.IntegrationTests
public async Task CheckUpdatesTestsAsync(NetworkType networkType)
{
using var torHttpClient = MakeTorHttpClient(networkType);
- using var client = new WasabiClient(torHttpClient);
+ var client = new WasabiClient(torHttpClient);
var updateStatus = await client.CheckUpdatesAsync(CancellationToken.None);
@@ -159,7 +159,7 @@ namespace WalletWasabi.Tests.IntegrationTests
public async Task GetLegalDocumentsTestsAsync(NetworkType networkType)
{
using var torHttpClient = MakeTorHttpClient(networkType);
- using var client = new WasabiClient(torHttpClient);
+ var client = new WasabiClient(torHttpClient);
var content = await client.GetLegalDocumentsAsync(CancellationToken.None);

MODIFY
WalletWasabi.Tests/RegressionTests/BackendTests.cs
WalletWasabi.Tests/RegressionTests/BackendTests.cs
@@ -29,20 +29,25 @@ namespace WalletWasabi.Tests.RegressionTests
public BackendTests(RegTestFixture regTestFixture)
{
RegTestFixture = regTestFixture;
- BackendHttpClient = new BackendHttpClient(new ClearnetHttpClient(() => RegTestFixture.BackendEndPointApiUri));
+
+ BackendClearnetHttpClient = new ClearnetHttpClient(() => RegTestFixture.BackendEndPointUri);
+ BackendApiHttpClient = new BackendHttpClient(new ClearnetHttpClient(() => RegTestFixture.BackendEndPointApiUri));
}
private RegTestFixture RegTestFixture { get; }
+ /// <summary></summary>
+ public ClearnetHttpClient BackendClearnetHttpClient { get; }
+
/// <summary>Clearnet HTTP client.</summary>
- private BackendHttpClient BackendHttpClient { get; }
+ private BackendHttpClient BackendApiHttpClient { get; }
#region BackendTests
[Fact]
public async Task GetExchangeRatesAsync()
{
- using var response = await BackendHttpClient.SendAsync(HttpMethod.Get, "btc/offchain/exchange-rates");
+ using var response = await BackendApiHttpClient.SendAsync(HttpMethod.Get, "btc/offchain/exchange-rates");
Assert.True(response.StatusCode == HttpStatusCode.OK);
var exchangeRates = await response.Content.ReadAsJsonAsync<List<ExchangeRate>>();
@@ -56,7 +61,7 @@ namespace WalletWasabi.Tests.RegressionTests
[Fact]
public async Task GetClientVersionAsync()
{
- using var client = new WasabiClient(new Uri(RegTestFixture.BackendEndPoint), null);
+ var client = new WasabiClient(BackendClearnetHttpClient);
var uptodate = await client.CheckUpdatesAsync(CancellationToken.None);
Assert.True(uptodate.BackendCompatible);
Assert.True(uptodate.ClientUpToDate);
@@ -74,7 +79,7 @@ namespace WalletWasabi.Tests.RegressionTests
Logger.TurnOff();
- using var response = await BackendHttpClient.SendAsync(HttpMethod.Post, "btc/blockchain/broadcast", content);
+ using var response = await BackendApiHttpClient.SendAsync(HttpMethod.Post, "btc/blockchain/broadcast", content);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Transaction is already in the blockchain.", await response.Content.ReadAsJsonAsync<string>());
@@ -90,7 +95,7 @@ namespace WalletWasabi.Tests.RegressionTests
Logger.TurnOff();
- using var response = await BackendHttpClient.SendAsync(HttpMethod.Post, "btc/blockchain/broadcast", content);
+ using var response = await BackendApiHttpClient.SendAsync(HttpMethod.Post, "btc/blockchain/broadcast", content);
Assert.NotEqual(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
@@ -192,7 +197,7 @@ namespace WalletWasabi.Tests.RegressionTests
}
// First request.
- using (HttpResponseMessage response = await BackendHttpClient.SendAsync(HttpMethod.Get, requestUri))
+ using (HttpResponseMessage response = await BackendApiHttpClient.SendAsync(HttpMethod.Get, requestUri))
{
Assert.NotNull(response);
@@ -207,7 +212,7 @@ namespace WalletWasabi.Tests.RegressionTests
}
// Second request.
- using (HttpResponseMessage response = await BackendHttpClient.SendAsync(HttpMethod.Get, requestUri))
+ using (HttpResponseMessage response = await BackendApiHttpClient.SendAsync(HttpMethod.Get, requestUri))
{
Assert.NotNull(response);
@@ -224,7 +229,7 @@ namespace WalletWasabi.Tests.RegressionTests
}
// Third request.
- using (HttpResponseMessage response = await BackendHttpClient.SendAsync(HttpMethod.Get, requestUri))
+ using (HttpResponseMessage response = await BackendApiHttpClient.SendAsync(HttpMethod.Get, requestUri))
{
Assert.NotNull(response);

MODIFY
WalletWasabi.Tests/RegressionTests/CoinJoinTests.cs
WalletWasabi.Tests/RegressionTests/CoinJoinTests.cs
@@ -45,10 +45,12 @@ namespace WalletWasabi.Tests.RegressionTests
{
RegTestFixture = regTestFixture;
BaseUri = new Uri(RegTestFixture.BackendEndPoint);
+ BackendClearnetHttpClient = new ClearnetHttpClient(() => RegTestFixture.BackendEndPointUri);
}
private RegTestFixture RegTestFixture { get; }
public Uri BaseUri { get; }
+ public ClearnetHttpClient BackendClearnetHttpClient { get; }
[Fact]
public async Task CoordinatorCtorTestsAsync()
@@ -683,7 +685,7 @@ namespace WalletWasabi.Tests.RegressionTests
uint256[] mempooltxs = await rpc.GetRawMempoolAsync();
Assert.Contains(unsignedCoinJoin.GetHash(), mempooltxs);
- var wasabiClient = new WasabiClient(BaseUri, null);
+ var wasabiClient = new WasabiClient(BackendClearnetHttpClient);
var syncInfo = await wasabiClient.GetSynchronizeAsync(blockHashed[0], 1);
Assert.Contains(unsignedCoinJoin.GetHash(), syncInfo.UnconfirmedCoinJoins);
var txs = await wasabiClient.GetTransactionsAsync(network, new[] { unsignedCoinJoin.GetHash() }, CancellationToken.None);

MODIFY
WalletWasabi.Tests/RegressionTests/Common.cs
WalletWasabi.Tests/RegressionTests/Common.cs
using NBitcoin;
using System;
-using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
@@ -13,10 +12,10 @@ using WalletWasabi.Blockchain.Blocks;
using WalletWasabi.Blockchain.Mempool;
using WalletWasabi.Blockchain.Transactions;
using WalletWasabi.CoinJoin.Coordinator;
-using WalletWasabi.Helpers;
using WalletWasabi.Models;
using WalletWasabi.Stores;
using WalletWasabi.Tests.XunitConfiguration;
+using WalletWasabi.Tor.Http;
using WalletWasabi.Wallets;
using WalletWasabi.WebClients.Wasabi;
using Xunit;
@@ -41,7 +40,6 @@ namespace WalletWasabi.Tests.RegressionTests
}
}
- [SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Must match delegate")]
public static void Wallet_NewFilterProcessed(object? sender, FilterModel e)
{
Interlocked.Increment(ref FiltersProcessedByWalletCount);
@@ -52,11 +50,11 @@ namespace WalletWasabi.Tests.RegressionTests
var firstHash = await global.RpcClient.GetBlockHashAsync(0);
while (true)
{
- using var client = new WasabiClient(new Uri(regTestFixture.BackendEndPoint), torSocks5EndPoint: null);
+ var client = new WasabiClient(new ClearnetHttpClient(() => regTestFixture.BackendEndPointUri));
FiltersResponse? filtersResponse = await client.GetFiltersAsync(firstHash, 1000);
Assert.NotNull(filtersResponse);
- var filterCount = filtersResponse.Filters.Count();
+ var filterCount = filtersResponse!.Filters.Count();
if (filterCount >= 101)
{
break;
@@ -83,7 +81,7 @@ namespace WalletWasabi.Tests.RegressionTests
global.Coordinator.UtxoReferee.Clear();
var network = global.RpcClient.Network;
- var serviceConfiguration = new ServiceConfiguration(MixUntilAnonymitySet.PrivacyLevelSome.ToString(), 2, 21, 50, regTestFixture.BackendRegTestNode.P2pEndPoint, Money.Coins(Constants.DefaultDustThreshold));
+ var serviceConfiguration = new ServiceConfiguration(MixUntilAnonymitySet.PrivacyLevelSome.ToString(), 2, 21, 50, regTestFixture.BackendRegTestNode.P2pEndPoint, Money.Coins(WalletWasabi.Helpers.Constants.DefaultDustThreshold));
var dir = Tests.Common.GetWorkDir(callerFilePath, callerMemberName);
var indexStore = new IndexStore(Path.Combine(dir, "indexStore"), network, new SmartHeaderChain());

MODIFY
WalletWasabi/Blockchain/Mempool/MempoolService.cs
WalletWasabi/Blockchain/Mempool/MempoolService.cs
@@ -114,10 +114,9 @@ namespace WalletWasabi.Blockchain.Mempool
}
Logger.LogInfo("Start cleaning out mempool...");
- using (var client = wasabiClientFactory.NewBackendClient())
{
var compactness = 10;
- var allMempoolHashes = await client.GetMempoolHashesAsync(compactness).ConfigureAwait(false);
+ var allMempoolHashes = await wasabiClientFactory.SharedWasabiClient.GetMempoolHashesAsync(compactness).ConfigureAwait(false);
lock (ProcessedLock)
{

MODIFY
WalletWasabi/Blockchain/TransactionBroadcasting/TransactionBroadcaster.cs
WalletWasabi/Blockchain/TransactionBroadcasting/TransactionBroadcaster.cs
@@ -11,6 +11,7 @@ using WalletWasabi.Logging;
using WalletWasabi.Models;
using WalletWasabi.Services;
using WalletWasabi.Stores;
+using WalletWasabi.Tor.Http;
using WalletWasabi.Wallets;
using WalletWasabi.WebClients.Wasabi;
@@ -85,8 +86,10 @@ namespace WalletWasabi.Blockchain.TransactionBroadcasting
private async Task BroadcastTransactionToBackendAsync(SmartTransaction transaction)
{
Logger.LogInfo("Broadcasting with backend...");
- using (WasabiClient client = Synchronizer.WasabiClientFactory.NewBackendClient(true))
+ using (TorHttpClient torHttpClient = Synchronizer.WasabiClientFactory.NewTorHttpClient(isolateStream: true))
{
+ var client = new WasabiClient(torHttpClient);
+
try
{
await client.BroadcastAsync(transaction).ConfigureAwait(false);

MODIFY
WalletWasabi/CoinJoin/Client/CoinJoinProcessor.cs
WalletWasabi/CoinJoin/Client/CoinJoinProcessor.cs
@@ -47,8 +47,7 @@ namespace WalletWasabi.CoinJoin.Client
var txsNotKnownByAWallet = WalletManager.FilterUnknownCoinjoins(unconfirmedCoinJoinHashes);
- using var client = Synchronizer.WasabiClientFactory.NewBackendClient();
-
+ var client = Synchronizer.WasabiClientFactory.SharedWasabiClient;
var unconfirmedCoinJoins = await client.GetTransactionsAsync(Synchronizer.Network, txsNotKnownByAWallet, CancellationToken.None).ConfigureAwait(false);
foreach (var tx in unconfirmedCoinJoins.Select(x => new SmartTransaction(x, Height.Mempool)))

MODIFY
WalletWasabi/Services/UpdateChecker.cs
WalletWasabi/Services/UpdateChecker.cs
@@ -14,7 +14,7 @@ namespace WalletWasabi.Services
{
Synchronizer = synchronizer;
UpdateStatus = new UpdateStatus(true, true, new Version(), 0);
- WasabiClient = Synchronizer.WasabiClientFactory.NewBackendClient();
+ WasabiClient = Synchronizer.WasabiClientFactory.SharedWasabiClient;
Synchronizer.PropertyChanged += Synchronizer_PropertyChanged;
}
@@ -46,7 +46,6 @@ namespace WalletWasabi.Services
public override void Dispose()
{
Synchronizer.PropertyChanged -= Synchronizer_PropertyChanged;
- WasabiClient.Dispose();
base.Dispose();
}
}

MODIFY
WalletWasabi/Services/WasabiSynchronizer.cs
WalletWasabi/Services/WasabiSynchronizer.cs
@@ -50,7 +50,7 @@ namespace WalletWasabi.Services
_running = StateNotStarted;
BitcoinStore = bitcoinStore;
WasabiClientFactory = wasabiClientFactory;
- WasabiClient = wasabiClientFactory.NewBackendClient();
+ WasabiClient = wasabiClientFactory.SharedWasabiClient;
StopCts = new CancellationTokenSource();
}
@@ -412,7 +412,6 @@ namespace WalletWasabi.Services
await Task.Delay(50).ConfigureAwait(false);
}
- WasabiClient.Dispose();
StopCts.Dispose();
EnableRequests(); // Enable requests (it's possible something is being blocked outside the class by AreRequestsBlocked.

MODIFY
WalletWasabi/Wallets/Wallet.cs
WalletWasabi/Wallets/Wallet.cs
@@ -22,7 +22,6 @@ using WalletWasabi.Models;
using WalletWasabi.Services;
using WalletWasabi.Stores;
using WalletWasabi.WebClients.PayJoin;
-using WalletWasabi.WebClients.Wasabi;
namespace WalletWasabi.Wallets
{
@@ -421,7 +420,7 @@ namespace WalletWasabi.Wallets
{
try
{
- using var client = Synchronizer.WasabiClientFactory.NewBackendClient();
+ var client = Synchronizer.WasabiClientFactory.SharedWasabiClient;
var compactness = 10;
var mempoolHashes = await client.GetMempoolHashesAsync(compactness).ConfigureAwait(false);

MODIFY
WalletWasabi/WebClients/Wasabi/WasabiClient.cs
WalletWasabi/WebClients/Wasabi/WasabiClient.cs
@@ -17,19 +17,8 @@ using WalletWasabi.Tor.Http.Extensions;
namespace WalletWasabi.WebClients.Wasabi
{
- public class WasabiClient : IDisposable
+ public class WasabiClient
{
- private volatile bool _disposedValue = false; // To detect redundant calls
-
- private WasabiClient(Func<Uri> baseUriAction, EndPoint? torSocks5EndPoint)
- {
- HttpClient = new TorHttpClient(baseUriAction, torSocks5EndPoint, isolateStream: true);
- }
-
- public WasabiClient(Uri baseUri, EndPoint? torSocks5EndPoint) : this(() => baseUri, torSocks5EndPoint)
- {
- }
-
public WasabiClient(IRelativeHttpClient httpClient)
{
HttpClient = httpClient;
@@ -288,25 +277,5 @@ namespace WalletWasabi.WebClients.Wasabi
}
#endregion wasabi
-
- protected virtual void Dispose(bool disposing)
- {
- if (!_disposedValue)
- {
- if (disposing)
- {
- (HttpClient as IDisposable)?.Dispose();
- }
-
- _disposedValue = true;
- }
- }
-
- // This code added to correctly implement the disposable pattern.
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- Dispose(true);
- }
}
}
\ No newline at end of file

MODIFY
WalletWasabi/WebClients/Wasabi/WasabiClientFactory.cs
WalletWasabi/WebClients/Wasabi/WasabiClientFactory.cs
@@ -17,8 +17,16 @@ namespace WalletWasabi.WebClients.Wasabi
{
TorEndpoint = torEndPoint;
BackendUriGetter = backendUriGetter;
+
+ SharedTorHttpClient = new TorHttpClient(BackendUriGetter.Invoke(), TorEndpoint, isolateStream: false);
+ SharedWasabiClient = new WasabiClient(SharedTorHttpClient);
}
+ /// <summary>
+ /// To detect redundant calls.
+ /// </summary>
+ private bool _disposed = false;
+
/// <summary>Tor SOCKS5 endpoint.</summary>
/// <remarks>The property should be <c>>private</c> when Tor refactoring is done.</remarks>
public EndPoint? TorEndpoint { get; }
@@ -29,17 +37,44 @@ namespace WalletWasabi.WebClients.Wasabi
/// <summary>Whether Tor is enabled or disabled.</summary>
public bool IsTorEnabled => TorEndpoint is { };
+ /// <summary>Shared instance of <see cref="TorHttpClient"/>.</summary>
+ public TorHttpClient SharedTorHttpClient { get; }
+
+ /// <summary>Shared instance of <see cref="WasabiClient"/>.</summary>
+ public WasabiClient SharedWasabiClient { get; }
+
/// <summary>
- /// Creates new <see cref="WasabiClient"/> instance with correctly set backend URL.
+ /// Creates new <see cref="TorHttpClient"/> instance with correctly set backend URL.
/// </summary>
- /// <remarks>
- /// For privacy reasons, it is advisable to create a new instance of <see cref="WasabiClient"/>
- /// for each HTTP request instead of reusing one instance for multiple HTTP requests.
- /// </remarks>
- public WasabiClient NewBackendClient(bool isolateStream = false)
- {
- TorHttpClient torHttpClient = new TorHttpClient(BackendUriGetter.Invoke(), TorEndpoint, isolateStream: isolateStream);
- return new WasabiClient(torHttpClient);
+ public TorHttpClient NewTorHttpClient(bool isolateStream = true)
+ {
+ return new TorHttpClient(BackendUriGetter.Invoke(), TorEndpoint, isolateStream: isolateStream);
+ }
+
+ // Protected implementation of Dispose pattern.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed)
+ {
+ return;
+ }
+
+ if (disposing)
+ {
+ // Dispose managed state (managed objects).
+ SharedTorHttpClient.Dispose();
+ }
+
+ _disposed = true;
+ }
+
+ public void Dispose()
+ {
+ // Dispose of unmanaged resources.
+ Dispose(true);
+
+ // Suppress finalization.
+ GC.SuppressFinalize(this);
}
}
}
\ No newline at end of file

WasabiClient is not disposable anymore.