Enhance UI, add AI integration, improve logging and database stats

This commit is contained in:
Richard
2026-07-04 21:11:31 +02:00
parent 7a44914d9d
commit d102af2965
57 changed files with 4025 additions and 229 deletions
@@ -43,39 +43,39 @@ public class PolymarketApiClient
public async Task<List<PolymarketTradeResponse>> GetTradesAsync(string walletAddress, int limit = 1000, CancellationToken ct = default)
{
var url = $"/activity?user={walletAddress}&limit={limit}";
return await ExecuteWithRetryAsync<List<PolymarketTradeResponse>>(_client, url, ct) ?? [];
return await ExecuteWithRetryAsync<List<PolymarketTradeResponse>>(_client, url, "Data", ct) ?? [];
}
public async Task<List<PolymarketTradeResponse>> GetMarketTradesAsync(string conditionId, int limit = 1000, CancellationToken ct = default)
{
var url = $"/trades?condition_id={conditionId}&limit={limit}";
return await ExecuteWithRetryAsync<List<PolymarketTradeResponse>>(_client, url, ct) ?? [];
return await ExecuteWithRetryAsync<List<PolymarketTradeResponse>>(_client, url, "Data", ct) ?? [];
}
public async Task<List<PolymarketPositionResponse>> GetPositionsAsync(string walletAddress, CancellationToken ct = default)
{
var url = $"/positions?user={walletAddress}&sizeThreshold=0.1&sortBy=CURRENT&sortOrder=DESC";
return await ExecuteWithRetryAsync<List<PolymarketPositionResponse>>(_client, url, ct) ?? [];
return await ExecuteWithRetryAsync<List<PolymarketPositionResponse>>(_client, url, "Data", ct) ?? [];
}
public async Task<GammaMarketResponse?> GetMarketAsync(string conditionId, CancellationToken ct = default)
{
var url = $"/markets?condition_id={conditionId}";
var results = await ExecuteWithRetryAsync<List<GammaMarketResponse>>(_gammaClient, url, ct);
var results = await ExecuteWithRetryAsync<List<GammaMarketResponse>>(_gammaClient, url, "Gamma", ct);
return results?.FirstOrDefault();
}
/// <summary>
/// Fetch a batch of markets from the Gamma API with pagination.
/// Fetch a batch of events (and their nested markets) from the Gamma API with pagination.
/// Supports offset-based pagination via the offset parameter.
/// </summary>
public async Task<List<GammaMarketResponse>> GetMarketsAsync(int limit = 1000, int offset = 0, bool includeClosed = false, CancellationToken ct = default)
public async Task<List<GammaEventResponse>> GetEventsAsync(int limit = 100, int offset = 0, bool includeClosed = false, CancellationToken ct = default)
{
var activeOnly = !includeClosed;
var url = $"/markets?limit={limit}&offset={offset}&active={activeOnly.ToString().ToLower()}&closed={includeClosed.ToString().ToLower()}";
_logger.LogDebug("Fetching markets: {Url}", url);
var result = await ExecuteWithRetryAsync<List<GammaMarketResponse>>(_gammaClient, url, ct);
_logger.LogInformation("Fetched {Count} markets (offset={Offset}, closed={Closed})", result?.Count ?? 0, offset, includeClosed);
var url = $"/events?limit={limit}&offset={offset}&active={activeOnly.ToString().ToLower()}&closed={includeClosed.ToString().ToLower()}";
_logger.LogDebug("Fetching events: {Url}", url);
var result = await ExecuteWithRetryAsync<List<GammaEventResponse>>(_gammaClient, url, "Gamma", ct);
_logger.LogInformation("Fetched {Count} events (offset={Offset}, closed={Closed})", result?.Count ?? 0, offset, includeClosed);
return result ?? [];
}
@@ -87,7 +87,7 @@ public class PolymarketApiClient
{
var url = $"/holders?market={conditionId}&limit={limit}";
_logger.LogDebug("Fetching holders: {Url}", url);
var result = await ExecuteWithRetryAsync<List<HoldersResponse>>(_client, url, ct);
var result = await ExecuteWithRetryAsync<List<HoldersResponse>>(_client, url, "Data", ct);
_logger.LogInformation("Fetched holders for {Market}: {Count} token groups",
conditionId.Length > 12 ? conditionId[..12] + "..." : conditionId, result?.Count ?? 0);
return result ?? [];
@@ -106,13 +106,15 @@ public class PolymarketApiClient
{
var url = $"/v1/leaderboard?limit={Math.Min(limit, 50)}&time_period={timePeriod}&order_by={orderBy}&category={category}";
_logger.LogDebug("Fetching leaderboard: {Url}", url);
var result = await ExecuteWithRetryAsync<List<LeaderboardEntry>>(_client, url, ct);
var result = await ExecuteWithRetryAsync<List<LeaderboardEntry>>(_client, url, "Data", ct);
_logger.LogInformation("Leaderboard returned {Count} entries", result?.Count ?? 0);
return result ?? [];
}
private async Task<T?> ExecuteWithRetryAsync<T>(HttpClient client, string url, CancellationToken ct, int attempt = 1)
private async Task<T?> ExecuteWithRetryAsync<T>(HttpClient client, string url, string endpointGroup, CancellationToken ct, int attempt = 1)
{
await _rateLimiter.WaitAsync(PlatformType.Polymarket, ct, endpointGroup);
try
{
var response = await client.GetAsync(url, ct);
@@ -135,15 +137,14 @@ public class PolymarketApiClient
waitTime = TimeSpan.FromSeconds(30);
}
_logger.LogWarning("⚠️ Rate limit exceeded (429) for Polymarket. Pausing for {WaitTime}s...", (int)waitTime.TotalSeconds);
_logger.LogWarning("⚠️ Rate limit exceeded (429) for Polymarket {Group}. Pausing for {WaitTime}s...", endpointGroup, (int)waitTime.TotalSeconds);
_rateLimiter.ReportRateLimitExceeded(PlatformType.Polymarket, waitTime);
_rateLimiter.ReportRateLimitExceeded(PlatformType.Polymarket, waitTime, endpointGroup);
if (attempt < 3)
{
await _rateLimiter.WaitAsync(PlatformType.Polymarket, ct);
_logger.LogWarning("Retrying {Url} (attempt {NextAttempt})...", url, attempt + 1);
return await ExecuteWithRetryAsync<T>(client, url, ct, attempt + 1);
return await ExecuteWithRetryAsync<T>(client, url, endpointGroup, ct, attempt + 1);
}
return default;
@@ -172,7 +173,7 @@ public class PolymarketApiClient
public async Task<List<PriceHistoryEntry>> GetPricesHistoryAsync(string clobTokenId, string interval = "6h", CancellationToken ct = default)
{
var url = $"/prices-history?market={clobTokenId}&interval={interval}";
var result = await ExecuteWithRetryAsync<PolymarketPriceHistoryResponse>(_clobClient, url, ct);
var result = await ExecuteWithRetryAsync<PolymarketPriceHistoryResponse>(_clobClient, url, "Clob", ct);
return result?.History ?? [];
}
}