EthSmartContractIO 1.0.0

dotnet add package EthSmartContractIO --version 1.0.0
NuGet\Install-Package EthSmartContractIO -Version 1.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EthSmartContractIO" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add EthSmartContractIO --version 1.0.0
#r "nuget: EthSmartContractIO, 1.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install EthSmartContractIO as a Cake Addin
#addin nuget:?package=EthSmartContractIO&version=1.0.0

// Install EthSmartContractIO as a Cake Tool
#tool nuget:?package=EthSmartContractIO&version=1.0.0

EthSmartContractIO

SonarCloud

Quality Gate Status SonarScanner for .NET 6 CodeFactor

NuGet version License

The Arcadia Group security audit

EthSmartContractIO is a .NET library aimed at simplifying the interaction with Ethereum smart contracts. It allows developers to execute actions on the Ethereum network by wrapping the complexity of Ethereum RPC calls into a more manageable, high-level API.

Getting Started

To use EthSmartContractIO, you will need to add it as a dependency to your project. You can do this by adding it as a NuGet package:

.NET CLI

dotnet add package EthSmartContractIO

Package Manager

Install-Package EthSmartContractIO

Core Components

RpcRequest

RpcRequest is the main object that is used to communicate with the Ethereum network. It represents a request to either read data from a smart contract or write data to a smart contract.

Read Request

A Read request is created by calling the constructor RpcRequest(string rpcUrl, string to, string data). This type of request doesn't require a transaction to be mined and therefore doesn't require gas settings or a value.

var readRequest = new RpcRequest(
    rpcUrl: "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID",
    to: "0xYourContractAddress",
    data: "0xYourData"
);
Write Request

A Write request is created by calling the constructor RpcRequest(string rpcUrl, string to, WriteRpcRequest writeRequest, string? data = null). A Write request can call contract write methods, and send money to other account This type of request creates a transaction that needs to be mined, which requires gas settings and potentially a value.

Call contract example:

var writeRequest = new RpcRequest(
    rpcUrl: "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID",
    to: "0xYourContractAddress",
    writeRequest: new WriteRpcRequest(
        chainId: 1,
        value: new HexBigInteger(1000000000000000),
        gasSettings: new GasSettings(maxGasLimit: 31000, maxGweiGasPrice: 20),
        accountProvider: new YourIAccountProvider() // The class that implements the interface 'IAccountProvider'
    ),
    data: "0xYourData" // Optional parameter, set if need to call contract method
);

Send money example:

var writeRequest = new RpcRequest(
    rpcUrl: "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID",
    to: "0xOtherAccountAddress",
    writeRequest: new WriteRpcRequest(
        chainId: 1,
        value: new HexBigInteger("0xDE0B6B3A7640000"),
        gasSettings: new GasSettings(maxGasLimit: 31000, maxGweiGasPrice: 20),
        accountProvider: new YourIAccountProvider() // The class that implements the interface 'IAccountProvider'
    )
);

GasSettings

GasSettings is a simple class that holds the GasPrice and GasLimit settings for a write request. Gas is the mechanism that Ethereum uses to allocate resources among nodes.

var gasSettings = new GasSettings(maxGasLimit: 31000, maxGweiGasPrice: 20);

IAccountProvider

IAccountProvider is an interface that should be implemented by the class responsible for providing an Ethereum account. The Ethereum account holds a private key that will be used to sign the Ethereum transaction. The Account property is expected to return an instance of the Account object from the Nethereum.Web3.Accounts namespace.

Example

Here is an example of how to implement this interface:

using Nethereum.Web3.Accounts;
using EthSmartContractIO.Providers;

public class MyAccountProvider : IAccountProvider 
{
    public Account Account => new Account("0x4e3c79ee2f53da4e456cb13887f4a7d59488677e9e48b6fb6701832df828f7e9");
}

In this example, we're providing an Ethereum account with a specific private key. Please note that hardcoding private keys is not a good practice, this is just an illustrative example. Always store private keys in a secure manner.

