8000 Changed the http client to use IHttpClientFactory by DavidGershony · Pull Request #394 · block-core/angor · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Changed the http client to use IHttpClientFactory #394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Angor.Test/Angor.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
<PackageReference Include="Microsoft.JSInterop" Version="8.0.11" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="Moq" Version="4.20.72" />
Expand Down
9 changes: 8 additions & 1 deletion src/Angor.Test/Services/TestSignService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ public TestSignService()
},
});

var mockIHttpClientFactory = new Mock<IHttpClientFactory>();
mockIHttpClientFactory.Setup(x => x.CreateClient(It.IsAny<string>()))
.Returns(new HttpClient(new HttpClientHandler())
{
BaseAddress = new Uri("https://mempool.space/api/v1/")
});

var communicationFactory = new NostrCommunicationFactory(new NullLogger<NostrWebsocketClient>(), new NullLogger<NostrCommunicationFactory>());
var networkService = new NetworkService(mockNetworkStorage.Object, new HttpClient { BaseAddress = new Uri("https://angor.io") }, new NullLogger<NetworkService>(), mockNetworkConfiguration.Object);
var networkService = new NetworkService(mockNetworkStorage.Object, mockIHttpClientFactory.Object, new NullLogger<NetworkService>(), mockNetworkConfiguration.Object);
var subscriptionsHanding = new RelaySubscriptionsHandling(new NullLogger<RelaySubscriptionsHandling>(), communicationFactory, networkService);

_signService = new SignService(communicationFactory, networkService, subscriptionsHanding);
Expand Down
2 changes: 1 addition & 1 deletion src/Angor/Client/Angor.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<PackageReference Include="Blazored.SessionStorage" Version="2.4.0" />
<PackageReference Include="Blockcore.Core" Version="1.1.41" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.71" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
<PackageReference Include="Microsoft.JSInterop" Version="8.0.11" />
<PackageReference Include="NBitcoin" Version="7.0.46" />
<PackageReference Include="Blockcore.Nostr.Client" Version="2.0.1" />
Expand Down
5 changes: 3 additions & 2 deletions src/Angor/Client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
using Blazored.SessionStorage;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using System.Globalization;
using Angor.Shared.Protocol;
using Angor.Shared.Protocol.Scripts;
using Angor.Shared.Protocol.TransactionBuilders;


var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddHttpClient();


builder.Services.AddBlazoredLocalStorage();
builder.Services.AddBlazoredSessionStorage();
Expand Down
3 changes: 2 additions & 1 deletion src/Angor/Shared/Angor.Shared.csproj
10000
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

<ItemGroup>
<PackageReference Include="Blockcore.Core" Version="1.1.41" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
<PackageReference Include="NBitcoin" Version="7.0.46" />
<PackageReference Include="Blockcore.Nostr.Client" Version="2.0.1" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
Expand Down
96 changes: 49 additions & 47 deletions src/Angor/Shared/Services/MempoolSpaceIndexerApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,17 @@ namespace Angor.Shared.Services;
public class MempoolSpaceIndexerApi : IIndexerService
{
private readonly ILogger<MempoolSpaceIndexerApi> _logger;

private readonly INetworkConfiguration _networkConfiguration;
private readonly HttpClient _httpClient;

private readonly IHttpClientFactory _clientFactory;
private readonly INetworkService _networkService;

private const string AngorApiRoute = "/api/v1/query/Angor";
private const string MempoolApiRoute = "/api/v1";

public MempoolSpaceIndexerApi(ILogger<MempoolSpaceIndexerApi> logger, INetworkConfiguration networkConfiguration, HttpClient httpClient, INetworkService networkService)
public MempoolSpaceIndexerApi(ILogger<MempoolSpaceIndexerApi> logger, IHttpClientFactory clientFactory, INetworkService networkService)
{
_logger = logger;
_networkConfiguration = networkConfiguration;
_httpClient = httpClient;
_clientFactory = clientFactory;
_networkService = networkService;
}

Expand Down Expand Up @@ -112,13 +110,22 @@ private class Outspent
public UtxoStatus Status { get; set; }
}

