2
0
mirror of synced 2025-02-22 04:58:19 +00:00

Merge branch 'master' into feature/bot-upgrade

This commit is contained in:
Ben 2024-04-22 14:03:51 +02:00
commit d3390892af
No known key found for this signature in database
GPG Key ID: 541B9D8C9F1426A1
13 changed files with 119 additions and 33 deletions

View File

@ -16,7 +16,7 @@
public class MarketAverage public class MarketAverage
{ {
public int NumberOfFinished { get; set; } public int NumberOfFinished { get; set; }
public TimeSpan TimeRange { get; set; } public int TimeRangeSeconds { get; set; }
public float Price { get; set; } public float Price { get; set; }
public float Size { get; set; } public float Size { get; set; }
public float Duration { get; set; } public float Duration { get; set; }

View File

@ -18,6 +18,13 @@ namespace NethereumWorkflow.BlockUtils
bounds = new BlockchainBounds(cache, web3); bounds = new BlockchainBounds(cache, web3);
} }
public BlockTimeEntry Get(ulong blockNumber)
{
var b = cache.Get(blockNumber);
if (b != null) return b;
return GetBlock(blockNumber);
}
public ulong? GetHighestBlockNumberBefore(DateTime moment) public ulong? GetHighestBlockNumberBefore(DateTime moment)
{ {
bounds.Initialize(); bounds.Initialize();

View File

@ -121,5 +121,12 @@ namespace NethereumWorkflow
to: toBlock.Value to: toBlock.Value
); );
} }
public BlockTimeEntry GetBlockForNumber(ulong number)
{
var wrapper = new Web3Wrapper(web3, log);
var blockTimeFinder = new BlockTimeFinder(blockCache, wrapper, log);
return blockTimeFinder.Get(number);
}
} }
} }

View File

