2023-04-25 09:31:15 +00:00
|
|
|
|
using Logging;
|
2023-12-19 14:30:46 +00:00
|
|
|
|
using Nethereum.ABI.FunctionEncoding.Attributes;
|
2023-04-18 11:22:41 +00:00
|
|
|
|
using Nethereum.Contracts;
|
2023-09-19 09:51:59 +00:00
|
|
|
|
using Nethereum.RPC.Eth.DTOs;
|
2023-04-14 08:51:35 +00:00
|
|
|
|
using Nethereum.Web3;
|
2024-03-21 15:26:48 +00:00
|
|
|
|
using NethereumWorkflow.BlockUtils;
|
2023-04-14 08:51:35 +00:00
|
|
|
|
using Utils;
|
|
|
|
|
|
|
|
|
|
namespace NethereumWorkflow
|
|
|
|
|
{
|
2023-04-14 10:37:05 +00:00
|
|
|
|
public class NethereumInteraction
|
2023-04-14 08:51:35 +00:00
|
|
|
|
{
|
2024-03-21 15:26:48 +00:00
|
|
|
|
// BlockCache is a static instance: It stays alive for the duration of the application runtime.
|
|
|
|
|
private readonly static BlockCache blockCache = new BlockCache();
|
|
|
|
|
|
2023-09-15 14:27:08 +00:00
|
|
|
|
private readonly ILog log;
|
2023-04-14 08:51:35 +00:00
|
|
|
|
private readonly Web3 web3;
|
|
|
|
|
|
2023-09-15 14:27:08 +00:00
|
|
|
|
internal NethereumInteraction(ILog log, Web3 web3)
|
2023-04-14 08:51:35 +00:00
|
|
|
|
{
|
2023-04-25 09:31:15 +00:00
|
|
|
|
this.log = log;
|
2023-04-14 08:51:35 +00:00
|
|
|
|
this.web3 = web3;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-15 10:02:06 +00:00
|
|
|
|
public string SendEth(string toAddress, decimal ethAmount)
|
2023-09-19 09:51:59 +00:00
|
|
|
|
{
|
2023-10-23 14:04:50 +00:00
|
|
|
|
log.Debug();
|
2023-09-19 09:51:59 +00:00
|
|
|
|
var receipt = Time.Wait(web3.Eth.GetEtherTransferService().TransferEtherAndWaitForReceiptAsync(toAddress, ethAmount));
|
|
|
|
|
if (!receipt.Succeeded()) throw new Exception("Unable to send Eth");
|
2023-12-15 10:02:06 +00:00
|
|
|
|
return receipt.TransactionHash;
|
2023-09-19 09:51:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public decimal GetEthBalance()
|
|
|
|
|
{
|
2023-10-23 14:04:50 +00:00
|
|
|
|
log.Debug();
|
2023-09-19 09:51:59 +00:00
|
|
|
|
return GetEthBalance(web3.TransactionManager.Account.Address);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public decimal GetEthBalance(string address)
|
|
|
|
|
{
|
2023-10-23 14:04:50 +00:00
|
|
|
|
log.Debug();
|
2023-09-19 09:51:59 +00:00
|
|
|
|
var balance = Time.Wait(web3.Eth.GetBalance.SendRequestAsync(address));
|
|
|
|
|
return Web3.Convert.FromWei(balance.Value);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-19 11:39:24 +00:00
|
|
|
|
public TResult Call<TFunction, TResult>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new()
|
2023-04-18 11:22:41 +00:00
|
|
|
|
{
|
2023-10-23 14:04:50 +00:00
|
|
|
|
log.Debug(typeof(TFunction).ToString());
|
2023-09-19 11:39:24 +00:00
|
|
|
|
var handler = web3.Eth.GetContractQueryHandler<TFunction>();
|
|
|
|
|
return Time.Wait(handler.QueryAsync<TResult>(contractAddress, function));
|
2023-04-25 05:46:09 +00:00
|
|
|
|
}
|
2023-04-24 12:09:23 +00:00
|
|
|
|
|
2023-12-15 10:02:06 +00:00
|
|
|
|
public string SendTransaction<TFunction>(string contractAddress, TFunction function) where TFunction : FunctionMessage, new()
|
2023-04-25 05:46:09 +00:00
|
|
|
|
{
|
2023-10-23 14:04:50 +00:00
|
|
|
|
log.Debug();
|
2023-09-19 11:39:24 +00:00
|
|
|
|
var handler = web3.Eth.GetContractTransactionHandler<TFunction>();
|
|
|
|
|
var receipt = Time.Wait(handler.SendRequestAndWaitForReceiptAsync(contractAddress, function));
|
|
|
|
|
if (!receipt.Succeeded()) throw new Exception("Unable to perform contract transaction.");
|
2023-12-15 10:02:06 +00:00
|
|
|
|
return receipt.TransactionHash;
|
2023-04-24 12:09:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-20 12:21:53 +00:00
|
|
|
|
public Transaction GetTransaction(string transactionHash)
|
|
|
|
|
{
|
|
|
|
|
log.Debug();
|
|
|
|
|
return Time.Wait(web3.Eth.Transactions.GetTransactionByHash.SendRequestAsync(transactionHash));
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-19 11:58:45 +00:00
|
|
|
|
public decimal? GetSyncedBlockNumber()
|
|
|
|
|
{
|
|
|
|
|
log.Debug();
|
|
|
|
|
var sync = Time.Wait(web3.Eth.Syncing.SendRequestAsync());
|
|
|
|
|
var number = Time.Wait(web3.Eth.Blocks.GetBlockNumber.SendRequestAsync());
|
|
|
|
|
var numberOfBlocks = number.ToDecimal();
|
|
|
|
|
if (sync.IsSyncing) return null;
|
|
|
|
|
return numberOfBlocks;
|
|
|
|
|
}
|
2023-09-19 11:39:24 +00:00
|
|
|
|
|
2023-09-19 11:58:45 +00:00
|
|
|
|
public bool IsContractAvailable(string abi, string contractAddress)
|
|
|
|
|
{
|
|
|
|
|
log.Debug();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var contract = web3.Eth.GetContract(abi, contractAddress);
|
|
|
|
|
return contract != null;
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-19 14:30:46 +00:00
|
|
|
|
|
2024-03-27 14:39:42 +00:00
|
|
|
|
public List<EventLog<TEvent>> GetEvents<TEvent>(string address, BlockInterval blockRange) where TEvent : IEventDTO, new()
|
2023-12-19 14:30:46 +00:00
|
|
|
|
{
|
2024-03-27 14:39:42 +00:00
|
|
|
|
return GetEvents<TEvent>(address, blockRange.From, blockRange.To);
|
2023-12-19 14:30:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-19 14:43:26 +00:00
|
|
|
|
public List<EventLog<TEvent>> GetEvents<TEvent>(string address, ulong fromBlockNumber, ulong toBlockNumber) where TEvent : IEventDTO, new()
|
2023-12-19 14:30:46 +00:00
|
|
|
|
{
|
|
|
|
|
var eventHandler = web3.Eth.GetEvent<TEvent>(address);
|
|
|
|
|
var from = new BlockParameter(fromBlockNumber);
|
|
|
|
|
var to = new BlockParameter(toBlockNumber);
|
|
|
|
|
var blockFilter = Time.Wait(eventHandler.CreateFilterBlockRangeAsync(from, to));
|
|
|
|
|
return Time.Wait(eventHandler.GetAllChangesAsync(blockFilter));
|
|
|
|
|
}
|
2024-03-27 14:39:42 +00:00
|
|
|
|
|
|
|
|
|
public BlockInterval ConvertTimeRangeToBlockRange(TimeRange timeRange)
|
|
|
|
|
{
|
|
|
|
|
var wrapper = new Web3Wrapper(web3, log);
|
|
|
|
|
var blockTimeFinder = new BlockTimeFinder(blockCache, wrapper, log);
|
|
|
|
|
|
|
|
|
|
var fromBlock = blockTimeFinder.GetLowestBlockNumberAfter(timeRange.From);
|
|
|
|
|
var toBlock = blockTimeFinder.GetHighestBlockNumberBefore(timeRange.To);
|
|
|
|
|
|
|
|
|
|
if (fromBlock == null || toBlock == null)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Failed to convert time range to block range.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new BlockInterval(
|
2024-05-31 08:16:57 +00:00
|
|
|
|
timeRange: timeRange,
|
2024-03-27 14:39:42 +00:00
|
|
|
|
from: fromBlock.Value,
|
|
|
|
|
to: toBlock.Value
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-04-13 07:19:20 +00:00
|
|
|
|
|
|
|
|
|
public BlockTimeEntry GetBlockForNumber(ulong number)
|
|
|
|
|
{
|
|
|
|
|
var wrapper = new Web3Wrapper(web3, log);
|
|
|
|
|
var blockTimeFinder = new BlockTimeFinder(blockCache, wrapper, log);
|
|
|
|
|
return blockTimeFinder.Get(number);
|
|
|
|
|
}
|
2023-04-18 13:33:12 +00:00
|
|
|
|
}
|
2023-04-14 08:51:35 +00:00
|
|
|
|
}
|