Loupe is an open source C# ASP.NET Core blockchain explorer for Ethereum based crypto coins made using Razor Pages and DotNet Core 2.1. It’s designed to be highly portable and will also eventually power the free hosted blockchain explorers for coins made with the CoinPress cryptocurrency generator. Installation is very simple and requires only downloading and setting execute permissions. By default it will attempt to connect to the RPC port of a local instance of a CoinPress wallet (https://blog.coinpress.cc/coinpress-guide/) so the easiest way is to just run the wallet on Windows first, but if you’re connecting to a CoinPress dedicated server or to the MainNet (or another coin entirely) you’ll need to update Web3Client.cs with the address and RPC port. I used http://gasprice.poa.network:8545 to test it against the MainNet and confirmed it working. Plans are in the works to have all the free CoinPress hosted nodes enable their RPC ports for public use and will probably dovetail with the release of a later version of this software.
This is a very alpha product and is being released early with the aim of showing developers how to read data from the blockchain. For the technical purposes of this project, Nethereum is used to talk to Geth and abstracts much of the heavy lifting involved in querying the blockchain. Fortunately, Nethereum was just recently updated to support ASP.NET Core 2.1 which really opens up the options on where the program can be hosted. I’ve tested on both Ubuntu 16.04 and Windows Server 2012 without any issues. Nethereum abstracts the Web3/RPC connection in a way that’s very close to the way the Ethereum web3.js works, so if you’re planning on using another language or library that implements it in a similarly faithful way it should be very simple to port the code.
Much of components involving CSS or HTML are out of the scope of this article and I will be covering only important code chunks and information that can be directly extrapolated to other blockchain projects. The explorer is built using Razor Pages which allows for the easy embedding of data, but I won’t really be concentrating on the plumbing of the pages.
If you’re rolling your own solution to access the blockchain, it may be helpful to know that I started by creating a new ASP.NET Core project on .net 2.1 SDK. I selected “Web Application” and unchecked the box “configure for https” to avoid certificate errors on wider-scale deployments as this program is going to end up on a lot of servers identified only by IP. For individual deployment, it’s up to your personal preference. It is important, however, to get the version of DotNet right for the Nethereum library. I tried running the DotNet 3.0 preview but it broke Nethereum for me when I tried it.
Nethereum.web3: Handles the connection to Geth. It allows you to grab most all information from the blockchain in just a few commands or less.
Namespace Nethereum.Hex.HexTypes: A ton of the Nethereum data comes back using the custom type “HexBigInteger”. This return type has a built-in conversion to more manageable units. f you get a returned variable of, say, “returnedData”, you can call “returnedData.Value” to get an automatic conversion to the type “BigInteger” from the System.Numerics namespace which then has an easy conversion to int.
Namespace Nethereum.RPC.Eth.DTOs: This will give you the types for the blocks returned from Ethereum, and keeps you from having to define your own classes for the data.
Watch out: as it’s easy to overflow a 32-bit integer with data returned from the blockchain. Keep this in mind when doing type conversions.
A lot of this will change as this codebase matures into more production-ready, but for right now there’s a few relatively simple commands that do most of the work. Much of the rest of the code is doing data type changes, handling exception cases, and manipulating the data that comes out of these commands.
There are 3 different connections here, and the first 2 are commented out but there to show how the various connections would be handled. The comments next to each line of code identify where that line of code would connect. This hard-coding of the address is temporary just to get the software working.
The rest of the file is basically wrapping a few lines of code that are doing most of the work.
You’ll want to use this in situations like the Top 50 page where you’re querying a multitude of blocks at once as otherwise the memory usage of the Web3 objects can skyrocket. This isn’t as noticeable on private blockchains but there’s a huge performance difference against the MainNet.
This grabs a transaction by hash. This is nice as it keeps you from having to iterate through blocks looking at all the transactions in them to find the match.
Take note of the Convert.FromWei.(account.Value) part. “account.Value” converts it from the Nethereum type HexBigInteger to just the System.Numeric BigInteger, but if you send this value back you’ll see a much larger number than you were expecting. Convert.FromWei() converts the value that’s returned as the Ethereum order of magnitude moniker “Wei” to the more manageable “Ether” you were probably expecting. This is preferred over the alternative of simply dividing the returned number by 1000000000000000000.
Reminder: Watch your data types as they’re easy to overflow unexpectedly with the data you’re going to get back from the blockchain.
If you don’t do either of these, you’ll get a green squiggly line under the code and a fun race condition.
Block numbers are distinguished as being integers.
Addresses are hashes that can be distinguished as being exactly 42 bytes.
Block and transaction hashes are both 66 bytes, which distinguishes them as hashes but amongst the two of them I’m not aware of a good way to differentiate them just by looking at them.
To differentiate between transaction hashes and block hashes, I check and see if the 66 byte hash is a valid transaction and then default to it being a block if it’s not. There may be a better way to do this, the exception isn’t handled properly, and it’s possible the order could affect performance as well.
At the time of writing, CoinPress downloadable server nodes come with RPC disabled. Although the public CoinPress servers will soon support RPC connections, the downloadable ones will likely remain opt-in for security reasons.
NOTE! This opens your RPC server to anybody. There are a bunch of options (https://github.com/ethereum/wiki/wiki/JSON-RPC) you can configure. It’s not recommended to use this exact configuration in production, but makes it much easier to work with in testing.
There’s no caching of results. This likely will not scale well.
The Top 50 page is currently hard coded to “top 10” due to the lack of caching.
The Top 50 page also appears to have some sort of memory leak. Requesting the page a bunch of times causes the memory use to rise and not release. It might be related to garbage collection.
Error handling isn’t perfect. There’s still an occasional exception on a page when it’s having trouble hitting the RPC host.
A lot of the formatting can use some work.
You may run into an issue where you need to expose IIS Express to more than just localhost if you’re just running it straight out of IIS Express/Visual Studio. If you don’t do this, you may only be able to get to the blockchain explorer from the host it’s running on.