@ -5,6 +5,7 @@ using Nethereum.ABI;
using Nethereum.Hex.HexTypes; using Nethereum.Hex.HexTypes;
using Nethereum.Util; using Nethereum.Util;
using NethereumWorkflow; using NethereumWorkflow;
using NethereumWorkflow.BlockUtils;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using Utils; using Utils;
@ -89,7 +90,7 @@ namespace CodexContractsPlugin
{ {
var requestEvent = i.GetRequest(Deployment.MarketplaceAddress, e.Event.RequestId); var requestEvent = i.GetRequest(Deployment.MarketplaceAddress, e.Event.RequestId);
var result = requestEvent.ReturnValue1; var result = requestEvent.ReturnValue1;
result.BlockNumber = e.Log.BlockNumber.ToUlong(); result.Block = GetBlock(e.Log.BlockNumber.ToUlong());
result.RequestId = e.Event.RequestId; result.RequestId = e.Event.RequestId;
return result; return result;
}) })
@ -102,7 +103,7 @@ namespace CodexContractsPlugin
return events.Select(e => return events.Select(e =>
{ {
var result = e.Event; var result = e.Event;
result.BlockNumber = e.Log.BlockNumber.ToUlong(); result.Block = GetBlock(e.Log.BlockNumber.ToUlong());
return result; return result;
}).ToArray(); }).ToArray();
} }
@ -113,7 +114,7 @@ namespace CodexContractsPlugin
return events.Select(e => return events.Select(e =>
{ {
var result = e.Event; var result = e.Event;
result.BlockNumber = e.Log.BlockNumber.ToUlong(); result.Block = GetBlock(e.Log.BlockNumber.ToUlong());
return result; return result;
}).ToArray(); }).ToArray();
} }
@ -124,7 +125,7 @@ namespace CodexContractsPlugin
return events.Select(e => return events.Select(e =>
{ {
var result = e.Event; var result = e.Event;
result.BlockNumber = e.Log.BlockNumber.ToUlong(); result.Block = GetBlock(e.Log.BlockNumber.ToUlong());
result.Host = GetEthAddressFromTransaction(e.Log.TransactionHash); result.Host = GetEthAddressFromTransaction(e.Log.TransactionHash);
return result; return result;
}).ToArray(); }).ToArray();
@ -136,7 +137,7 @@ namespace CodexContractsPlugin
return events.Select(e => return events.Select(e =>
{ {
var result = e.Event; var result = e.Event;
result.BlockNumber = e.Log.BlockNumber.ToUlong(); result.Block = GetBlock(e.Log.BlockNumber.ToUlong());
return result; return result;
}).ToArray(); }).ToArray();
} }
@ -169,6 +170,11 @@ namespace CodexContractsPlugin
return gethNode.Call<RequestStateFunction, RequestState>(Deployment.MarketplaceAddress, func); return gethNode.Call<RequestStateFunction, RequestState>(Deployment.MarketplaceAddress, func);
} }
private BlockTimeEntry GetBlock(ulong number)
{
return gethNode.GetBlockForNumber(number);
}
private EthAddress GetEthAddressFromTransaction(string transactionHash) private EthAddress GetEthAddressFromTransaction(string transactionHash)
{ {
var transaction = gethNode.GetTransaction(transactionHash); var transaction = gethNode.GetTransaction(transactionHash);

View File

@ -1,5 +1,6 @@
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
using GethPlugin; using GethPlugin;
using NethereumWorkflow.BlockUtils;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace CodexContractsPlugin.Marketplace namespace CodexContractsPlugin.Marketplace
@ -7,7 +8,7 @@ namespace CodexContractsPlugin.Marketplace
public partial class Request : RequestBase public partial class Request : RequestBase
{ {
[JsonIgnore] [JsonIgnore]
public ulong BlockNumber { get; set; } public BlockTimeEntry Block { get; set; }
public byte[] RequestId { get; set; } public byte[] RequestId { get; set; }
public EthAddress ClientAddress { get { return new EthAddress(Client); } } public EthAddress ClientAddress { get { return new EthAddress(Client); } }
@ -16,26 +17,26 @@ namespace CodexContractsPlugin.Marketplace
public partial class RequestFulfilledEventDTO public partial class RequestFulfilledEventDTO
{ {
[JsonIgnore] [JsonIgnore]
public ulong BlockNumber { get; set; } public BlockTimeEntry Block { get; set; }
} }
public partial class RequestCancelledEventDTO public partial class RequestCancelledEventDTO
{ {
[JsonIgnore] [JsonIgnore]
public ulong BlockNumber { get; set; } public BlockTimeEntry Block { get; set; }
} }
public partial class SlotFilledEventDTO public partial class SlotFilledEventDTO
{ {
[JsonIgnore] [JsonIgnore]
public ulong BlockNumber { get; set; } public BlockTimeEntry Block { get; set; }
public EthAddress Host { get; set; } public EthAddress Host { get; set; }
} }
public partial class SlotFreedEventDTO public partial class SlotFreedEventDTO
{ {
[JsonIgnore] [JsonIgnore]
public ulong BlockNumber { get; set; } public BlockTimeEntry Block { get; set; }
} }
} }
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

View File

@ -5,6 +5,7 @@ using Nethereum.ABI.FunctionEncoding.Attributes;
using Nethereum.Contracts; using Nethereum.Contracts;
using Nethereum.RPC.Eth.DTOs; using Nethereum.RPC.Eth.DTOs;
using NethereumWorkflow; using NethereumWorkflow;
using NethereumWorkflow.BlockUtils;
using Utils; using Utils;
namespace GethPlugin namespace GethPlugin
@ -27,6 +28,7 @@ namespace GethPlugin
List<EventLog<TEvent>> GetEvents<TEvent>(string address, BlockInterval blockRange) where TEvent : IEventDTO, new(); List<EventLog<TEvent>> GetEvents<TEvent>(string address, BlockInterval blockRange) where TEvent : IEventDTO, new();
List<EventLog<TEvent>> GetEvents<TEvent>(string address, TimeRange timeRange) where TEvent : IEventDTO, new(); List<EventLog<TEvent>> GetEvents<TEvent>(string address, TimeRange timeRange) where TEvent : IEventDTO, new();
BlockInterval ConvertTimeRangeToBlockRange(TimeRange timeRange); BlockInterval ConvertTimeRangeToBlockRange(TimeRange timeRange);
BlockTimeEntry GetBlockForNumber(ulong number);
} }
public class DeploymentGethNode : BaseGethNode, IGethNode public class DeploymentGethNode : BaseGethNode, IGethNode
@ -160,6 +162,11 @@ namespace GethPlugin
return StartInteraction().ConvertTimeRangeToBlockRange(timeRange); return StartInteraction().ConvertTimeRangeToBlockRange(timeRange);
} }
public BlockTimeEntry GetBlockForNumber(ulong number)
{
return StartInteraction().GetBlockForNumber(number);
}
protected abstract NethereumInteraction StartInteraction(); protected abstract NethereumInteraction StartInteraction();
} }
} }