public async Task<List<ProjectIndexerData>> GetProjectsAsync(int? offset, int limit)
private HttpClient GetIndexerClient()
{
var indexer = _networkService.GetPrimaryIndexer();
var client = _clientFactory.CreateClient();
client.BaseAddress = new Uri(indexer.Url);
return client;
}

public async Task<List<ProjectIndexerData>> GetProjectsAsync(int? offset, int limit)
{
var url = offset == null ?
$"{indexer.Url}{AngorApiRoute}/projects?limit={limit}" :
$"{indexer.Url}{AngorApiRoute}/projects?offset={offset}&limit={limit}";
var response = await _httpClient.GetAsync(url);
$"{AngorApiRoute}/projects?limit={limit}" :
$"{AngorApiRoute}/projects?offset={offset}&limit={limit}";

var response = await GetIndexerClient()
.GetAsync(url);
_networkService.CheckAndHandleError(response);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<List<ProjectIndexerData>>() ?? new List<ProjectIndexerData>();
Expand All @@ -136,8 +143,8 @@ public async Task<List<ProjectIndexerData>> GetProjectsAsync(int? offset, int li
return null;
}

var indexer = _networkService.GetPrimaryIndexer();
var response = await _httpClient.GetAsync($"{indexer.Url}{AngorApiRoute}/projects/{projectId}");
var response = await GetIndexerClient()
.GetAsync($"{AngorApiRoute}/projects/{projectId}");
_networkService.CheckAndHandleError(response);

if (response.StatusCode == HttpStatusCode.NotFound)
Expand All @@ -155,8 +162,8 @@ public async Task<List<ProjectIndexerData>> GetProjectsAsync(int? offset, int li
return null;
}

var indexer = _networkService.GetPrimaryIndexer();
var response = await _httpClient.GetAsync($"{indexer.Url}{AngorApiRoute}/projects/{projectId}/stats");
var response = await GetIndexerClient()
.GetAsync($"{AngorApiRoute}/projects/{projectId}/stats");
_networkService.CheckAndHandleError(response);

if (response.StatusCode == HttpStatusCode.NotFound)
Expand All @@ -169,27 +176,26 @@ public async Task<List<ProjectIndexerData>> GetProjectsAsync(int? offset, int li

public async Task<List<ProjectInvestment>> GetInvestmentsAsync(string projectId)
{
var indexer = _networkService.GetPrimaryIndexer();
var response = await _httpClient.GetAsync($"{indexer.Url}{AngorApiRoute}/projects/{projectId}/investments");
var response = await GetIndexerClient()
.GetAsync($"{AngorApiRoute}/projects/{projectId}/investments");
_networkService.CheckAndHandleError(response);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<List<ProjectInvestment>>();
}

public async Task<ProjectInvestment?> GetInvestmentAsync(string projectId, string investorPubKey)
{
var indexer = _networkService.GetPrimaryIndexer();
var response = await _httpClient.GetAsync($"{indexer.Url}{AngorApiRoute}/projects/{projectId}/investments/{investorPubKey}");
var response = await GetIndexerClient()
.GetAsync($"{AngorApiRoute}/projects/{projectId}/investments/{investorPubKey}");
_networkService.CheckAndHandleError(response);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<ProjectInvestment>();
}

public async Task<string> PublishTransactionAsync(string trxHex)
{
var indexer = _networkService.GetPrimaryIndexer();

var response = await _httpClient.PostAsync($"{indexer.Url}{MempoolApiRoute}/tx", new StringContent(trxHex));
var response = await GetIndexerClient()
.PostAsync($"{MempoolApiRoute}/tx", new StringContent(trxHex));

_networkService.CheckAndHandleError(response);

Expand All @@ -213,8 +219,8 @@ public async Task<AddressBalance[]> GetAdressBalancesAsync(List<AddressInfo> dat
{
//check all new addresses for balance or a history

var indexer = _networkService.GetPrimaryIndexer();
return _httpClient.GetAsync(indexer.Url + urlBalance + x.Address);
return GetIndexerClient()
.GetAsync(urlBalance + x.Address);
});

var results = await Task.WhenAll(tasks);
Expand Down Expand Up @@ -247,11 +253,10 @@ public async Task<AddressBalance[]> GetAdressBalancesAsync(List<AddressInfo> dat

public async Task<List<UtxoData>?> FetchUtxoAsync(string address, int limit, int offset)
{
var indexer = _networkService.GetPrimaryIndexer();

var txsUrl = $"{MempoolApiRoute}/address/{address}/txs";

var response = await _httpClient.GetAsync(indexer.Url + txsUrl);
var response = await GetIndexerClient()
.GetAsync(txsUrl);
_networkService.CheckAndHandleError(response);

if (!response.IsSuccessStatusCode)
Expand All @@ -272,7 +277,7 @@ public async Task<AddressBalance[]> GetAdressBalancesAsync(List<AddressInfo> dat

var outspendsUrl = $"{MempoolApiRoute}/tx/" + mempoolTransaction.Txid + "/outspends";

var resultsOutputs = await _httpClient.GetAsync(indexer.Url + outspendsUrl);
var resultsOutputs = await GetIndexerClient().GetAsync(outspendsUrl);

var spentOutputsStatus = await resultsOutputs.Content.ReadFromJsonAsync<List<Outspent>>(new JsonSerializerOptions()
{ PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower });
Expand Down Expand Up @@ -316,14 +321,13 @@ public async Task<AddressBalance[]> GetAdressBalancesAsync(List<AddressInfo> dat

public async Task<List<QueryTransaction>?> FetchAddressHistoryAsync(string address, string? afterTrxId = null) //TODO check the paging (I think it is 50 by default
{
var indexer = _networkService.GetPrimaryIndexer();

var txsUrl = $"{MempoolApiRoute}/address/{address}/txs";

if (!string.IsNullOrEmpty(afterTrxId))
txsUrl += $"?after_txid={afterTrxId}";

var response = await _httpClient.GetAsync(indexer.Url + txsUrl);
var response = await GetIndexerClient()
.GetAsync( txsUrl);
_networkService.CheckAndHandleError(response);

if (!response.IsSuccessStatusCode)
Expand All @@ -337,11 +341,10 @@ public async Task<AddressBalance[]> GetAdressBalancesAsync(List<AddressInfo> dat

public async Task<FeeEstimations?> GetFeeEstimationAsync(int[] confirmations)
{
var indexer = _networkService.GetPrimaryIndexer();

var url = $"{MempoolApiRoute}/fees/recommended";

var response = await _httpClient.GetAsync(indexer.Url + url);

var response = await GetIndexerClient()
.GetAsync(url);
_networkService.CheckAndHandleError(response);

if (!response.IsSuccessStatusCode)
Expand Down Expand Up @@ -369,11 +372,10 @@ public async Task<AddressBalance[]> GetAdressBalancesAsync(List<AddressInfo> dat

public async Task<string> GetTransactionHexByIdAsync(string transactionId)
{
var indexer = _networkService.GetPrimaryIndexer();

var url = $"{MempoolApiRoute}/tx/{transactionId}/hex";

var response = await _httpClient.GetAsync(indexer.Url + url);
var response = await GetIndexerClient()
.GetAsync(url);
_networkService.CheckAndHandleError(response);

if (!response.IsSuccessStatusCode)
Expand All @@ -384,11 +386,10 @@ public async Task<string> GetTransactionHexByIdAsync(string transactionId)

public async Task<QueryTransaction?> GetTransactionInfoByIdAsync(string transactionId)
{
var indexer = _networkService.GetPrimaryIndexer();

var url = $"{MempoolApiRoute}/tx/{transactionId}";

var response = await _httpClient.GetAsync(indexer.Url + url);
var response = await GetIndexerClient()
.GetAsync(url);
_networkService.CheckAndHandleError(response);

if (!response.IsSuccessStatusCode)
Expand All @@ -403,7 +404,8 @@ public async Task<string> GetTransactionHexByIdAsync(string transactionId)

var urlSpent = $"{MempoolApiRoute}/tx/{transactionId}/outspends";

var responseSpent = await _httpClient.GetAsync(indexer.Url + urlSpent);
var responseSpent = await GetIndexerClient()
.GetAsync(urlSpent);
_networkService.CheckAndHandleError(responseSpent);

if (!responseSpent.IsSuccessStatusCode)
Expand Down Expand Up @@ -462,8 +464,6 @@ private QueryTransaction MapToQueryTransaction(MempoolTransaction x, List<Outspe

private async Task PopulateSpentMissingData(List<Outspent> outspents, MempoolTransaction mempoolTransaction)
{
var indexer = _networkService.GetPrimaryIndexer();

for (int index = 0; index < outspents.Count; index++)
{
var outspent = outspents[index];
Expand All @@ -475,7 +475,8 @@ private async Task PopulateSpentMissingData(List<Outspent> outspents, MempoolTra
{
var txsUrl = $"{MempoolApiRoute}/address/{output.ScriptpubkeyAddress}/txs";

var response = await _httpClient.GetAsync(indexer.Url + txsUrl);
var response = await GetIndexerClient()
.GetAsync(txsUrl);
_networkService.CheckAndHandleError(response);

if (!response.IsSuccessStatusCode)
Expand Down Expand Up @@ -514,9 +515,10 @@ private async Task PopulateSpentMissingData(List<Outspent> outspents, MempoolTra
try
{
// fetch block 0 (Genesis Block)
var blockUrl = $"{indexerUrl}{MempoolApiRoute}/block-height/0";

var blockResponse = await _httpClient.GetAsync(blockUrl);
var blockUrl = $"{MempoolApiRoute}/block-height/0";

var blockResponse = await GetIndexerClient()
.GetAsync(blockUrl);

if (!blockResponse.IsSuccessStatusCode)
{
Expand Down
16 changes: 9 additions & 7 deletions src/Angor/Shared/Services/NetworkService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ namespace Angor.Shared.Services
public class NetworkService : INetworkService
{
private readonly INetworkStorage _networkStorage;
private readonly HttpClient _httpClient;
private readonly IHttpClientFactory _clientFactory;
private readonly ILogger<NetworkService> _logger;
private readonly INetworkConfiguration _networkConfiguration;
public event Action OnStatusChanged;


public NetworkService(INetworkStorage networkStorage, HttpClient httpClient, ILogger<NetworkService> logger, INetworkConfiguration networkConfiguration)
public NetworkService(INetworkStorage networkStorage, IHttpClientFactory clientFactory, ILogger<NetworkService> logger, INetworkConfiguration networkConfiguration)
{
_networkStorage = networkStorage;
_httpClient = httpClient;
_clientFactory = clientFactory;
_logger = logger;
_networkConfiguration = networkConfiguration;
}
Expand Down Expand Up @@ -113,7 +113,8 @@ public async Task CheckServices(bool force = false)

var blockUrl = Path.Combine(uri.AbsoluteUri, "api", "v1", "block-height", "0");

var response = await _httpClient.GetAsync(blockUrl);
var response = await _clientFactory.CreateClient()
.GetAsync(blockUrl);

if (response.IsSuccessStatusCode)
{
Expand Down Expand Up @@ -165,7 +166,8 @@ public async Task CheckServices(bool force = false)
//}

var nostrHeaderMediaType = new MediaTypeWithQualityHeaderValue("application/nostr+json");
_httpClient.DefaultRequestHeaders.Accept.Add(nostrHeaderMediaType);
var client = _clientFactory.CreateClient();
client.DefaultRequestHeaders.Accept.Add(nostrHeaderMediaType);
foreach (var relayUrl in settings.Relays)
{
if (force || (DateTime.UtcNow - relayUrl.LastCheck).Minutes > 1)
Expand All @@ -179,7 +181,7 @@ public async Task CheckServices(bool force = false)
? new Uri($"https://{uri.Host}/")
: new Uri($"http://{uri.Host}/");

var response = await _httpClient.GetAsync(httpUri);
var response = await client.GetAsync(httpUri);

if (response.IsSuccessStatusCode)
{
Expand All @@ -201,7 +203,7 @@ public async Task CheckServices(bool force = false)
}
}

_httpClient.DefaultRequestHeaders.Accept.Remove(nostrHeaderMediaType);
client.DefaultRequestHeaders.Accept.Remove(nostrHeaderMediaType);
_networkStorage.SetSettings(settings);
}

Expand Down
0