blockchain-rpc
blockchain-rpc is a typesafe RPC client for Bitcoin, Ethereum and Omni written for Scala 2.12 or 2.13. Under the hood, it's using http4s, circe and cats-effect. We appreciate external contributions, please check issues for inspiration. For all examples, check: src/main/scala/examples. We're planning a non IO-monad interface soon which makes it easier to use with Java and without Cats-effect knowledge.
Add Dependency
Simply add the following dependency to your project.
libraryDependencies += "io.tokenanalyst" %% "blockchain-rpc" % "2.5.2"
Example: Fetch Bitcoin Block
This is a simple example of how the RPCClient is generally used. We're using Cats Resources here which automatically deallocate any opened resources after use.
import cats.effect.{ExitCode, IO, IOApp}
import scala.concurrent.ExecutionContext.global
import io.tokenanalyst.blockchainrpc.RPCClient
import io.tokenanalyst.blockchainrpc.bitcoin.Syntax._
object GetBlockHash extends IOApp {
def run(args: List[String]): IO[ExitCode] = {
implicit val ec = global
RPCClient
.bitcoin(
Seq(127.0.0.1),
username = "tokenanalyst",
password = "!@#$%^&*(2009"
)
.use { bitcoin =>
for {
block <- bitcoin.getBlockByHash(
"0000000000000000000759de6ab39c2d8fb01e4481ba581761ddc1d50a57358d"
)
_ <- IO { println(block) }
} yield ExitCode(0)
}
}
}
Example: Catch up bitcoin from block zero
This example makes use of the EnvConfig import, which automatically configures RPC via ENV flags exported in the shell. The environment flags for it are BLOCKCHAIN_RPC_HOSTS
, BLOCKCHAIN_RPC_USERNAME
, BLOCKCHAIN_RPC_PASSWORD
.
import io.tokenanalyst.blockchainrpc.Bitcoin
import io.tokenanalyst.blockchainrpc.{RPCClient, Config}
import io.tokenanalyst.blockchainrpc.bitcoin.Syntax._
object CatchupFromZero extends IOApp {
def loop(rpc: Bitcoin, current: Long = 0L, until: Long = 10L): IO[Unit] =
for {
block <- rpc.getBlockByHeight(current)
_ <- IO { println(block) }
l <- if (current + 1 < until) loop(rpc, current + 1, until) else IO.unit
} yield l
def run(args: List[String]): IO[ExitCode] = {
implicit val ec = global
implicit val config = Config.fromEnv
RPCClient
.bitcoin(config.hosts, config.port, config.username, config.password)
.use { rpc =>
for {
_ <- loop(rpc)
} yield ExitCode(0)
}
}
}
Example: Fetch an Ethereum block by hash
In this example, the Ethereum syntax is used to fetch a specific block. It uses HexTools
to parse the blocknumber and prints the contents of the block. RPC configuration is acquired from the env vars BLOCKCHAIN_RPC_HOSTS
, BLOCKCHAIN_RPC_USERNAME
, and BLOCKCHAIN_RPC_PASSWORD
.
package io.tokenanalyst.blockchainrpc.examples.ethereum
import cats.effect.{ExitCode, IO, IOApp}
import scala.concurrent.ExecutionContext.global
import io.tokenanalyst.blockchainrpc.{RPCClient, Config}
import io.tokenanalyst.blockchainrpc.ethereum.Syntax._
import io.tokenanalyst.blockchainrpc.ethereum.HexTools
object GetEthereumBlockByHash extends IOApp {
def run(args: List[String]): IO[ExitCode] = {
implicit val ec = global
implicit val config = Config.fromEnv
RPCClient
.ethereum(
config.hosts,
config.port,
config.username,
config.password
)
.use { ethereum =>
for {
block <- ethereum.getBlockByHash(
"0x3bad41c70c9efac92490e8a74ab816558bbdada0984f2bcfa4cb1522ddb3ca16"
)
_ <- IO { println(s"block ${HexTools.parseQuantity(block.number)}: $block") }
} yield ExitCode(0)
}
}
}
Supported Bitcoin methods
blockchain-rpc method | description | bitcoin rpc method |
---|---|---|
getBlockHash(height: Long) | Gets the block hash at a specific height | getblockhash |
getBestBlockHash() | Gets the block tip hash | getbestblockhash |
getBlockByHash(hash: String) | Gets the block with transaction ids | getblock |
getBlockByHeight(height: Long) | Gets the block with transaction ids | getblockhash , getblock |
getTransaction(hash: String) | Gets raw transaction data | getrawtransaction |
getTransactions(hashes: Seq[String]) | Gets raw transaction data | batch of getrawtransaction |
estimateSmartFee(height: Long) | Estimates fee for include in block n | estimatesmartfee |
getNextBlockHash() | Gets next block hash subscription | usage of ZeroMQ |
Supported Ethereum methods
blockchain-rpc method | description | ethereum rpc method |
---|---|---|
getBlockByHeight(long: Height) | Get a block by height | eth_getBlockByNumber |
getBlockByHash(hash: String) | Get a block by hash | eth_getBlockByHash |
getBestBlockHeight | Get the best block height | eth_blockNumber |
getTransaction(hash: String) | Get a transaction by hash | eth_getTransactionByHash |
getTransactions(hashes: Seq[String]) | Get a batch of transaction by hash | eth_getTransactionByHash |
getReceiptByHash(hash: String) | Get a transaction receipt by hash | eth_getTransactionReceipt |
getReceiptsByHash(hashes: Seq[String]) | Get transaction receipts by hashes | Batch of eth_getTransactionReceipt |
Environment Variables
variable | description | type |
---|---|---|
BLOCKCHAIN_RPC_HOSTS |
Comma-seperated IP list or hostname of full nodes | String |
BLOCKCHAIN_RPC_USERNAME |
RPC username | Optional String |
BLOCKCHAIN_RPC_PASSWORD |
RPC password | Optional String |
BLOCKCHAIN_RPC_PORT |
RPC port when not default | Optional Int |
BLOCKCHAIN_RPC_ZEROMQ_PORT |
ZeroMQ port when not default | Optional Int |