2024-12-17 16:06:06 +01:00
|
|
|
|
using BlockchainUtils;
|
|
|
|
|
|
using Core;
|
2023-11-12 10:07:23 +01:00
|
|
|
|
using KubernetesWorkflow.Types;
|
2023-09-21 10:56:48 +02:00
|
|
|
|
using Logging;
|
2023-12-19 15:30:46 +01:00
|
|
|
|
using Nethereum.ABI.FunctionEncoding.Attributes;
|
2023-09-19 13:39:24 +02:00
|
|
|
|
using Nethereum.Contracts;
|
2023-12-20 13:21:53 +01:00
|
|
|
|
using Nethereum.RPC.Eth.DTOs;
|
2023-09-15 16:27:08 +02:00
|
|
|
|
using NethereumWorkflow;
|
2023-12-20 09:48:22 +01:00
|
|
|
|
using Utils;
|
2023-09-15 15:52:02 +02:00
|
|
|
|
|
|
|
|
|
|
namespace GethPlugin
|
|
|
|
|
|
{
|
2023-09-21 10:56:48 +02:00
|
|
|
|
public interface IGethNode : IHasContainer
|
2023-09-15 15:52:02 +02:00
|
|
|
|
{
|
2023-09-20 10:13:29 +02:00
|
|
|
|
GethDeployment StartResult { get; }
|
2025-07-31 09:27:02 +02:00
|
|
|
|
EthAddress CurrentAddress { get; }
|
2023-09-15 16:27:08 +02:00
|
|
|
|
|
2023-09-19 11:51:59 +02:00
|
|
|
|
Ether GetEthBalance();
|
|
|
|
|
|
Ether GetEthBalance(IHasEthAddress address);
|
2023-09-20 10:13:29 +02:00
|
|
|
|
Ether GetEthBalance(EthAddress address);
|
2023-12-15 11:02:06 +01:00
|
|
|
|
string SendEth(IHasEthAddress account, Ether eth);
|
|
|
|
|
|
string SendEth(EthAddress account, Ether eth);
|
2023-09-19 13:39:24 +02:00
|
|
|
|
TResult Call<TFunction, TResult>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new();
|
2025-03-04 15:24:25 +01:00
|
|
|
|
TResult Call<TFunction, TResult>(string contractAddress, TFunction function, ulong blockNumber) where TFunction : FunctionMessage, new();
|
2025-07-30 09:04:07 +02:00
|
|
|
|
void Call<TFunction>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new();
|
2025-03-04 15:24:25 +01:00
|
|
|
|
void Call<TFunction>(string contractAddress, TFunction function, ulong blockNumber) where TFunction : FunctionMessage, new();
|
2023-12-15 11:02:06 +01:00
|
|
|
|
string SendTransaction<TFunction>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new();
|
2023-12-20 13:21:53 +01:00
|
|
|
|
Transaction GetTransaction(string transactionHash);
|
2023-09-19 13:58:45 +02:00
|
|
|
|
decimal? GetSyncedBlockNumber();
|
|
|
|
|
|
bool IsContractAvailable(string abi, string contractAddress);
|
2023-11-21 10:33:11 +01:00
|
|
|
|
GethBootstrapNode GetBootstrapRecord();
|
2024-03-27 15:39:42 +01:00
|
|
|
|
List<EventLog<TEvent>> GetEvents<TEvent>(string address, BlockInterval blockRange) where TEvent : IEventDTO, new();
|
2023-12-20 09:48:22 +01:00
|
|
|
|
List<EventLog<TEvent>> GetEvents<TEvent>(string address, TimeRange timeRange) where TEvent : IEventDTO, new();
|
2024-03-27 15:39:42 +01:00
|
|
|
|
BlockInterval ConvertTimeRangeToBlockRange(TimeRange timeRange);
|
2024-04-13 09:19:20 +02:00
|
|
|
|
BlockTimeEntry GetBlockForNumber(ulong number);
|
2025-08-15 12:02:33 +02:00
|
|
|
|
void IterateTransactions(BlockInterval blockRange, Action<Transaction, ulong, DateTime> action);
|
2025-05-20 10:19:07 +02:00
|
|
|
|
void IterateFunctionCalls<TFunc>(BlockInterval blockInterval, Action<BlockTimeEntry, TFunc> onCall) where TFunc : FunctionMessage, new();
|
2025-07-03 11:03:13 +02:00
|
|
|
|
IGethNode WithDifferentAccount(EthAccount account);
|
2023-09-15 15:52:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-11 11:01:12 +01:00
|
|
|
|
public class DeploymentGethNode : BaseGethNode, IGethNode
|
2023-09-15 15:52:02 +02:00
|
|
|
|
{
|
2023-09-19 11:51:59 +02:00
|
|
|
|
private readonly ILog log;
|
2024-12-17 16:06:06 +01:00
|
|
|
|
private readonly BlockCache blockCache;
|
2023-09-19 11:51:59 +02:00
|
|
|
|
|
2024-12-17 16:06:06 +01:00
|
|
|
|
public DeploymentGethNode(ILog log, BlockCache blockCache, GethDeployment startResult)
|
2023-09-15 15:52:02 +02:00
|
|
|
|
{
|
2023-09-19 11:51:59 +02:00
|
|
|
|
this.log = log;
|
2024-12-17 16:06:06 +01:00
|
|
|
|
this.blockCache = blockCache;
|
2023-09-19 11:51:59 +02:00
|
|
|
|
StartResult = startResult;
|
2025-07-31 09:27:02 +02:00
|
|
|
|
CurrentAddress = new EthAddress(startResult.Account.Account);
|
2023-09-15 15:52:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-09-20 10:13:29 +02:00
|
|
|
|
public GethDeployment StartResult { get; }
|
2023-09-21 10:56:48 +02:00
|
|
|
|
public RunningContainer Container => StartResult.Container;
|
2025-07-31 09:27:02 +02:00
|
|
|
|
public EthAddress CurrentAddress { get; }
|
2023-09-15 15:52:02 +02:00
|
|
|
|
|
2023-12-11 11:01:12 +01:00
|
|
|
|
public GethBootstrapNode GetBootstrapRecord()
|
|
|
|
|
|
{
|
|
|
|
|
|
var address = StartResult.Container.GetInternalAddress(GethContainerRecipe.ListenPortTag);
|
|
|
|
|
|
|
|
|
|
|
|
return new GethBootstrapNode(
|
|
|
|
|
|
publicKey: StartResult.PubKey,
|
|
|
|
|
|
ipAddress: address.Host.Replace("http://", ""),
|
|
|
|
|
|
port: address.Port
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override NethereumInteraction StartInteraction()
|
|
|
|
|
|
{
|
2024-09-23 10:52:12 +02:00
|
|
|
|
var address = StartResult.Container.GetAddress(GethContainerRecipe.HttpPortTag);
|
2023-12-11 11:01:12 +01:00
|
|
|
|
var account = StartResult.Account;
|
|
|
|
|
|
|
2024-12-17 16:06:06 +01:00
|
|
|
|
var creator = new NethereumInteractionCreator(log, blockCache, address.Host, address.Port, account.PrivateKey);
|
2023-12-11 11:01:12 +01:00
|
|
|
|
return creator.CreateWorkflow();
|
|
|
|
|
|
}
|
2025-07-03 11:03:13 +02:00
|
|
|
|
|
|
|
|
|
|
public IGethNode WithDifferentAccount(EthAccount account)
|
|
|
|
|
|
{
|
|
|
|
|
|
return new DeploymentGethNode(log, blockCache,
|
|
|
|
|
|
new GethDeployment(
|
|
|
|
|
|
StartResult.Pod,
|
|
|
|
|
|
StartResult.DiscoveryPort,
|
|
|
|
|
|
StartResult.HttpPort,
|
|
|
|
|
|
StartResult.WsPort,
|
|
|
|
|
|
new GethAccount(
|
|
|
|
|
|
account.EthAddress.Address,
|
|
|
|
|
|
account.PrivateKey
|
|
|
|
|
|
),
|
|
|
|
|
|
account.PrivateKey));
|
|
|
|
|
|
}
|
2023-12-11 11:01:12 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class CustomGethNode : BaseGethNode, IGethNode
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly ILog log;
|
2024-12-17 16:06:06 +01:00
|
|
|
|
private readonly BlockCache blockCache;
|
2023-12-11 11:01:12 +01:00
|
|
|
|
private readonly string gethHost;
|
|
|
|
|
|
private readonly int gethPort;
|
|
|
|
|
|
private readonly string privateKey;
|
|
|
|
|
|
|
|
|
|
|
|
public GethDeployment StartResult => throw new NotImplementedException();
|
|
|
|
|
|
public RunningContainer Container => throw new NotImplementedException();
|
2025-07-31 09:27:02 +02:00
|
|
|
|
public EthAddress CurrentAddress { get; }
|
2023-12-11 11:01:12 +01:00
|
|
|
|
|
2024-12-17 16:06:06 +01:00
|
|
|
|
public CustomGethNode(ILog log, BlockCache blockCache, string gethHost, int gethPort, string privateKey)
|
2023-12-11 11:01:12 +01:00
|
|
|
|
{
|
|
|
|
|
|
this.log = log;
|
2024-12-17 16:06:06 +01:00
|
|
|
|
this.blockCache = blockCache;
|
2023-12-11 11:01:12 +01:00
|
|
|
|
this.gethHost = gethHost;
|
|
|
|
|
|
this.gethPort = gethPort;
|
|
|
|
|
|
this.privateKey = privateKey;
|
2025-07-31 09:27:02 +02:00
|
|
|
|
|
|
|
|
|
|
var creator = new NethereumInteractionCreator(log, blockCache, gethHost, gethPort, privateKey);
|
|
|
|
|
|
CurrentAddress = creator.GetEthAddress();
|
2023-12-11 11:01:12 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public GethBootstrapNode GetBootstrapRecord()
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 11:03:13 +02:00
|
|
|
|
public IGethNode WithDifferentAccount(EthAccount account)
|
|
|
|
|
|
{
|
|
|
|
|
|
return new CustomGethNode(log, blockCache, gethHost, gethPort, account.PrivateKey);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-11 11:01:12 +01:00
|
|
|
|
protected override NethereumInteraction StartInteraction()
|
|
|
|
|
|
{
|
2024-12-17 16:06:06 +01:00
|
|
|
|
var creator = new NethereumInteractionCreator(log, blockCache, gethHost, gethPort, privateKey);
|
2023-12-11 11:01:12 +01:00
|
|
|
|
return creator.CreateWorkflow();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public abstract class BaseGethNode
|
|
|
|
|
|
{
|
2023-09-19 11:51:59 +02:00
|
|
|
|
public Ether GetEthBalance()
|
|
|
|
|
|
{
|
|
|
|
|
|
return StartInteraction().GetEthBalance().Eth();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Ether GetEthBalance(IHasEthAddress owner)
|
|
|
|
|
|
{
|
|
|
|
|
|
return GetEthBalance(owner.EthAddress);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-09-20 10:13:29 +02:00
|
|
|
|
public Ether GetEthBalance(EthAddress address)
|
2023-09-19 11:51:59 +02:00
|
|
|
|
{
|
2025-07-30 09:04:07 +02:00
|
|
|
|
return StartInteraction().GetEthBalance(address.Address).Wei();
|
2023-09-19 11:51:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-15 11:02:06 +01:00
|
|
|
|
public string SendEth(IHasEthAddress owner, Ether eth)
|
2023-09-19 11:51:59 +02:00
|
|
|
|
{
|
2023-12-15 11:02:06 +01:00
|
|
|
|
return SendEth(owner.EthAddress, eth);
|
2023-09-19 11:51:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-15 11:02:06 +01:00
|
|
|
|
public string SendEth(EthAddress account, Ether eth)
|
2023-09-19 11:51:59 +02:00
|
|
|
|
{
|
2025-08-05 15:02:52 +02:00
|
|
|
|
return StartInteraction().SendEth(account.Address, eth);
|
2023-09-19 13:39:24 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public TResult Call<TFunction, TResult>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new()
|
|
|
|
|
|
{
|
|
|
|
|
|
return StartInteraction().Call<TFunction, TResult>(contractAddress, function);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-04 15:24:25 +01:00
|
|
|
|
public TResult Call<TFunction, TResult>(string contractAddress, TFunction function, ulong blockNumber) where TFunction : FunctionMessage, new()
|
|
|
|
|
|
{
|
|
|
|
|
|
return StartInteraction().Call<TFunction, TResult>(contractAddress, function, blockNumber);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-30 09:04:07 +02:00
|
|
|
|
public void Call<TFunction>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new()
|
|
|
|
|
|
{
|
|
|
|
|
|
StartInteraction().Call(contractAddress, function);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-04 15:24:25 +01:00
|
|
|
|
public void Call<TFunction>(string contractAddress, TFunction function, ulong blockNumber) where TFunction : FunctionMessage, new()
|
|
|
|
|
|
{
|
|
|
|
|
|
StartInteraction().Call(contractAddress, function, blockNumber);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-15 11:02:06 +01:00
|
|
|
|
public string SendTransaction<TFunction>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new()
|
2023-09-19 13:39:24 +02:00
|
|
|
|
{
|
2023-12-15 11:02:06 +01:00
|
|
|
|
return StartInteraction().SendTransaction(contractAddress, function);
|
2023-09-19 13:39:24 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-20 13:21:53 +01:00
|
|
|
|
public Transaction GetTransaction(string transactionHash)
|
|
|
|
|
|
{
|
|
|
|
|
|
return StartInteraction().GetTransaction(transactionHash);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-09-19 13:58:45 +02:00
|
|
|
|
public decimal? GetSyncedBlockNumber()
|
|
|
|
|
|
{
|
|
|
|
|
|
return StartInteraction().GetSyncedBlockNumber();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool IsContractAvailable(string abi, string contractAddress)
|
|
|
|
|
|
{
|
|
|
|
|
|
return StartInteraction().IsContractAvailable(abi, contractAddress);
|
|
|
|
|
|
}
|
2023-12-11 11:01:12 +01:00
|
|
|
|
|
2024-03-27 15:39:42 +01:00
|
|
|
|
public List<EventLog<TEvent>> GetEvents<TEvent>(string address, BlockInterval blockRange) where TEvent : IEventDTO, new()
|
2023-12-19 15:30:46 +01:00
|
|
|
|
{
|
2024-02-19 15:20:12 +01:00
|
|
|
|
return StartInteraction().GetEvents<TEvent>(address, blockRange);
|
2023-12-19 15:30:46 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-20 09:48:22 +01:00
|
|
|
|
public List<EventLog<TEvent>> GetEvents<TEvent>(string address, TimeRange timeRange) where TEvent : IEventDTO, new()
|
2023-12-19 15:30:46 +01:00
|
|
|
|
{
|
2024-03-27 15:39:42 +01:00
|
|
|
|
return StartInteraction().GetEvents<TEvent>(address, ConvertTimeRangeToBlockRange(timeRange));
|
2023-12-19 15:30:46 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-03-27 15:39:42 +01:00
|
|
|
|
public BlockInterval ConvertTimeRangeToBlockRange(TimeRange timeRange)
|
2024-02-19 15:20:12 +01:00
|
|
|
|
{
|
|
|
|
|
|
return StartInteraction().ConvertTimeRangeToBlockRange(timeRange);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-13 09:19:20 +02:00
|
|
|
|
public BlockTimeEntry GetBlockForNumber(ulong number)
|
|
|
|
|
|
{
|
|
|
|
|
|
return StartInteraction().GetBlockForNumber(number);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-04 11:20:33 +02:00
|
|
|
|
public BlockWithTransactions GetBlk(ulong number)
|
|
|
|
|
|
{
|
2025-05-06 20:33:37 +02:00
|
|
|
|
return StartInteraction().GetBlockWithTransactions(number);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-15 12:02:33 +02:00
|
|
|
|
public void IterateTransactions(BlockInterval blockRange, Action<Transaction, ulong, DateTime> action)
|
2025-05-06 20:33:37 +02:00
|
|
|
|
{
|
|
|
|
|
|
var i = StartInteraction();
|
|
|
|
|
|
for (var blkI = blockRange.From; blkI <= blockRange.To; blkI++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var blk = i.GetBlockWithTransactions(blkI);
|
2025-08-15 12:02:33 +02:00
|
|
|
|
var blkUtc = DateTimeOffset.FromUnixTimeSeconds(blk.Timestamp.ToLong()).UtcDateTime;
|
2025-05-06 20:33:37 +02:00
|
|
|
|
|
|
|
|
|
|
foreach (var t in blk.Transactions)
|
|
|
|
|
|
{
|
2025-08-15 12:02:33 +02:00
|
|
|
|
action(t, blkI, blkUtc);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void IterateFunctionCalls<TFunc>(BlockInterval blockRange, Action<BlockTimeEntry, TFunc> onCall) where TFunc : FunctionMessage, new()
|
|
|
|
|
|
{
|
|
|
|
|
|
IterateTransactions(blockRange, (t, blkI, blkUtc) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if (t.IsTransactionForFunctionMessage<TFunc>())
|
|
|
|
|
|
{
|
|
|
|
|
|
var func = t.DecodeTransactionToFunctionMessage<TFunc>();
|
|
|
|
|
|
if (func != null)
|
2025-05-07 15:20:24 +02:00
|
|
|
|
{
|
2025-08-15 12:02:33 +02:00
|
|
|
|
var b = GetBlockForNumber(blkI);
|
|
|
|
|
|
onCall(b, func);
|
2025-05-07 15:20:24 +02:00
|
|
|
|
}
|
2025-05-06 20:33:37 +02:00
|
|
|
|
}
|
2025-08-15 12:02:33 +02:00
|
|
|
|
});
|
2025-05-04 11:20:33 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-11 11:01:12 +01:00
|
|
|
|
protected abstract NethereumInteraction StartInteraction();
|
2023-09-15 15:52:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|