/ ProjectPlugins / GethPlugin / GethNode.cs
GethNode.cs
  1  using BlockchainUtils;
  2  using Core;
  3  using KubernetesWorkflow.Types;
  4  using Logging;
  5  using Nethereum.ABI.FunctionEncoding.Attributes;
  6  using Nethereum.BlockchainProcessing.BlockStorage.Entities.Mapping;
  7  using Nethereum.Contracts;
  8  using Nethereum.RPC.Eth.DTOs;
  9  using NethereumWorkflow;
 10  using Utils;
 11  
 12  namespace GethPlugin
 13  {
 14      public interface IGethNode : IHasContainer
 15      {
 16          GethDeployment StartResult { get; }
 17          EthAddress CurrentAddress { get; }
 18  
 19          Ether GetEthBalance();
 20          Ether GetEthBalance(IHasEthAddress address);
 21          Ether GetEthBalance(EthAddress address);
 22          string SendEth(IHasEthAddress account, Ether eth);
 23          string SendEth(EthAddress account, Ether eth);
 24          TResult Call<TFunction, TResult>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new();
 25          TResult Call<TFunction, TResult>(string contractAddress, TFunction function, ulong blockNumber) where TFunction : FunctionMessage, new();
 26          void Call<TFunction>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new();
 27          void Call<TFunction>(string contractAddress, TFunction function, ulong blockNumber) where TFunction : FunctionMessage, new();
 28          string SendTransaction<TFunction>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new();
 29          Transaction GetTransaction(string transactionHash);
 30          decimal? GetSyncedBlockNumber();
 31          bool IsContractAvailable(string abi, string contractAddress);
 32          GethBootstrapNode GetBootstrapRecord();
 33          List<EventLog<TEvent>> GetEvents<TEvent>(string address, BlockInterval blockRange) where TEvent : IEventDTO, new();
 34          List<EventLog<TEvent>> GetEvents<TEvent>(string address, TimeRange timeRange) where TEvent : IEventDTO, new();
 35          BlockInterval ConvertTimeRangeToBlockRange(TimeRange timeRange);
 36          BlockTimeEntry GetBlockForNumber(ulong number);
 37          void IterateTransactions(BlockInterval blockRange, Action<Transaction, ulong, DateTime> action);
 38          void IterateFunctionCalls<TFunc>(BlockInterval blockInterval, Action<BlockTimeEntry, TFunc> onCall) where TFunc : FunctionMessage, new();
 39          IGethNode WithDifferentAccount(EthAccount account);
 40      }
 41  
 42      public class DeploymentGethNode : BaseGethNode, IGethNode
 43      {
 44          private readonly ILog log;
 45          private readonly BlockCache blockCache;
 46  
 47          public DeploymentGethNode(ILog log, BlockCache blockCache, GethDeployment startResult)
 48          {
 49              this.log = log;
 50              this.blockCache = blockCache;
 51              StartResult = startResult;
 52              CurrentAddress = new EthAddress(startResult.Account.Account);
 53          }
 54  
 55          public GethDeployment StartResult { get; }
 56          public RunningContainer Container => StartResult.Container;
 57          public EthAddress CurrentAddress { get; }
 58  
 59          public GethBootstrapNode GetBootstrapRecord()
 60          {
 61              var address = StartResult.Container.GetInternalAddress(GethContainerRecipe.ListenPortTag);
 62  
 63              return new GethBootstrapNode(
 64                  publicKey: StartResult.PubKey,
 65                  ipAddress: address.Host.Replace("http://", ""),
 66                  port: address.Port
 67              );
 68          }
 69  
 70          protected override NethereumInteraction StartInteraction()
 71          {
 72              var address = StartResult.Container.GetAddress(GethContainerRecipe.HttpPortTag);
 73              var account = StartResult.Account;
 74  
 75              var creator = new NethereumInteractionCreator(log, blockCache, address.Host, address.Port, account.PrivateKey);
 76              return creator.CreateWorkflow();
 77          }
 78  
 79          public IGethNode WithDifferentAccount(EthAccount account)
 80          {
 81              return new DeploymentGethNode(log, blockCache,
 82                  new GethDeployment(
 83                      StartResult.Pod,
 84                      StartResult.DiscoveryPort,
 85                      StartResult.HttpPort,
 86                      StartResult.WsPort,
 87                      new GethAccount(
 88                          account.EthAddress.Address,
 89                          account.PrivateKey
 90                      ),
 91                      account.PrivateKey));
 92          }
 93      }
 94  
 95      public class CustomGethNode : BaseGethNode, IGethNode
 96      {
 97          private readonly ILog log;
 98          private readonly BlockCache blockCache;
 99          private readonly string gethHost;
100          private readonly int gethPort;
101          private readonly string privateKey;
102  
103          public GethDeployment StartResult => throw new NotImplementedException();
104          public RunningContainer Container => throw new NotImplementedException();
105          public EthAddress CurrentAddress { get; }
106  
107          public CustomGethNode(ILog log, BlockCache blockCache, string gethHost, int gethPort, string privateKey)
108          {
109              this.log = log;
110              this.blockCache = blockCache;
111              this.gethHost = gethHost;
112              this.gethPort = gethPort;
113              this.privateKey = privateKey;
114  
115              var creator = new NethereumInteractionCreator(log, blockCache, gethHost, gethPort, privateKey);
116              CurrentAddress = creator.GetEthAddress();
117          }
118  
119          public GethBootstrapNode GetBootstrapRecord()
120          {
121              throw new NotImplementedException();
122          }
123  
124          public IGethNode WithDifferentAccount(EthAccount account)
125          {
126              return new CustomGethNode(log, blockCache, gethHost, gethPort, account.PrivateKey);
127          }
128  
129          protected override NethereumInteraction StartInteraction()
130          {
131              var creator = new NethereumInteractionCreator(log, blockCache, gethHost, gethPort, privateKey);
132              return creator.CreateWorkflow();
133          }
134      }
135  
136      public abstract class BaseGethNode
137      {
138          public Ether GetEthBalance()
139          {
140              return StartInteraction().GetEthBalance().Eth();
141          }
142  
143          public Ether GetEthBalance(IHasEthAddress owner)
144          {
145              return GetEthBalance(owner.EthAddress);
146          }
147  
148          public Ether GetEthBalance(EthAddress address)
149          {
150              return StartInteraction().GetEthBalance(address.Address).Wei();
151          }
152  
153          public string SendEth(IHasEthAddress owner, Ether eth)
154          {
155              return SendEth(owner.EthAddress, eth);
156          }
157  
158          public string SendEth(EthAddress account, Ether eth)
159          {
160              return StartInteraction().SendEth(account.Address, eth);
161          }
162  
163          public TResult Call<TFunction, TResult>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new()
164          {
165              return StartInteraction().Call<TFunction, TResult>(contractAddress, function);
166          }
167  
168          public TResult Call<TFunction, TResult>(string contractAddress, TFunction function, ulong blockNumber) where TFunction : FunctionMessage, new()
169          {
170              return StartInteraction().Call<TFunction, TResult>(contractAddress, function, blockNumber);
171          }
172  
173          public void Call<TFunction>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new()
174          {
175              StartInteraction().Call(contractAddress, function);
176          }
177  
178          public void Call<TFunction>(string contractAddress, TFunction function, ulong blockNumber) where TFunction : FunctionMessage, new()
179          {
180              StartInteraction().Call(contractAddress, function, blockNumber);
181          }
182  
183          public string SendTransaction<TFunction>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new()
184          {
185              return StartInteraction().SendTransaction(contractAddress, function);
186          }
187  
188          public Transaction GetTransaction(string transactionHash)
189          {
190              return StartInteraction().GetTransaction(transactionHash);
191          }
192  
193          public decimal? GetSyncedBlockNumber()
194          {
195              return StartInteraction().GetSyncedBlockNumber();
196          }
197  
198          public bool IsContractAvailable(string abi, string contractAddress)
199          {
200              return StartInteraction().IsContractAvailable(abi, contractAddress);
201          }
202  
203          public List<EventLog<TEvent>> GetEvents<TEvent>(string address, BlockInterval blockRange) where TEvent : IEventDTO, new()
204          {
205              return StartInteraction().GetEvents<TEvent>(address, blockRange);
206          }
207  
208          public List<EventLog<TEvent>> GetEvents<TEvent>(string address, TimeRange timeRange) where TEvent : IEventDTO, new()
209          {
210              return StartInteraction().GetEvents<TEvent>(address, ConvertTimeRangeToBlockRange(timeRange));
211          }
212  
213          public BlockInterval ConvertTimeRangeToBlockRange(TimeRange timeRange)
214          {
215              return StartInteraction().ConvertTimeRangeToBlockRange(timeRange);
216          }
217  
218          public BlockTimeEntry GetBlockForNumber(ulong number)
219          {
220              return StartInteraction().GetBlockForNumber(number);
221          }
222  
223          public BlockWithTransactions GetBlk(ulong number)
224          {
225              return StartInteraction().GetBlockWithTransactions(number);
226          }
227  
228          public void IterateTransactions(BlockInterval blockRange, Action<Transaction, ulong, DateTime> action)
229          {
230              var i = StartInteraction();
231              for (var blkI = blockRange.From; blkI <= blockRange.To; blkI++)
232              {
233                  var blk = i.GetBlockWithTransactions(blkI);
234                  var blkUtc = DateTimeOffset.FromUnixTimeSeconds(blk.Timestamp.ToLong()).UtcDateTime;
235  
236                  foreach (var t in blk.Transactions)
237                  {
238                      action(t, blkI, blkUtc);
239                  }
240              }
241          }
242  
243          public void IterateFunctionCalls<TFunc>(BlockInterval blockRange, Action<BlockTimeEntry, TFunc> onCall) where TFunc : FunctionMessage, new()
244          {
245              IterateTransactions(blockRange, (t, blkI, blkUtc) =>
246              {
247                  if (t.IsTransactionForFunctionMessage<TFunc>())
248                  {
249                      var func = t.DecodeTransactionToFunctionMessage<TFunc>();
250                      if (func != null)
251                      {
252                          var b = GetBlockForNumber(blkI);
253                          onCall(b, func);
254                      }
255                  }
256              });
257          }
258  
259          protected abstract NethereumInteraction StartInteraction();
260      }
261  }