Skip to content

Commit 3d347a9

Browse files
committed
Implements marketinsights api
1 parent 87bda47 commit 3d347a9

File tree

12 files changed

+277
-73
lines changed

12 files changed

+277
-73
lines changed

Framework/Utils/RollingAverage.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@ public static float GetNewAverage(float currentAverage, int newNumberOfValues, f
1515
var originalValue = currentAverage;
1616
var originalValueWeight = ((n - 1.0f) / n);
1717
var newValueWeight = (1.0f / n);
18-
return (originalValue * originalValueWeight) + (newValue * newValueWeight);
18+
return GetWeightedAverage(originalValue, originalValueWeight, newValue, newValueWeight);
19+
}
20+
21+
public static float GetWeightedAverage(float value1, float weight1, float value2, float weight2)
22+
{
23+
float totalWeight = weight1 + weight2;
24+
if (totalWeight == 0.0f) return 0.0f;
25+
return ((value1 * weight1) + (value2 * weight2)) / totalWeight;
1926
}
2027
}
2128
}

Tools/MarketInsights/AppState.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace MarketInsights
1+
using Logging;
2+
3+
namespace MarketInsights
24
{
35
public class AppState
46
{
@@ -7,7 +9,9 @@ public AppState(Configuration config)
79
Config = config;
810
}
911

10-
public MarketOverview MarketOverview { get; set; } = new ();
12+
public bool Realtime { get; set; }
13+
public MarketOverview MarketOverview { get; set; } = new();
1114
public Configuration Config { get; }
15+
public ILog Log { get; } = new ConsoleLog();
1216
}
1317
}
Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,50 @@
1-
using CodexContractsPlugin.ChainMonitor;
2-
using GethPlugin;
3-
using System.Numerics;
1+
using CodexContractsPlugin;
2+
using CodexContractsPlugin.ChainMonitor;
3+
using Nethereum.Model;
4+
using TestNetRewarder;
45
using Utils;
56

67
namespace MarketInsights
78
{
8-
public class AverageHistory
9+
public class AverageHistory : ITimeSegmentHandler
910
{
10-
public readonly List<MarketTimeSegment> contributions = new List<MarketTimeSegment>();
11+
private readonly List<MarketTimeSegment> contributions = new List<MarketTimeSegment>();
12+
private readonly ChainStateChangeHandlerMux mux = new ChainStateChangeHandlerMux();
13+
private readonly AppState appState;
14+
private readonly int maxContributions;
15+
private readonly ChainState chainState;
1116

12-
}
13-
14-
public class ContributionBuilder : IChainStateChangeHandler
15-
{
16-
private readonly MarketTimeSegment segment = new MarketTimeSegment();
17-
18-
public void OnNewRequest(RequestEvent requestEvent)
17+
public AverageHistory(AppState appState, ICodexContracts contracts, int maxContributions)
1918
{
20-
AddRequestToAverage(segment.Submitted, requestEvent);
19+
this.appState = appState;
20+
this.maxContributions = maxContributions;
21+
chainState = new ChainState(appState.Log, contracts, mux, appState.Config.HistoryStartUtc);
2122
}
2223

23-
public void OnRequestCancelled(RequestEvent requestEvent)
24-
{
25-
AddRequestToAverage(segment.Expired, requestEvent);
26-
}
24+
public MarketTimeSegment[] Segments { get; private set; } = Array.Empty<MarketTimeSegment>();
2725

28-
public void OnRequestFailed(RequestEvent requestEvent)
26+
public Task OnNewSegment(TimeRange timeRange)
2927
{
30-
AddRequestToAverage(segment.Failed, requestEvent);
31-
}
28+
var contribution = BuildContribution(timeRange);
29+
contributions.Add(contribution);
3230

33-
public void OnRequestFinished(RequestEvent requestEvent)
34-
{
35-
AddRequestToAverage(segment.Finished, requestEvent);
36-
}
31+
while (contributions.Count > maxContributions)
32+
{
33+
contributions.RemoveAt(0);
34+
}
3735

38-
public void OnRequestFulfilled(RequestEvent requestEvent)
39-
{
40-
AddRequestToAverage(segment.Started, requestEvent);
41-
}
36+
Segments = contributions.ToArray();
4237

43-
public void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex)
44-
{
45-
}
46-
47-
public void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex)
48-
{
49-
}
50-
51-
private void AddRequestToAverage(ContractAverages average, RequestEvent requestEvent)
52-
{
53-
average.Number++;
54-
average.Price = GetNewAverage(average.Price, average.Number, requestEvent.Request.Request.Ask.Reward);
55-
average.Size = GetNewAverage(average.Size, average.Number, requestEvent.Request.Request.Ask.SlotSize);
56-
average.Duration = GetNewAverage(average.Duration, average.Number, requestEvent.Request.Request.Ask.Duration);
57-
average.Collateral = GetNewAverage(average.Collateral, average.Number, requestEvent.Request.Request.Ask.Collateral);
58-
average.ProofProbability = GetNewAverage(average.ProofProbability, average.Number, requestEvent.Request.Request.Ask.ProofProbability);
59-
}
60-
61-
private float GetNewAverage(float currentAverage, int newNumberOfValues, BigInteger newValue)
62-
{
63-
return GetNewAverage(currentAverage, newNumberOfValues, (float)newValue);
38+
return Task.CompletedTask;
6439
}
6540