View File

@ -31,7 +31,8 @@ namespace BiblioTech.Commands
private string[] GetInsight(MarketAverage avg) private string[] GetInsight(MarketAverage avg)
{ {
var headerLine = $"[Last {Time.FormatDuration(avg.TimeRange)}] ({avg.NumberOfFinished} Contracts finished)"; var timeRange = TimeSpan.FromSeconds(avg.TimeRangeSeconds);
var headerLine = $"[Last {Time.FormatDuration(timeRange)}] ({avg.NumberOfFinished} Contracts finished)";
if (avg.NumberOfFinished == 0) if (avg.NumberOfFinished == 0)
{ {

View File

@ -23,7 +23,10 @@ namespace BiblioTech.Rewards
{ {
try try
{ {
Program.Averages = cmd.Averages; if (cmd.Averages != null && cmd.Averages.Any())
{
Program.Averages = cmd.Averages;
}
await Program.RoleDriver.GiveRewards(cmd); await Program.RoleDriver.GiveRewards(cmd);
} }
catch (Exception ex) catch (Exception ex)

View File

@ -24,6 +24,16 @@ namespace BiblioTech.Rewards
{ {
Program.Log.Log($"Processing rewards command: '{JsonConvert.SerializeObject(rewards)}'"); Program.Log.Log($"Processing rewards command: '{JsonConvert.SerializeObject(rewards)}'");
if (rewards.Rewards.Any())
{
await ProcessRewards(rewards);
}
await ProcessChainEvents(rewards.EventsOverview);
}
private async Task ProcessRewards(GiveRewardsCommand rewards)
{
var guild = GetGuild(); var guild = GetGuild();
// We load all role and user information first, // We load all role and user information first,
// so we don't ask the server for the same info multiple times. // so we don't ask the server for the same info multiple times.
@ -33,7 +43,6 @@ namespace BiblioTech.Rewards
rewardsChannel); rewardsChannel);
await context.ProcessGiveRewardsCommand(LookUpUsers(rewards)); await context.ProcessGiveRewardsCommand(LookUpUsers(rewards));
await ProcessChainEvents(rewards.EventsOverview);
} }
private SocketTextChannel? GetChannel(string name) private SocketTextChannel? GetChannel(string name)

View File

@ -1,7 +1,5 @@
using CodexContractsPlugin.Marketplace; using DiscordRewards;
using DiscordRewards;
using Logging; using Logging;
using Newtonsoft.Json;
using System.Net.Http.Json; using System.Net.Http.Json;
namespace TestNetRewarder namespace TestNetRewarder
@ -26,7 +24,7 @@ namespace TestNetRewarder
public async Task<bool> SendRewards(GiveRewardsCommand command) public async Task<bool> SendRewards(GiveRewardsCommand command)
{ {
if (command == null || command.Rewards == null || !command.Rewards.Any()) return false; if (command == null) return false;
var result = await HttpPostJson(command); var result = await HttpPostJson(command);
log.Log("Reward response: " + result); log.Log("Reward response: " + result);
return result == "OK"; return result == "OK";

View File

@ -1,5 +1,6 @@
using CodexContractsPlugin; using CodexContractsPlugin;
using CodexContractsPlugin.Marketplace; using CodexContractsPlugin.Marketplace;
using NethereumWorkflow.BlockUtils;
using Newtonsoft.Json; using Newtonsoft.Json;
using Utils; using Utils;
@ -8,6 +9,29 @@ namespace TestNetRewarder
public class ChainState public class ChainState
{ {
private readonly HistoricState historicState; private readonly HistoricState historicState;
private readonly string[] colorIcons = new[]
{
"🔴",
"🟠",
"🟡",
"🟢",
"🔵",
"🟣",
"🟤",
"⚫",
"⚪",
"🟥",
"🟧",
"🟨",
"🟩",
"🟦",
"🟪",
"🟫",
"⬛",
"⬜",
"🔶",
"🔷"
};
public ChainState(HistoricState historicState, ICodexContracts contracts, BlockInterval blockRange) public ChainState(HistoricState historicState, ICodexContracts contracts, BlockInterval blockRange)
{ {
@ -44,6 +68,7 @@ namespace TestNetRewarder
entries.AddRange(RequestCancelledEvents.Select(ToPair)); entries.AddRange(RequestCancelledEvents.Select(ToPair));
entries.AddRange(SlotFilledEvents.Select(ToPair)); entries.AddRange(SlotFilledEvents.Select(ToPair));
entries.AddRange(SlotFreedEvents.Select(ToPair)); entries.AddRange(SlotFreedEvents.Select(ToPair));
entries.AddRange(FinishedRequests.Select(ToPair));
entries.Sort(new StringUtcComparer()); entries.Sort(new StringUtcComparer());
@ -52,46 +77,64 @@ namespace TestNetRewarder
private StringBlockNumberPair ToPair(Request r) private StringBlockNumberPair ToPair(Request r)
{ {
return new StringBlockNumberPair("NewRequest", JsonConvert.SerializeObject(r), r.BlockNumber); return new StringBlockNumberPair("NewRequest", JsonConvert.SerializeObject(r), r.Block, r.RequestId);
}
public StringBlockNumberPair ToPair(StorageRequest r)
{
return new StringBlockNumberPair("FinishedRequest", JsonConvert.SerializeObject(r), r.Request.Block, r.Request.RequestId);
} }
private StringBlockNumberPair ToPair(RequestFulfilledEventDTO r) private StringBlockNumberPair ToPair(RequestFulfilledEventDTO r)
{ {
return new StringBlockNumberPair("Fulfilled", JsonConvert.SerializeObject(r), r.BlockNumber); return new StringBlockNumberPair("Fulfilled", JsonConvert.SerializeObject(r), r.Block, r.RequestId);
} }
private StringBlockNumberPair ToPair(RequestCancelledEventDTO r) private StringBlockNumberPair ToPair(RequestCancelledEventDTO r)
{ {
return new StringBlockNumberPair("Cancelled", JsonConvert.SerializeObject(r), r.BlockNumber); return new StringBlockNumberPair("Cancelled", JsonConvert.SerializeObject(r), r.Block, r.RequestId);
} }
private StringBlockNumberPair ToPair(SlotFilledEventDTO r) private StringBlockNumberPair ToPair(SlotFilledEventDTO r)
{ {
return new StringBlockNumberPair("SlotFilled", JsonConvert.SerializeObject(r), r.BlockNumber); return new StringBlockNumberPair("SlotFilled", JsonConvert.SerializeObject(r), r.Block, r.RequestId);
} }
private StringBlockNumberPair ToPair(SlotFreedEventDTO r) private StringBlockNumberPair ToPair(SlotFreedEventDTO r)
{ {
return new StringBlockNumberPair("SlotFreed", JsonConvert.SerializeObject(r), r.BlockNumber); return new StringBlockNumberPair("SlotFreed", JsonConvert.SerializeObject(r), r.Block, r.RequestId);
} }
private string ToLine(StringBlockNumberPair pair) private string ToLine(StringBlockNumberPair pair)
{ {
return $"[{pair.Number}]({pair.Name}) {pair.Str}"; var nl = Environment.NewLine;
var colorIcon = GetColorIcon(pair.RequestId);
return $"{colorIcon} {pair.Block} ({pair.Name}){nl}" +
$"```json{nl}" +
$"{pair.Str}{nl}" +
$"```";
}
private string GetColorIcon(byte[] requestId)
{
var index = requestId[0] % colorIcons.Length;
return colorIcons[index];
} }
public class StringBlockNumberPair public class StringBlockNumberPair
{ {
public StringBlockNumberPair(string name, string str, ulong number) public StringBlockNumberPair(string name, string str, BlockTimeEntry block, byte[] requestId)
{ {
Name = name; Name = name;
Str = str; Str = str;
Number = number; Block = block;
RequestId = requestId;
} }
public string Name { get; } public string Name { get; }
public string Str { get; } public string Str { get; }
public ulong Number { get; } public BlockTimeEntry Block { get; }
public byte[] RequestId { get; }
} }
public class StringUtcComparer : IComparer<StringBlockNumberPair> public class StringUtcComparer : IComparer<StringBlockNumberPair>
@ -101,7 +144,7 @@ namespace TestNetRewarder
if (x == null && y == null) return 0; if (x == null && y == null) return 0;
if (x == null) return 1; if (x == null) return 1;
if (y == null) return -1; if (y == null) return -1;
return x.Number.CompareTo(y.Number); return x.Block.BlockNumber.CompareTo(y.Block.BlockNumber);
} }
} }
} }

View File

@ -42,6 +42,7 @@ namespace TestNetRewarder
private ChainState[] SelectStates(int numberOfIntervals) private ChainState[] SelectStates(int numberOfIntervals)
{ {
if (numberOfIntervals < 1) return Array.Empty<ChainState>(); if (numberOfIntervals < 1) return Array.Empty<ChainState>();
if (numberOfIntervals > buffer.Count) return Array.Empty<ChainState>();
return buffer.TakeLast(numberOfIntervals).ToArray(); return buffer.TakeLast(numberOfIntervals).ToArray();
} }
@ -52,7 +53,7 @@ namespace TestNetRewarder
return new MarketAverage return new MarketAverage
{ {
NumberOfFinished = CountNumberOfFinishedRequests(states), NumberOfFinished = CountNumberOfFinishedRequests(states),
TimeRange = GetTotalTimeRange(states), TimeRangeSeconds = GetTotalTimeRange(states),
Price = Average(states, s => s.Request.Ask.Reward), Price = Average(states, s => s.Request.Ask.Reward),
Duration = Average(states, s => s.Request.Ask.Duration), Duration = Average(states, s => s.Request.Ask.Duration),
Size = Average(states, s => GetTotalSize(s.Request.Ask)), Size = Average(states, s => GetTotalSize(s.Request.Ask)),
@ -92,12 +93,13 @@ namespace TestNetRewarder
} }
} }
if (count < 1.0f) return 0.0f;
return sum / count; return sum / count;
} }
private TimeSpan GetTotalTimeRange(ChainState[] states) private int GetTotalTimeRange(ChainState[] states)
{ {
return Program.Config.Interval * states.Length; return Convert.ToInt32((Program.Config.Interval * states.Length).TotalSeconds);
} }
private int CountNumberOfFinishedRequests(ChainState[] states) private int CountNumberOfFinishedRequests(ChainState[] states)

View File

@ -67,9 +67,11 @@ namespace TestNetRewarder
var marketAverages = GetMarketAverages(chainState); var marketAverages = GetMarketAverages(chainState);
var eventsOverview = GenerateEventsOverview(chainState); var eventsOverview = GenerateEventsOverview(chainState);
log.Log($"Found {outgoingRewards.Count} rewards to send. Found {marketAverages.Length} market averages."); log.Log($"Found {outgoingRewards.Count} rewards. " +
$"Found {marketAverages.Length} market averages. " +
$"Found {eventsOverview.Length} events.");
if (outgoingRewards.Any()) if (outgoingRewards.Any() || marketAverages.Any() || eventsOverview.Any())
{ {
if (!await SendRewardsCommand(outgoingRewards, marketAverages, eventsOverview)) if (!await SendRewardsCommand(outgoingRewards, marketAverages, eventsOverview))
{ {