Merge branch 'feature/bot-upgrade'
This commit is contained in:
commit
605004286a
|
@ -4,6 +4,7 @@
|
|||
{
|
||||
public RewardUsersCommand[] Rewards { get; set; } = Array.Empty<RewardUsersCommand>();
|
||||
public MarketAverage[] Averages { get; set; } = Array.Empty<MarketAverage>();
|
||||
public string[] EventsOverview { get; set; } = Array.Empty<string>();
|
||||
}
|
||||
|
||||
public class RewardUsersCommand
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
using GethPlugin;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CodexContractsPlugin.Marketplace
|
||||
{
|
||||
public partial class Request : RequestBase
|
||||
{
|
||||
[JsonIgnore]
|
||||
public ulong BlockNumber { get; set; }
|
||||
public byte[] RequestId { get; set; }
|
||||
|
||||
|
@ -13,22 +15,26 @@ namespace CodexContractsPlugin.Marketplace
|
|||
|
||||
public partial class RequestFulfilledEventDTO
|
||||
{
|
||||
[JsonIgnore]
|
||||
public ulong BlockNumber { get; set; }
|
||||
}
|
||||
|
||||
public partial class RequestCancelledEventDTO
|
||||
{
|
||||
[JsonIgnore]
|
||||
public ulong BlockNumber { get; set; }
|
||||
}
|
||||
|
||||
public partial class SlotFilledEventDTO
|
||||
{
|
||||
[JsonIgnore]
|
||||
public ulong BlockNumber { get; set; }
|
||||
public EthAddress Host { get; set; }
|
||||
}
|
||||
|
||||
public partial class SlotFreedEventDTO
|
||||
{
|
||||
[JsonIgnore]
|
||||
public ulong BlockNumber { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,14 @@ namespace BiblioTech.Commands
|
|||
return;
|
||||
}
|
||||
|
||||
var eth = gethNode.GetEthBalance(addr);
|
||||
var testTokens = contracts.GetTestTokenBalance(addr);
|
||||
var eth = 0.Eth();
|
||||
var testTokens = 0.TestTokens();
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
eth = gethNode.GetEthBalance(addr);
|
||||
testTokens = contracts.GetTestTokenBalance(addr);
|
||||
});
|
||||
|
||||
await context.Followup($"{context.Command.User.Username} has {eth} and {testTokens}.");
|
||||
}
|
||||
|
|
|
@ -33,8 +33,14 @@ namespace BiblioTech.Commands
|
|||
|
||||
var report = new List<string>();
|
||||
|
||||
var sentEth = ProcessEth(gethNode, addr, report);
|
||||
var mintedTokens = ProcessTokens(contracts, addr, report);
|
||||
Transaction<Ether>? sentEth = null;
|
||||
Transaction<TestToken>? mintedTokens = null;
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
sentEth = ProcessEth(gethNode, addr, report);
|
||||
mintedTokens = ProcessTokens(contracts, addr, report);
|
||||
});
|
||||
|
||||
Program.UserRepo.AddMintEventForUser(userId, addr, sentEth, mintedTokens);
|
||||
|
||||
|
|
|
@ -22,6 +22,9 @@ namespace BiblioTech
|
|||
[Uniform("rewards-channel-name", "rc", "REWARDSCHANNELNAME", false, "Name of the Discord server channel where participation rewards will be announced.")]
|
||||
public string RewardsChannelName { get; set; } = "";
|
||||
|
||||
[Uniform("chain-events-channel-name", "cc", "CHAINEVENTSCHANNELNAME", false, "Name of the Discord server channel where chain events will be posted.")]
|
||||
public string ChainEventsChannelName { get; set; } = "";
|
||||
|
||||
[Uniform("reward-api-port", "rp", "REWARDAPIPORT", false, "TCP listen port for the reward API.")]
|
||||
public int RewardApiPort { get; set; } = 31080;
|
||||
|
||||
|
|
|
@ -9,16 +9,15 @@ namespace BiblioTech.Rewards
|
|||
{
|
||||
private readonly DiscordSocketClient client;
|
||||
private readonly SocketTextChannel? rewardsChannel;
|
||||
private readonly SocketTextChannel? eventsChannel;
|
||||
private readonly RewardRepo repo = new RewardRepo();
|
||||
|
||||
public RoleDriver(DiscordSocketClient client)
|
||||
{
|
||||
this.client = client;
|
||||
|
||||
if (!string.IsNullOrEmpty(Program.Config.RewardsChannelName))
|
||||
{
|
||||
rewardsChannel = GetGuild().TextChannels.SingleOrDefault(c => c.Name == Program.Config.RewardsChannelName);
|
||||
}
|
||||
rewardsChannel = GetChannel(Program.Config.RewardsChannelName);
|
||||
eventsChannel = GetChannel(Program.Config.ChainEventsChannelName);
|
||||
}
|
||||
|
||||
public async Task GiveRewards(GiveRewardsCommand rewards)
|
||||
|
@ -34,6 +33,22 @@ namespace BiblioTech.Rewards
|
|||
rewardsChannel);
|
||||
|
||||
await context.ProcessGiveRewardsCommand(LookUpUsers(rewards));
|
||||
await ProcessChainEvents(rewards.EventsOverview);
|
||||
}
|
||||
|
||||
private SocketTextChannel? GetChannel(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return null;
|
||||
return GetGuild().TextChannels.SingleOrDefault(c => c.Name == name);
|
||||
}
|
||||
|
||||
private async Task ProcessChainEvents(string[] eventsOverview)
|
||||
{
|
||||
if (eventsChannel == null || eventsOverview == null || !eventsOverview.Any()) return;
|
||||
foreach (var e in eventsOverview)
|
||||
{
|
||||
await eventsChannel.SendMessageAsync(e);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Dictionary<ulong, IGuildUser>> LoadAllUsers(SocketGuild guild)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using CodexContractsPlugin;
|
||||
using CodexContractsPlugin.Marketplace;
|
||||
using Newtonsoft.Json;
|
||||
using Utils;
|
||||
|
||||
namespace TestNetRewarder
|
||||
|
@ -11,11 +12,13 @@ namespace TestNetRewarder
|
|||
public ChainState(HistoricState historicState, ICodexContracts contracts, BlockInterval blockRange)
|
||||
{
|
||||
NewRequests = contracts.GetStorageRequests(blockRange);
|
||||
historicState.CleanUpOldRequests();
|
||||
historicState.ProcessNewRequests(NewRequests);
|
||||
historicState.UpdateStorageRequests(contracts);
|
||||
|
||||
StartedRequests = historicState.StorageRequests.Where(r => r.RecentlyStarted).ToArray();
|
||||
FinishedRequests = historicState.StorageRequests.Where(r => r.RecentlyFinished).ToArray();
|
||||
ChangedRequests = historicState.StorageRequests.Where(r => r.RecentlyChanged).ToArray();
|
||||
RequestFulfilledEvents = contracts.GetRequestFulfilledEvents(blockRange);
|
||||
RequestCancelledEvents = contracts.GetRequestCancelledEvents(blockRange);
|
||||
SlotFilledEvents = contracts.GetSlotFilledEvents(blockRange);
|
||||
|
@ -27,9 +30,78 @@ namespace TestNetRewarder
|
|||
public StorageRequest[] AllRequests => historicState.StorageRequests;
|
||||
public StorageRequest[] StartedRequests { get; private set; }
|
||||
public StorageRequest[] FinishedRequests { get; private set; }
|
||||
public StorageRequest[] ChangedRequests { get; private set; }
|
||||
public RequestFulfilledEventDTO[] RequestFulfilledEvents { get; }
|
||||
public RequestCancelledEventDTO[] RequestCancelledEvents { get; }
|
||||
public SlotFilledEventDTO[] SlotFilledEvents { get; }
|
||||
public SlotFreedEventDTO[] SlotFreedEvents { get; }
|
||||
|
||||
public string[] GenerateOverview()
|
||||
{
|
||||
var entries = new List<StringBlockNumberPair>();
|
||||
|
||||
entries.AddRange(ChangedRequests.Select(ToPair));
|
||||
entries.AddRange(RequestFulfilledEvents.Select(ToPair));
|
||||
entries.AddRange(RequestCancelledEvents.Select(ToPair));
|
||||
entries.AddRange(SlotFilledEvents.Select(ToPair));
|
||||
entries.AddRange(SlotFreedEvents.Select(ToPair));
|
||||
|
||||
entries.Sort(new StringUtcComparer());
|
||||
|
||||
return entries.Select(ToLine).ToArray();
|
||||
}
|
||||
|
||||
private StringBlockNumberPair ToPair(StorageRequest r)
|
||||
{
|
||||
return new StringBlockNumberPair(JsonConvert.SerializeObject(r), r.Request.BlockNumber);
|
||||
}
|
||||
|
||||
private StringBlockNumberPair ToPair(RequestFulfilledEventDTO r)
|
||||
{
|
||||
return new StringBlockNumberPair(JsonConvert.SerializeObject(r), r.BlockNumber);
|
||||
}
|
||||
|
||||
private StringBlockNumberPair ToPair(RequestCancelledEventDTO r)
|
||||
{
|
||||
return new StringBlockNumberPair(JsonConvert.SerializeObject(r), r.BlockNumber);
|
||||
}
|
||||
|
||||
private StringBlockNumberPair ToPair(SlotFilledEventDTO r)
|
||||
{
|
||||
return new StringBlockNumberPair(JsonConvert.SerializeObject(r), r.BlockNumber);
|
||||
}
|
||||
|
||||
private StringBlockNumberPair ToPair(SlotFreedEventDTO r)
|
||||
{
|
||||
return new StringBlockNumberPair(JsonConvert.SerializeObject(r), r.BlockNumber);
|
||||
}
|
||||
|
||||
private string ToLine(StringBlockNumberPair pair)
|
||||
{
|
||||
return $"[{pair.Number}] {pair.Str}";
|
||||
}
|
||||
|
||||
public class StringBlockNumberPair
|
||||
{
|
||||
public StringBlockNumberPair(string str, ulong number)
|
||||
{
|
||||
Str = str;
|
||||
Number = number;
|
||||
}
|
||||
|
||||
public string Str { get; }
|
||||
public ulong Number { get; }
|
||||
}
|
||||
|
||||
public class StringUtcComparer : IComparer<StringBlockNumberPair>
|
||||
{
|
||||
public int Compare(StringBlockNumberPair? x, StringBlockNumberPair? y)
|
||||
{
|
||||
if (x == null && y == null) return 0;
|
||||
if (x == null) return 1;
|
||||
if (y == null) return -1;
|
||||
return x.Number.CompareTo(y.Number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ namespace TestNetRewarder
|
|||
[Uniform("market-insights", "mi", "MARKETINSIGHTS", false, "Semi-colon separated integers. Each represents a multiple of intervals, for which a market insights average will be generated.")]
|
||||
public string MarketInsights { get; set; } = "1;96";
|
||||
|
||||
[Uniform("events-overview", "eo", "EVENTSOVERVIEW", false, "When greater than zero, chain event summary will be generated. (default 1)")]
|
||||
public int CreateChainEventsOverview { get; set; } = 1;
|
||||
|
||||
public string LogPath
|
||||
{
|
||||
get
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using CodexContractsPlugin;
|
||||
using CodexContractsPlugin.Marketplace;
|
||||
using GethPlugin;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace TestNetRewarder
|
||||
{
|
||||
|
@ -19,6 +20,17 @@ namespace TestNetRewarder
|
|||
{
|
||||
foreach (var r in storageRequests) r.Update(contracts);
|
||||
}
|
||||
|
||||
public void CleanUpOldRequests()
|
||||
{
|
||||
storageRequests.RemoveAll(r =>
|
||||
r.State == RequestState.Cancelled ||
|
||||
r.State == RequestState.Finished ||
|
||||
r.State == RequestState.Failed
|
||||
);
|
||||
|
||||
foreach (var r in storageRequests) r.IsNew = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class StorageRequest
|
||||
|
@ -27,17 +39,26 @@ namespace TestNetRewarder
|
|||
{
|
||||
Request = request;
|
||||
Hosts = Array.Empty<EthAddress>();
|
||||
IsNew = true;
|
||||
}
|
||||
|
||||
public Request Request { get; }
|
||||
public EthAddress[] Hosts { get; private set; }
|
||||
public RequestState State { get; private set; }
|
||||
public bool IsNew { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool RecentlyStarted { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool RecentlyFinished { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool RecentlyChanged { get; private set; }
|
||||
|
||||
public void Update(ICodexContracts contracts)
|
||||
{
|
||||
Hosts = GetHosts(contracts);
|
||||
var newHosts = GetHosts(contracts);
|
||||
|
||||
var newState = contracts.GetRequestState(Request);
|
||||
|
||||
|
@ -49,7 +70,25 @@ namespace TestNetRewarder
|
|||
State == RequestState.Started &&
|
||||
newState == RequestState.Finished;
|
||||
|
||||
RecentlyChanged =
|
||||
IsNew ||
|
||||
State != newState ||
|
||||
HostsChanged(newHosts);
|
||||
|
||||
State = newState;
|
||||
Hosts = newHosts;
|
||||
}
|
||||
|
||||
private bool HostsChanged(EthAddress[] newHosts)
|
||||
{
|
||||
if (newHosts.Length != Hosts.Length) return true;
|
||||
|
||||
foreach (var newHost in newHosts)
|
||||
{
|
||||
if (!Hosts.Contains(newHost)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private EthAddress[] GetHosts(ICodexContracts contracts)
|
||||
|
|
|
@ -65,29 +65,36 @@ namespace TestNetRewarder
|
|||
}
|
||||
|
||||
var marketAverages = GetMarketAverages(chainState);
|
||||
var eventsOverview = GenerateEventsOverview(chainState);
|
||||
|
||||
log.Log($"Found {outgoingRewards.Count} rewards to send. Found {marketAverages.Length} market averages.");
|
||||
|
||||
if (outgoingRewards.Any())
|
||||
{
|
||||
if (!await SendRewardsCommand(outgoingRewards, marketAverages))
|
||||
if (!await SendRewardsCommand(outgoingRewards, marketAverages, eventsOverview))
|
||||
{
|
||||
log.Error("Failed to send reward command.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string[] GenerateEventsOverview(ChainState chainState)
|
||||
{
|
||||
return chainState.GenerateOverview();
|
||||
}
|
||||
|
||||
private MarketAverage[] GetMarketAverages(ChainState chainState)
|
||||
{
|
||||
return marketTracker.ProcessChainState(chainState);
|
||||
}
|
||||
|
||||
private async Task<bool> SendRewardsCommand(List<RewardUsersCommand> outgoingRewards, MarketAverage[] marketAverages)
|
||||
private async Task<bool> SendRewardsCommand(List<RewardUsersCommand> outgoingRewards, MarketAverage[] marketAverages, string[] eventsOverview)
|
||||
{
|
||||
var cmd = new GiveRewardsCommand
|
||||
{
|
||||
Rewards = outgoingRewards.ToArray(),
|
||||
Averages = marketAverages.ToArray()
|
||||
Averages = marketAverages.ToArray(),
|
||||
EventsOverview = eventsOverview
|
||||
};
|
||||
|
||||
log.Debug("Sending rewards: " + JsonConvert.SerializeObject(cmd));
|
||||
|
|
Loading…
Reference in New Issue