ContractIO

ContractIO is the main class that interfaces with your Ethereum node. You can use it to execute actions (read or write) on the Ethereum network.

// Initialize the ContractIO object
var contractIO = new ContractIO();

// Execute the action
var result = contractIO.ExecuteAction(myRpcRequest);

// Handle the result
Console.WriteLine(result);

In the example above, ContractIO uses the strategy pattern to decide which class (ContractReader for read operations and ContractWriter for write operations) to use to execute the action.

How to Use

Here's a simple example of how to read data from a smart contract using this library:

// Create a read request
var readRequest = new RpcRequest(
    rpcUrl: "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID",
    to: "0xYourContractAddress",
    data: "0xYourData"
);

// Initialize the ContractIO object
var contractIO = new ContractIO();

// Execute the action
var result = contractIO.ExecuteAction(readRequest);

// Handle the result
Console.WriteLine(result);

And here's how to write data to a smart contract:

// Initialize your account provider
var myAccountProvider = new MyAccountProvider();

// Create a write request
var writeRequest = new RpcRequest(
    rpcUrl: "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID",
    to: "0xYourContractAddress",
    writeRequest: new WriteRpcRequest(
        chainId: 1,
        value: new HexBigInteger(10000000000000000),
        gasSettings: new GasSettings(30000, 6),
        accountProvider: myAccountProvider
    ),
    data: "0xYourData"
);

// Initialize the ContractIO object
var contractIO = new ContractIO();

// Execute the action
var result = contractIO.ExecuteAction(writeRequest);

// Handle the result
Console.WriteLine(result);

Custom Implementations and Dependency Injection

With EthSmartContractIO, you're not limited to the default implementation of certain interfaces like IGasPricer, ITransactionSigner, and ITransactionSender. You can provide your own custom implementations and inject them into the ContractIO class using the IServiceProvider property.

Interfaces

Here are the interfaces you can replace:

IGasPricer

This interface is responsible for providing the current gas price. If you have a custom strategy for gas price, you can implement this interface and provide your own method for getting the current gas price.

public interface IGasPricer
{
    HexBigInteger GetCurrentWeiGasPrice();
}
ITransactionSigner

This interface is responsible for signing transactions. If you have a custom transaction signing method, you can implement this interface and provide your own transaction signing logic.

public interface ITransactionSigner
{
    string SignTransaction(TransactionInput transaction);
}
ITransactionSender

This interface is responsible for sending transactions to the Ethereum network. If you have a custom method for sending transactions, you can implement this interface and provide your own transaction sending logic.

public interface ITransactionSender
{
    string SendTransaction(string signedTransaction);
}

IServiceProvider

To use your custom implementations, you need to provide an IServiceProvider instance to the ContractIO class that contains your implementations. You can use the ServiceProviderBuilder class from the EthSmartContractIO.Builders namespace to create an IServiceProvider object.

Here is a sample usage of ServiceProviderBuilder:

// Add your custom implementations
var serviceProvider = new ServiceProviderBuilder()
    .AddGasPricer(new MyCustomGasPricer())
    .AddTransactionSigner(new MyCustomTransactionSigner())
    .AddTransactionSender(new MyCustomTransactionSender())
    .Build();

// Create a ContractRpc instance and inject your custom implementations
var contractIO = new ContractIO(serviceProvider)

In the example above, MyCustomGasPricer, MyCustomTransactionSigner, and MyCustomTransactionSender are your custom implementations of the IGasPricer, ITransactionSigner, and ITransactionSender interfaces, respectively.

By using this approach, you can easily customize the behavior of the library to suit your specific needs.

Testing EthSmartContractIO

Testing is a critical part of software development and ensures the reliability and accuracy of your code. EthSmartContractIO's architecture allows it to be tested in a couple of ways:

Overriding ExecuteAction Method

The ExecuteAction method in the ContractIO class is marked as virtual. This allows the method to be overridden in a subclass, which is useful for testing scenarios. You can use mocking libraries such as Moq to mock the method's behavior.

