Skip to content

Commit b8087e8

Browse files
Nethereum.AccountAbstraction: RpcServer, gas estimation, validation helper, NuGet packaging
Add Bundler.RpcServer project — standalone JSON-RPC server exposing ERC-4337 bundler methods (eth_sendUserOperation, eth_estimateUserOperationGas, eth_getUserOperationReceipt, etc.) plus debug_bundler_* admin methods. Includes DI setup, DevChain integration, and integration tests. Add TransactionExecutorGasEstimator for EVM-based gas estimation via TransactionExecutor. Add ValidationDataHelper for time/block-range validity checking (ERC-4337 validAfter/validUntil with bit-47 block range flag). Refactor InMemoryUserOpMempool to use ValidationDataHelper for consistent timestamp evaluation. Update EntryPoint address in RocksDB mempool tests. Upgrade AccountAbstraction, Bundler, and SimpleAccount csprojs to multi-target frameworks, strong naming, versioning, and NuGet packaging with READMEs.
1 parent 6918a5f commit b8087e8

37 files changed

Lines changed: 3171 additions & 8 deletions

File tree

src/Nethereum.AccountAbstraction.Bundler.RocksDB/Nethereum.AccountAbstraction.Bundler.RocksDB.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<Description>Nethereum Account Abstraction Bundler RocksDB - Persistent storage for ERC-4337 bundler mempool and reputation</Description>
55
<AssemblyTitle>Nethereum.AccountAbstraction.Bundler.RocksDB</AssemblyTitle>
66
<Version>$(NethereumVersion)</Version>
7-
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
7+
<TargetFrameworks>$(CoreChainFrameworks)</TargetFrameworks>
88
<AssemblyName>Nethereum.AccountAbstraction.Bundler.RocksDB</AssemblyName>
99
<PackageId>Nethereum.AccountAbstraction.Bundler.RocksDB</PackageId>
1010
<ImplicitUsings>enable</ImplicitUsings>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using System.Numerics;
2+
3+
namespace Nethereum.AccountAbstraction.Bundler.RpcServer.Configuration
4+
{
5+
public class BundlerRpcServerConfig
6+
{
7+
public string Host { get; set; } = "localhost";
8+
public int Port { get; set; } = 4337;
9+
public string RpcUrl { get; set; } = "http://localhost:8545";
10+
public BigInteger ChainId { get; set; } = 1;
11+
public string[] SupportedEntryPoints { get; set; } = Array.Empty<string>();
12+
public string BeneficiaryAddress { get; set; } = null!;
13+
public string? PrivateKey { get; set; }
14+
public int MaxBundleSize { get; set; } = 10;
15+
public int MaxMempoolSize { get; set; } = 1000;
16+
public BigInteger MinPriorityFeePerGas { get; set; } = 0;
17+
public BigInteger MaxBundleGas { get; set; } = 15_000_000;
18+
public int AutoBundleIntervalMs { get; set; } = 10_000;
19+
public bool StrictValidation { get; set; } = true;
20+
public bool SimulateValidation { get; set; } = true;
21+
public bool UnsafeMode { get; set; } = false;
22+
public bool Verbose { get; set; } = false;
23+
public bool EnableDebugMethods { get; set; } = false;
24+
25+
public BundlerConfig ToBundlerConfig()
26+
{
27+
return new BundlerConfig
28+
{
29+
SupportedEntryPoints = SupportedEntryPoints,
30+
BeneficiaryAddress = BeneficiaryAddress,
31+
MaxBundleSize = MaxBundleSize,
32+
MaxMempoolSize = MaxMempoolSize,
33+
MinPriorityFeePerGas = MinPriorityFeePerGas,
34+
MaxBundleGas = MaxBundleGas,
35+
AutoBundleIntervalMs = AutoBundleIntervalMs,
36+
StrictValidation = StrictValidation,
37+
SimulateValidation = SimulateValidation,
38+
UnsafeMode = UnsafeMode,
39+
ChainId = ChainId
40+
};
41+
}
42+
43+
public static BundlerRpcServerConfig CreateDefault(
44+
string entryPoint,
45+
string beneficiary,
46+
string rpcUrl,
47+
BigInteger chainId)
48+
{
49+
return new BundlerRpcServerConfig
50+
{
51+
SupportedEntryPoints = new[] { entryPoint },
52+
BeneficiaryAddress = beneficiary,
53+
RpcUrl = rpcUrl,
54+
ChainId = chainId
55+
};
56+
}
57+
58+
public static BundlerRpcServerConfig CreateAppChainConfig(
59+
string entryPoint,
60+
string beneficiary,
61+
string rpcUrl,
62+
BigInteger chainId)
63+
{
64+
return new BundlerRpcServerConfig
65+
{
66+
SupportedEntryPoints = new[] { entryPoint },
67+
BeneficiaryAddress = beneficiary,
68+
RpcUrl = rpcUrl,
69+
ChainId = chainId,
70+
StrictValidation = false,
71+
AutoBundleIntervalMs = 1000,
72+
MinPriorityFeePerGas = 0,
73+
UnsafeMode = true
74+
};
75+
}
76+
}
77+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Logging;
3+
using Nethereum.AccountAbstraction.Bundler.RpcServer.Rpc;
4+
using Nethereum.CoreChain.Rpc;
5+
using Nethereum.Web3;
6+
7+
namespace Nethereum.AccountAbstraction.Bundler.RpcServer.Configuration
8+
{
9+
public static class ServiceCollectionExtensions
10+
{
11+
public static IServiceCollection AddBundlerRpcServer(
12+
this IServiceCollection services,
13+
BundlerRpcServerConfig config)
14+
{
15+
services.AddSingleton(config);
16+
17+
services.AddSingleton<IWeb3>(provider =>
18+
{
19+
if (!string.IsNullOrEmpty(config.PrivateKey))
20+
{
21+
var account = new Nethereum.Web3.Accounts.Account(config.PrivateKey, config.ChainId);
22+
return new Web3.Web3(account, config.RpcUrl);
23+
}
24+
return new Web3.Web3(config.RpcUrl);
25+
});
26+
27+
services.AddSingleton<BundlerService>(provider =>
28+
{
29+
var web3 = provider.GetRequiredService<IWeb3>();
30+
var bundlerConfig = config.ToBundlerConfig();
31+
return new BundlerService(web3, bundlerConfig);
32+
});
33+
34+
services.AddSingleton<IBundlerService>(provider =>
35+
provider.GetRequiredService<BundlerService>());
36+
37+
services.AddSingleton<IBundlerServiceExtended>(provider =>
38+
provider.GetRequiredService<BundlerService>());
39+
40+
services.AddSingleton<RpcHandlerRegistry>(provider =>
41+
{
42+
var bundler = provider.GetRequiredService<BundlerService>();
43+
var registry = new RpcHandlerRegistry();
44+
45+
registry.AddBundlerHandlers(bundler);
46+
47+
if (config.EnableDebugMethods)
48+
{
49+
registry.AddBundlerDebugHandlers(bundler);
50+
}
51+
52+
return registry;
53+
});
54+
55+
services.AddSingleton<RpcContext>(provider =>
56+
{
57+
return new RpcContext(null!, config.ChainId, provider);
58+
});
59+
60+
services.AddSingleton<RpcDispatcher>(provider =>
61+
{
62+
var registry = provider.GetRequiredService<RpcHandlerRegistry>();
63+
var context = provider.GetRequiredService<RpcContext>();
64+
var logger = config.Verbose
65+
? provider.GetService<ILogger<RpcDispatcher>>()
66+
: null;
67+
return new RpcDispatcher(registry, context, logger);
68+
});
69+
70+
return services;
71+
}
72+
73+
public static IServiceCollection AddBundlerRpcServer(
74+
this IServiceCollection services,
75+
BundlerRpcServerConfig config,
76+
BundlerService existingBundler)
77+
{
78+
services.AddSingleton(config);
79+
services.AddSingleton(existingBundler);
80+
services.AddSingleton<IBundlerService>(existingBundler);
81+
services.AddSingleton<IBundlerServiceExtended>(existingBundler);
82+
83+
services.AddSingleton<RpcHandlerRegistry>(provider =>
84+
{
85+
var bundler = provider.GetRequiredService<BundlerService>();
86+
var registry = new RpcHandlerRegistry();
87+
88+
registry.AddBundlerHandlers(bundler);
89+
90+
if (config.EnableDebugMethods)
91+
{
92+
registry.AddBundlerDebugHandlers(bundler);
93+
}
94+
95+
return registry;
96+
});
97+
98+
services.AddSingleton<RpcContext>(provider =>
99+
{
100+
return new RpcContext(null!, config.ChainId, provider);
101+
});
102+
103+
services.AddSingleton<RpcDispatcher>(provider =>
104+
{
105+
var registry = provider.GetRequiredService<RpcHandlerRegistry>();
106+
var context = provider.GetRequiredService<RpcContext>();
107+
var logger = config.Verbose
108+
? provider.GetService<ILogger<RpcDispatcher>>()
109+
: null;
110+
return new RpcDispatcher(registry, context, logger);
111+
});
112+
113+
return services;
114+
}
115+
}
116+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
3+
<PropertyGroup>
4+
<Description>Nethereum AccountAbstraction Bundler RpcServer - Standalone ERC-4337 bundler JSON-RPC server</Description>
5+
<AssemblyTitle>Nethereum.AccountAbstraction.Bundler.RpcServer</AssemblyTitle>
6+
<Version>$(NethereumVersion)</Version>
7+
<TargetFramework>$(ServerFrameworks)</TargetFramework>
8+
<AssemblyName>Nethereum.AccountAbstraction.Bundler.RpcServer</AssemblyName>
9+
<PackageId>Nethereum.AccountAbstraction.Bundler.RpcServer</PackageId>
10+
<PackageReadmeFile>README.md</PackageReadmeFile>
11+
<ImplicitUsings>enable</ImplicitUsings>
12+
<Nullable>enable</Nullable>
13+
<OutputType>Exe</OutputType>
14+
<RootNamespace>Nethereum.AccountAbstraction.Bundler.RpcServer</RootNamespace>
15+
</PropertyGroup>
16+
17+
<ItemGroup>
18+
<None Include="README.md" Pack="true" PackagePath="" />
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<ProjectReference Include="..\Nethereum.AccountAbstraction.Bundler\Nethereum.AccountAbstraction.Bundler.csproj" />
23+
<ProjectReference Include="..\Nethereum.AccountAbstraction\Nethereum.AccountAbstraction.csproj" />
24+
<ProjectReference Include="..\Nethereum.CoreChain\Nethereum.CoreChain.csproj" />
25+
<ProjectReference Include="..\Nethereum.RPC\Nethereum.RPC.csproj" />
26+
<ProjectReference Include="..\Nethereum.Web3\Nethereum.Web3.csproj" />
27+
</ItemGroup>
28+
<PropertyGroup Condition=" '$(TargetFramework)' != 'net35' And '$(TargetUnityNet461AOT)' != 'true'">
29+
<SignAssembly>true</SignAssembly>
30+
<AssemblyOriginatorKeyFile>..\..\NethereumKey.snk</AssemblyOriginatorKeyFile>
31+
</PropertyGroup>
32+
<ItemGroup Condition=" '$(TargetFramework)' != 'net35' And '$(TargetUnityNet461AOT)' != 'true'">
33+
<None Include="..\..\NethereumKey.snk" />
34+
</ItemGroup>
35+
36+
</Project>

0 commit comments

Comments
 (0)