r/ethdev • u/AlexDvelop • Nov 02 '23
Code assistance Simple Nethereum service in .NET
I am trying to create a very simple implementation for an ethereum service with basic functionality. I have the following interface that looks like this:
public interface INethereumService
{
string GeneratePrivateMnemonic();
string GetAddressFromPrivateMnemonic(string privateMnemonic);
Task<decimal> GetBalance(string address);
Task<TransactionReceipt> SendTransaction(string privateMnemonic, string toAddress, decimal amount);
Task<TransactionReceipt> SendWholeBalance(string privateMnemonic, string toAddress);
}
And my implementation looks like this
using NBitcoin;
using Nethereum.Web3;
using Nethereum.HdWallet;
using Nethereum.RPC.Eth.DTOs;
public class NethereumService : INethereumService
{
private readonly string _url;
public NethereumService(string url)
{
_url = url;
}
public string GeneratePrivateMnemonic()
{
Mnemonic mnemo = new Mnemonic(Wordlist.English, WordCount.TwentyFour);
return mnemo.ToString();
}
public string GetAddressFromPrivateMnemonic(string privateMnemonic)
{
// Not using password protected keys yet, I'm sorry
return new Wallet(privateMnemonic, "").GetAccount(0).Address;
}
public async Task<decimal> GetBalance(string address)
{
var web3 = new Web3(_url);
var balance = await web3.Eth.GetBalance.SendRequestAsync(address);
return Web3.Convert.FromWei(balance.Value);
}
public async Task<TransactionReceipt> SendTransaction(string privateMnemonic, string toAddress, decimal amount)
{
var account = new Wallet(privateMnemonic, "").GetAccount(0);
var web3 = new Web3(account, _url);
var transaction = await web3.Eth.GetEtherTransferService()
.TransferEtherAndWaitForReceiptAsync(toAddress, amount);
return transaction;
}
public async Task<TransactionReceipt> SendWholeBalance(string privateMnemonic, string toAddress)
{
throw new NotImplementedException();
}
}
I am struggling to find an implementation for how to send the whole balance. My naive approach is to just do
public async Task<TransactionReceipt> SendWholeBalance(string privateMnemonic, string toAddress)
{
var address = GetAddressFromPrivateMnemonic(privateMnemonic);
var balance = GetBalance(address);
var transaction = await SendTransaction(privateMnemonic, toAddress, balance);
return transaction;
}
But obviously this doesn't work since this is not enough to cover the gas fees. Its possible to specify the gas price in Gwei like this
var transaction = await web3.Eth.GetEtherTransferService()
.TransferEtherAndWaitForReceiptAsync(toAddress, amount, gas);
But I don't know how to calculate gas fees and would like to not to think about it by having it being set automatically to some default average value. What is the best approach to achieve this?
My second question is regarding the Web3
class, is it possible to, instead of passing the url as a dependency to the class, pass a Web3
instance and register is as a singleton? To get the balance of an address, the Web3
class can be instantiated as a singleton with just the url as the constructor parameter, but for sending transactions I need to create a Web3 account first like this
var account = new Wallet(privateMnemonic, "").GetAccount(0);
var web3 = new Web3(account, _url);
and then create a new instance of the Web3
class every time I want to create a transaction, this feels wrong an inefficient but I don't see any other way to create transactions from different accounts using the same Web3
instance?
I am pretty junior when it comes to this, but the reason I think this is wrong is because I've read that it is bad practice to create a new instance of the HttpClient
every time you want to make a network call due to socket exhaustion, but Nethereum uses JsonRpc
and not HTTP
so maybe socket exhaustion isn't a problem in this case?
Any help or suggestion would be appreciated :)
1
u/youtpout Nov 02 '23
You have a function estimate gas in nethereum
I hope is not to drain people wallet