Currently I'm using GetBlockWithTransactionsByNumber
by looping into the latest 200 blocks to get the transactions sent to my address. I can actually get my transaction through the block number but what about the pending transaction which has no block number yet (haven't mined to a block).
Nethereum – How to Get the List of Pending Transactions
nethereum
Related Solutions
The Nethereum.Web.Sample shows you how to interact with the DAO.
In the sample there is a generic DAO service Source code in Github
A simple pattern to create a contract service, is to instantiate it with your Web3 class and ABI.
public class DaoService
{
private readonly Web3.Web3 web3;
private string abi = @"abi...";
private Contract contract;
public DaoService(Web3.Web3 web3, string address)
{
this.web3 = web3;
this.contract = web3.Eth.GetContract(abi, address);
}
The DAO stores the total number of proposals by declaring a public attribute, this can be accessed as follows:
public Task<long> GetNumberOfProposals()
{
return contract.GetFunction("numberOfProposals").CallAsync<long>();
}
If you want to retrieve all the Proposals you can iterate from 0 to the total number of proposals and add them to a collection as:
public async Task<List<Proposal>> GetAllProposals()
{
var numberOfProposals = await GetNumberOfProposals().ConfigureAwait(false);
var proposals = new List<Proposal>();
for (var i = 0; i < numberOfProposals; i++)
{
proposals.Add(await GetProposal(i).ConfigureAwait(false));
}
return proposals;
}
What is missing above is how to get that specific Proposal data to so you can call the function "proposals" this is in solidity the "mapping" of the proposal number and the struct proposal, which are output parameters.
public async Task<Proposal> GetProposal(long index)
{
var proposalsFunction = contract.GetFunction("proposals");
var proposal = await proposalsFunction.CallDeserializingToObjectAsync<Proposal>(index).ConfigureAwait(false);
proposal.Index = index;
return proposal;
}
Above you may have noticed the output is deserialised into a Proposal Object, this is the FunctionOuput and requires information (from the ABI) to do the deserialisation.
[FunctionOutput]
public class Proposal
{
public long Index { get; set; }
[Parameter("address", 1)]
public string Recipient { get; set; }
[Parameter("uint256", 2)]
public BigInteger Amount { get; set; }
[Parameter("string", 3)]
public string Description { get; set; }
[Parameter("uint256", 4)]
public BigInteger VotingDeadline { get; set; }
[Parameter("bool", 5)]
public bool Open { get; set; }
[Parameter("bool", 6)]
public bool ProposalPassed { get; set; }
[Parameter("bytes32", 7)]
public byte[] ProposalHash { get; set; }
public string GetProposalHashToHex()
{
return ProposalHash.ToHex();
}
[Parameter("uint256", 8)]
public BigInteger ProposalDeposit { get; set; }
[Parameter("bool", 9)]
public bool NewCurator { get; set; }
[Parameter("uint256", 10)]
public BigInteger Yea { get; set; }
[Parameter("uint256", 11)]
public BigInteger Nay { get; set; }
[Parameter("address", 12)]
public string Creator { get; set; }
}
The Nethereum does not support it directly but all versions of Parity wallet supports it and recent versions of geth also supports it, so we can send an RPC call directly without using any Nethereum RPC call. The RPC method in question is eth_getRawTransactionByHash
.
Like so
/// <summary>
/// Attempt to get the raw hex directly from the geth node
/// </summary>
/// <param name="txid"></param>
/// <returns></returns>
internal string GetRawTxHexByGetRawTransactionByHash(string txid)
{
// Extract the HttpClient object from the web3 object
FieldInfo field = typeof(Nethereum.JsonRpc.Client.RpcClient).GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
HttpClient httpClient = (HttpClient)field.GetValue(_web3.Client);
// Make the post request to our own Geth node and deserialize the result
RpcRequest rpcRequest = new RpcRequest
{
method = "eth_getRawTransactionByHash",
@params = new string[] { txid },
};
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("/", UriKind.Relative));
requestMessage.Content = new StringContent(JsonConvert.SerializeObject(rpcRequest), Encoding.UTF8, "application/json");
HttpResponseMessage resp = httpClient.SendAsync(requestMessage).Result;
if (!resp.IsSuccessStatusCode)
{
_logger.LogWarning($"Failed to call to eth_getRawTransactionByHash for txid={txid}.");
return null;
}
EthGetRawTransactionByHashResponse txResp =
JsonConvert.DeserializeObject<EthGetRawTransactionByHashResponse>(resp.Content.ReadAsStringAsync().Result);
return txResp.result;
}
where the following helper classes have been used
private abstract class Web3RpcBase
{
public int id { get; set; } = 67;
public string jsonrpc { get; set; } = "2.0";
}
private class RpcRequest : Web3RpcBase
{
public string method { get; set; }
public string[] @params { get; set; }
}
private class EthGetRawTransactionByHashResponse : Web3RpcBase
{
public string result { get; set; }
}
If you are so unfortunate to use a node that does not support eth_getRawTransactionByHash
(old geth versions), you can still get the raw hex using the following functions to construct the raw hex from available data.
private abstract class Web3RpcBase
{
public int id { get; set; } = 67;
public string jsonrpc { get; set; } = "2.0";
}
private class RpcRequest : Web3RpcBase
{
public string method { get; set; }
public string[] @params { get; set; }
}
private class EthGetTransactionByHashResponseResult
{
public string blockHash { get; set; }
public string blockNumber { get; set; }
public string from { get; set; }
// This is what we usually call gas limit
public string gas { get; set; }
public string gasPrice { get; set; }
public string hash { get; set; }
// This is what we usually call data
public string input { get; set; }
public string nonce { get; set; }
public string to { get; set; }
public string transactionIndex { get; set; }
public string value { get; set; }
public string v { get; set; }
public string r { get; set; }
public string s { get; set; }
}
private class EthGetTransactionByHashResponse : Web3RpcBase
{
public EthGetTransactionByHashResponseResult result { get; set; }
}
private class EthGetRawTransactionByHashResponse : Web3RpcBase
{
public string result { get; set; }
}
/// <summary>
/// Should only be used for Ethereum, not BTC.
/// </summary>
/// <param name="hexString"></param>
/// <returns></returns>
private static byte[] HexToByteArrayWrapper(string hexString)
{
// Prevent "0" from becoming "00" represented by[0]. "0" should be[], and 1 should be [0x01]
if (string.IsNullOrEmpty(hexString) || hexString == "0" || hexString == "0x0")
{
return Array.Empty<byte>();
}
return hexString.HexToByteArray();
}
/// <summary>
/// Attempt to get the raw hex directly from the geth node
/// </summary>
/// <param name="txid"></param>
/// <returns></returns>
internal string GetRawTxHexByGetRawTransactionByHash(string txid)
{
// Extract the HttpClient object from the web3 object
FieldInfo field = typeof(Nethereum.JsonRpc.Client.RpcClient).GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
HttpClient httpClient = (HttpClient)field.GetValue(_web3.Client);
// Make the post request to our own Geth node and deserialize the result
RpcRequest rpcRequest = new RpcRequest
{
method = "eth_getRawTransactionByHash",
@params = new string[] { txid },
};
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("/", UriKind.Relative));
requestMessage.Content = new StringContent(JsonConvert.SerializeObject(rpcRequest), Encoding.UTF8, "application/json");
HttpResponseMessage resp = httpClient.SendAsync(requestMessage).Result;
if (!resp.IsSuccessStatusCode)
{
_logger.LogWarning($"Failed to call to eth_getRawTransactionByHash for txid={txid}.");
return null;
}
EthGetRawTransactionByHashResponse txResp =
JsonConvert.DeserializeObject<EthGetRawTransactionByHashResponse>(resp.Content.ReadAsStringAsync().Result);
return txResp.result;
}
/// <summary>
/// Attempt to reconstruct the raw hex by getting the transaction info from the geth node
/// </summary>
/// <param name="txid"></param>
/// <returns></returns>
internal string GetRawTxHexByGetTransactionByHash(string txid)
{
// Extract the HttpClient object from the web3 object
FieldInfo field = typeof(Nethereum.JsonRpc.Client.RpcClient).GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
HttpClient httpClient = (HttpClient)field.GetValue(_web3.Client);
// Make the post request to our own Geth node and deserialize the result
RpcRequest rpcRequest = new RpcRequest
{
method = "eth_getTransactionByHash",
@params = new string[] { txid },
};
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("/", UriKind.Relative));
requestMessage.Content = new StringContent(JsonConvert.SerializeObject(rpcRequest), Encoding.UTF8, "application/json");
HttpResponseMessage resp = httpClient.SendAsync(requestMessage).Result;
if (!resp.IsSuccessStatusCode)
{
_logger.LogWarning($"Failed to call to eth_getTransactionByHash for txid={txid}.");
return null;
}
EthGetTransactionByHashResponse txResp = JsonConvert.DeserializeObject<EthGetTransactionByHashResponse>(resp.Content.ReadAsStringAsync().Result);
// Create the signature object to insert in the transaction (needed to support chain IDs above 0xff)
Org.BouncyCastle.Math.BigInteger r = new Org.BouncyCastle.Math.BigInteger(txResp.result.r.Substring(2), 0x10);
Org.BouncyCastle.Math.BigInteger s = new Org.BouncyCastle.Math.BigInteger(txResp.result.s.Substring(2), 0x10);
byte[] v = new byte[] { byte.Parse(txResp.result.v.Substring(2), System.Globalization.NumberStyles.HexNumber, CultureInfo.GetCultureInfo("en-US")) };
EthECDSASignature signature = new Nethereum.Signer.EthECDSASignature(r, s, v);
// Create unsigned transaction object
Nethereum.Signer.Transaction transaction = new Nethereum.Signer.Transaction(
HexToByteArrayWrapper(txResp.result.nonce),
HexToByteArrayWrapper(txResp.result.gasPrice),
HexToByteArrayWrapper(txResp.result.gas),
HexToByteArrayWrapper(txResp.result.to),
HexToByteArrayWrapper(txResp.result.value),
HexToByteArrayWrapper(txResp.result.input),
Array.Empty<byte>(),
Array.Empty<byte>(),
0);
transaction.SetSignature(signature);
// Get the hex format of the RLP-encoded transaction, the rawtx
string rawTxHex = "0x" + transaction.GetRLPEncoded().Select(x => x.ToString("x2", NumberFormatInfo.InvariantInfo)).Aggregate((acc, elem) => acc + elem);
return rawTxHex;
}
/// <summary>
/// Given a txid return the RLP-encoded raw hex that represents the transcation on the blockchain.
/// </summary>
/// <param name="txid"></param>
/// <returns></returns>
internal string GetRawHex(string txid)
{
// First try to get the raw hex directly from the node
string res = GetRawTxHexByGetRawTransactionByHash(txid);
if (!String.IsNullOrWhiteSpace(res) && res != "0x")
{
return res;
}
// If that did not work, attempt to construct it from tx details
_logger.LogInformation("Failed to get raw hex from node, calculating it locally instead.");
return GetRawTxHexByGetTransactionByHash(txid);
}
Best Answer
The
txpool_content
inspection property can be queried to list the exact details of all the transactions currently pending for inclusion in the next block(s), as well as the ones that are being scheduled for future execution only.Refernce : https://github.com/ethereum/go-ethereum/wiki/Management-APIs#txpool
This API is not directly available.So you can integrate the
txpool_content
API using the following code.