Here's an example using Moq:

var contractIOMock = new Mock<ContractIO> { CallBase = true };
contractIOMock
    .Setup(x => x.ExecuteAction(It.IsAny<RpcRequest>()))
    .Returns("YourMockedResult");

// Now when you call ExecuteAction, it will return "YourMockedResult"
var result = contractIOMock.Object.ExecuteAction(someRpcRequest);

Assert.Equal("YourMockedResult", result);

In this example, regardless of what RpcRequest you pass to ExecuteAction, it will always return the string "YourMockedResult".

Creating an IWeb3 Moq Object for Write Requests

Alternatively, you can mock the IWeb3 object and pass it to ContractIO using the ServiceProvider. The ServiceProviderBuilder class provides an AddWeb3 method for this purpose.

Here's an example of how to mock IWeb3 using Moq and inject it using ServiceProviderBuilder:

var web3Mock = new Mock<IWeb3>();
// Setup your web3Mock...

var serviceProvider = new ServiceProviderBuilder()
    .AddWeb3(web3Mock.Object)
    .Build();

var contractIO = new ContractIO(serviceProvider)

In this example, ContractIO will use your mocked IWeb3 object, allowing you to control its behavior for testing.

By leveraging these strategies, you can create comprehensive unit tests for your code that interacts with the EthSmartContractIO library. This ensures the correct behavior of your Ethereum interactions.

Testing Read Requests using Flurl.Http.Testing

When testing read requests, you might want to simulate the HTTP calls made by the application. For this purpose, you can use Flurl.Http.Testing, a library that provides testing utilities for HTTP calls made using Flurl. This library provides an HttpTest class that can be used to set up expectations for HTTP calls and provide predefined responses.

Here's an example of how to use HttpTest for testing read requests:

using Flurl.Http.Testing;

// Setup expectations and response
string rpcUrl = "http://your_rpc_url_here";
string response = "{ your_json_rpc_response_here }";

// Start an HttpTest
using var httpTest = new HttpTest();
httpTest
    .ForCallsTo(RpcUrl)
    .RespondWithJson(response);

// Now when ContractIO executes a read request, it will receive your predefined response
var contractIO = new ContractIO();
var result = contractIO.ExecuteAction(readRequest);

// You can assert the expected output based on your predefined response
// This will vary based on the structure of your JSON RPC response

EthSmartContractIO.AccountProvider

The EthSmartContractIO.AccountProvider is a NuGet package that provides various account providers for Ethereum based smart contract I/O operations. The package includes two account providers: MnemonicAccountProvider and PrivateKeyAccountProvider.

Getting Started

To use EthSmartContractIO.AccountProvider, you will need to add it as a dependency to your project. You can do this by adding it as a NuGet package:

.NET CLI

dotnet add package EthSmartContractIO.AccountProvider

Package Manager

Install-Package EthSmartContractIO.AccountProvider

Account Providers

The package provides different classes for account management. These classes implement the IAccountProvider interface, providing flexibility and support for different Ethereum account types.

MnemonicAccountProvider

MnemonicAccountProvider is a class that generates an Ethereum account using a mnemonic (a list of words) that represents a wallet's private key. This class provides two constructors:

  • The first constructor accepts the mnemonic words, account ID, chain ID and optionally, a password for the seed. It generates an account corresponding to the account ID from the given mnemonic.

  • The second constructor uses an instance of ISecretsProvider to obtain the mnemonic words. This can be useful when you have a secure way to store and retrieve the mnemonic words and want to keep them separate from your main application code.

using Nethereum.HdWallet;
using Nethereum.Hex.HexTypes;
using Nethereum.Web3.Accounts;
using EthSmartContractIO.Providers;

namespace EthSmartContractIO.AccountProvider;

public class MnemonicAccountProvider : IAccountProvider
{
    public Account Account { get; private set; }