66-
private float GetNewAverage(float currentAverage, int newNumberOfValues, float newValue)
41+
private MarketTimeSegment BuildContribution(TimeRange timeRange)
6742
{
68-
return RollingAverage.GetNewAverage(currentAverage, newNumberOfValues, newValue);
43+
var builder = new ContributionBuilder(timeRange);
44+
mux.Handlers.Add(builder);
45+
chainState.Update(timeRange.To);
46+
mux.Handlers.Remove(builder);
47+
return builder.GetSegment();
6948
}
7049
}
7150
}

Tools/MarketInsights/Configuration.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,13 @@ public DateTime HistoryStartUtc
3333
return DateTimeOffset.FromUnixTimeSeconds(CheckHistoryTimestamp).UtcDateTime;
3434
}
3535
}
36+
37+
public TimeSpan UpdateInterval
38+
{
39+
get
40+
{
41+
return TimeSpan.FromMinutes(UpdateIntervalMinutes);
42+
}
43+
}
3644
}
3745
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using CodexContractsPlugin.ChainMonitor;
2+
using GethPlugin;
3+
using System.Numerics;
4+
using Utils;
5+
6+
namespace MarketInsights
7+
{
8+
public class ContributionBuilder : IChainStateChangeHandler
9+
{
10+
private readonly MarketTimeSegment segment = new MarketTimeSegment();
11+
12+
public ContributionBuilder(TimeRange timeRange)
13+
{
14+
segment = new MarketTimeSegment
15+
{
16+
FromUtc = timeRange.From,
17+
ToUtc = timeRange.To
18+
};
19+
}
20+
21+
public void OnNewRequest(RequestEvent requestEvent)
22+
{
23+
AddRequestToAverage(segment.Submitted, requestEvent);
24+
}
25+
26+
public void OnRequestCancelled(RequestEvent requestEvent)
27+
{
28+
AddRequestToAverage(segment.Expired, requestEvent);
29+
}
30+
31+
public void OnRequestFailed(RequestEvent requestEvent)
32+
{
33+
AddRequestToAverage(segment.Failed, requestEvent);
34+
}
35+
36+
public void OnRequestFinished(RequestEvent requestEvent)
37+
{
38+
AddRequestToAverage(segment.Finished, requestEvent);
39+
}
40+
41+
public void OnRequestFulfilled(RequestEvent requestEvent)
42+
{
43+
AddRequestToAverage(segment.Started, requestEvent);
44+
}
45+
46+
public void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex)
47+
{
48+
}
49+
50+
public void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex)
51+
{
52+
}
53+
54+
public MarketTimeSegment GetSegment()
55+
{
56+
return segment;
57+
}
58+
59+
private void AddRequestToAverage(ContractAverages average, RequestEvent requestEvent)
60+
{
61+
average.Number++;
62+
average.Price = GetNewAverage(average.Price, average.Number, requestEvent.Request.Request.Ask.Reward);
63+
average.Size = GetNewAverage(average.Size, average.Number, requestEvent.Request.Request.Ask.SlotSize);
64+
average.Duration = GetNewAverage(average.Duration, average.Number, requestEvent.Request.Request.Ask.Duration);
65+
average.Collateral = GetNewAverage(average.Collateral, average.Number, requestEvent.Request.Request.Ask.Collateral);
66+
average.ProofProbability = GetNewAverage(average.ProofProbability, average.Number, requestEvent.Request.Request.Ask.ProofProbability);
67+
}
68+
69+
private float GetNewAverage(float currentAverage, int newNumberOfValues, BigInteger newValue)
70+
{
71+
return GetNewAverage(currentAverage, newNumberOfValues, (float)newValue);
72+
}
73+
74+
private float GetNewAverage(float currentAverage, int newNumberOfValues, float newValue)
75+
{
76+
return RollingAverage.GetNewAverage(currentAverage, newNumberOfValues, newValue);
77+
}
78+
}
79+
}

Tools/MarketInsights/MarketInsights.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<ItemGroup>
2020
<ProjectReference Include="..\..\Framework\ArgsUniform\ArgsUniform.csproj" />
2121
<ProjectReference Include="..\..\ProjectPlugins\CodexContractsPlugin\CodexContractsPlugin.csproj" />
22+
<ProjectReference Include="..\TestNetRewarder\TestNetRewarder.csproj" />
2223
</ItemGroup>
2324

2425
</Project>