    public MnemonicAccountProvider(string mnemonicWords, uint accountId, uint chainId, string seedPassword = "")
    {
        var wallet = new Wallet(words: mnemonicWords, seedPassword: seedPassword);
        Account = wallet.GetAccount((int)accountId, new HexBigInteger(chainId));
    }

    public MnemonicAccountProvider(ISecretsProvider secretsProvider, uint accountId, uint chainId, string seedPassword = "")
        : this(secretsProvider.Secret, accountId, chainId, seedPassword)
    { }
}

PrivateKeyAccountProvider

The PrivateKeyAccountProvider is a class that generates an Ethereum account using a private key. This class provides two constructors:

  • The first constructor accepts a private key and a chain ID. It generates an account from the given private key for the specified chain.

  • The second constructor uses an instance of ISecretsProvider to obtain the private key. This can be useful when you have a secure way to store and retrieve the private key and want to keep it separate from your main application code.

Here is the code for PrivateKeyAccountProvider:

using Nethereum.Hex.HexTypes;
using Nethereum.Web3.Accounts;
using EthSmartContractIO.Providers;

namespace EthSmartContractIO.AccountProvider;

public class PrivateKeyAccountProvider : IAccountProvider
{
    public Account Account { get; private set; }

    public PrivateKeyAccountProvider(string privateKey, uint chainId)
    {
        Account = new Account(privateKey, new HexBigInteger(chainId));
    }

    public PrivateKeyAccountProvider(ISecretsProvider secretsProvider, uint chainId)
        : this(secretsProvider.Secret, chainId)
    { }
}

EthSmartContractIO.SecretsProvider

EthSmartContractIO.SecretsProvider is a NuGet package that provides a simple way to manage secrets in your Ethereum-based applications. It currently includes one secrets provider: EnvironmentSecretProvider.

Getting Started

To use EthSmartContractIO.SecretsProvider, you will need to add it as a dependency to your project. You can do this by adding it as a NuGet package:

.NET CLI

dotnet add package EthSmartContractIO.SecretsProvider

Package Manager

Install-Package EthSmartContractIO.SecretsProvider

Secrets Providers

The package provides a class for secret management. This class implements the ISecretsProvider interface, providing flexibility for different secret management mechanisms.

EnvironmentSecretProvider

EnvironmentSecretProvider is a class that retrieves a secret (such as a private key or a mnemonic) from AWS Secrets Manager.

Here is the code of EnvironmentSecretProvider:

using SecretsManager;
using EnvironmentManager;
using EthSmartContractIO.Providers;

namespace EthSmartContractIO.SecretsProvider;

public class EnvironmentSecretProvider : ISecretsProvider
{
    private static string SecretId =>
        EnvManager.GetEnvironmentValue<string>("SECRET_ID", raiseException: true);
    private static string SecretKey =>
        EnvManager.GetEnvironmentValue<string>("SECRET_KEY", raiseException: true);

    private readonly SecretManager secretManager;

    public EnvironmentSecretProvider(SecretManager? secretManager = null)
    {
        this.secretManager = secretManager ?? new SecretManager();
    }

    public virtual string Secret => secretManager.GetSecretValue(SecretId, SecretKey);
}

The EnvironmentSecretProvider uses the EnvManager to retrieve the environment variables SECRET_ID and SECRET_KEY. These are used as identifiers to fetch the actual secret from the AWS Secrets Manager via SecretManager.

Contribute

We welcome contributions from the community. Please submit pull requests for bug fixes, improvements and new features.

Happy coding!

More Information

RPC.Core Documentation

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on EthSmartContractIO:

Package Downloads
EthSmartContractIO.AccountProvider

A EthSmartContractIO module, offering account management features for Ethereum blockchains.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0 1,210 7/31/2023
0.9.0 265 6/14/2023

- Security audit by company 'The Arcadia Group'
- Updated 'Newtonsoft.Json' to 13.0.3
- One constructor of 'RpcRequest' instead of two constructors
- Added 'GetMethodHash' function in 'ContractIO' class