Tools/MarketInsights/Model.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ public class MarketOverview
77
/// </summary>
88
public DateTime LastUpdatedUtc { get; set; }
99

10+
/// <summary>
11+
/// When false, service is busy processing history in order to catch up to the present.
12+
/// </summary>
13+
public bool IsUpToDate { get; set; }
14+
1015
public MarketTimeSegment[] TimeSegments { get; set; } = Array.Empty<MarketTimeSegment>();
1116
}
1217

Tools/MarketInsights/Program.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using ArgsUniform;
22
using Microsoft.Extensions.Options;
3+
using Nethereum.Model;
34
using System.Reflection;
45

56
namespace MarketInsights
@@ -10,9 +11,20 @@ public static void Main(string[] args)
1011
{
1112
var uniformArgs = new ArgsUniform<Configuration>(PrintHelp, args);
1213
var config = uniformArgs.Parse(true);
13-
14+
var cts = new CancellationTokenSource();
1415
var appState = new AppState(config);
15-
var updater = new Updater(appState);
16+
17+
Console.CancelKeyPress += (s, e) =>
18+
{
19+
appState.Log.Log("Stopping...");
20+
cts.Cancel();
21+
e.Cancel = true;
22+
};
23+
24+
var connector = GethConnector.GethConnector.Initialize(appState.Log);
25+
if (connector == null) throw new Exception("Invalid Geth information");
26+
27+
var updater = new Updater(appState, connector.CodexContracts, cts.Token);
1628

1729
var builder = WebApplication.CreateBuilder(args);
1830

@@ -49,6 +61,14 @@ public static void Main(string[] args)
4961
private static void PrintHelp()
5062
{
5163
Console.WriteLine("WebAPI for generating market overview for Codex network. Comes with OpenAPI swagger endpoint.");
64+
65+
var nl = Environment.NewLine;
66+
Console.WriteLine($"Required environment variables: {nl}" +
67+
$"'GETH_HOST'{nl}",
68+
$"'GETH_HTTP_PORT'{nl}",
69+
$"'CODEXCONTRACTS_MARKETPLACEADDRESS'{nl}",
70+
$"'CODEXCONTRACTS_TOKENADDRESS'{nl}",
71+
$"'CODEXCONTRACTS_ABI'{nl}");
5272
}
5373
}
5474
}

Tools/MarketInsights/Tracker.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using CodexContractsPlugin.ChainMonitor;
2+
using Utils;
3+
using YamlDotNet.Core;
4+
5+
namespace MarketInsights
6+
{
7+
public class Tracker
8+
{
9+
private readonly AverageHistory history;
10+
11+
public Tracker(int numberOfSegments, AverageHistory history)
12+
{
13+
NumberOfSegments = numberOfSegments;
14+
this.history = history;
15+
}
16+
17+
public int NumberOfSegments { get; }
18+
19+
public MarketTimeSegment? CreateMarketTimeSegment()
20+
{
21+
if (history.Segments.Length < NumberOfSegments) return null;
22+
23+
var mySegments = history.Segments.TakeLast(NumberOfSegments);
24+
return AverageSegments(mySegments);
25+
}
26+
27+
private MarketTimeSegment AverageSegments(IEnumerable<MarketTimeSegment> mySegments)
28+
{
29+
var result = new MarketTimeSegment();
30+
31+
foreach (var segment in mySegments)
32+
{
33+
result.FromUtc = Min(result.FromUtc, segment.FromUtc);
34+
result.ToUtc = Max(result.ToUtc, segment.ToUtc);
35+
36+
Combine(result.Submitted, segment.Submitted);
37+
Combine(result.Expired, segment.Expired);
38+
Combine(result.Started, segment.Started);
39+
Combine(result.Finished, segment.Finished);
40+
Combine(result.Failed, segment.Failed);
41+
}
42+
return result;
43+
}
44+
45+
private void Combine(ContractAverages result, ContractAverages toAdd)
46+
{
47+
float weight1 = result.Number;
48+
float weight2 = toAdd.Number;
49+
50+
result.Price = RollingAverage.GetWeightedAverage(result.Price, weight1, toAdd.Price, weight2);
51+
result.Size = RollingAverage.GetWeightedAverage(result.Size, weight1, toAdd.Size, weight2);
52+
result.Duration = RollingAverage.GetWeightedAverage(result.Duration, weight1, toAdd.Duration, weight2);
53+
result.Collateral = RollingAverage.GetWeightedAverage(result.Collateral, weight1, toAdd.Collateral, weight2);
54+
result.ProofProbability = RollingAverage.GetWeightedAverage(result.ProofProbability, weight1, toAdd.ProofProbability, weight2);
55+
}
56+
57+
private DateTime Max(DateTime a, DateTime b)
58+
{
59+
if (a > b) return a;
60+
return b;
61+
}
62+
63+
private DateTime Min(DateTime a, DateTime b)
64+
{
65+
if (a > b) return b;
66+
return a;
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)