2019-05-15 01:05:14 +02:00
---
id: rpc-bitcoind
title: bitcoind/Bitcoin Core
---
2021-01-14 21:02:12 +01:00
## Downloading bitcoind
The Bitcoin Core RPC client in Bitcoin-S currently supports the Bitcoin Core
- 0.16
- 0.17
- 0.18
- 0.19
- 0.20
- 0.21
2021-11-19 20:58:27 +01:00
- 22
2019-05-15 01:05:14 +02:00
version lines. It can be set up to work with both local and remote Bitcoin Core servers.
2021-01-14 21:02:12 +01:00
You can fetch them using bitcoin-s by running the following sbt command. If you already have bitcoind installed on your machine, you can skip this step.
2020-03-10 18:49:22 +01:00
```bash
sbt downloadBitcoind
```
2021-01-14 21:02:12 +01:00
The binaries will be stored in `~/.bitcoin-s/binaries/bitcoind/`
2020-03-10 18:49:22 +01:00
2019-05-15 01:05:14 +02:00
## Connecting to a local `bitcoind` instance
2019-05-31 14:13:51 +02:00
### Getting started quickly, with default options:
2020-03-10 18:49:22 +01:00
```scala mdoc:invisible
2019-05-15 01:05:14 +02:00
import scala.concurrent._
2019-10-01 13:19:11 +02:00
import java.io._
2020-03-10 18:49:22 +01:00
import java.net.URI
import org.bitcoins.core.config._
import org.bitcoins.rpc.config._
import org.bitcoins.rpc.client.common._
import org.bitcoins.rpc.BitcoindWalletException
2020-04-30 19:34:53 +02:00
import org.bitcoins.crypto._
2020-03-10 18:49:22 +01:00
import org.bitcoins.core.protocol._
import org.bitcoins.core.currency._
2021-09-07 15:49:01 +02:00
import akka.actor.ActorSystem
2020-03-10 18:49:22 +01:00
```
```scala mdoc:compile-only
2019-05-15 01:05:14 +02:00
2019-08-30 22:12:18 +02:00
implicit val ec: ExecutionContext = ExecutionContext.global
2021-09-07 15:49:01 +02:00
implicit val system = ActorSystem("System")
2019-05-31 14:13:51 +02:00
// this reads authentication credentials and
// connection details from the default data
// directory on your platform
2019-10-01 13:19:11 +02:00
val client = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir"))
2019-05-15 01:05:14 +02:00
val balance: Future[Bitcoins] = for {
_ < - client . start ( )
balance < - client . getBalance
} yield balance
```
2020-11-07 16:24:09 +01:00
## Multi-wallet `bitcoind` instances
When using the `bitcoind` with multiple wallets you will need to specify the wallet's name.
To do so the wallet rpc functions have an optional `walletName` parameter.
```scala mdoc:compile-only
implicit val ec: ExecutionContext = ExecutionContext.global
2021-09-07 15:49:01 +02:00
implicit val system = ActorSystem("System")
2020-11-07 16:24:09 +01:00
val client = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir"))
for {
_ < - client . start ( )
_ < - client . walletPassphrase ( " mypassword " , 10000 , Some ( " walletName " ) )
balance < - client . getBalance ( " walletName " )
2021-07-01 13:34:10 +02:00
} yield balance
2020-11-07 16:24:09 +01:00
```
2019-05-15 01:05:14 +02:00
## Connecting to a remote `bitcoind`
First, we create a secure connection to our `bitcoind` instance by setting
up a SSH tunnel:
```bash
2021-01-14 21:02:12 +01:00
ssh -L 8332:localhost:8332 my-cool-user@my-cool-website.com
2019-05-15 01:05:14 +02:00
```
> Note: the port number '8332' is the default for mainnet. If you want to
> connect to a testnet `bitcoind`, the default port is '18332'
Now that we have a secure connection between our remote `bitcoind` , we're
ready to create the connection with our RPC client
```scala mdoc:compile-only
2020-03-10 18:49:22 +01:00
implicit val ec: ExecutionContext = ExecutionContext.global
2021-09-07 15:49:01 +02:00
implicit val system = ActorSystem("System")
2019-05-15 01:05:14 +02:00
val username = "FILL_ME_IN" //this username comes from 'rpcuser' in your bitcoin.conf file
val password = "FILL_ME_IN" //this password comes from your 'rpcpassword' in your bitcoin.conf file
2019-05-31 14:13:51 +02:00
val authCredentials = BitcoindAuthCredentials.PasswordBased(
2019-05-15 01:05:14 +02:00
username = username,
2019-05-31 14:13:51 +02:00
password = password
2019-05-15 01:05:14 +02:00
)
val bitcoindInstance = {
2021-09-07 15:49:01 +02:00
BitcoindInstanceLocal(
2019-05-15 01:05:14 +02:00
network = MainNet,
2019-05-31 14:13:51 +02:00
uri = new URI(s"http://localhost:${MainNet.port}"),
rpcUri = new URI(s"http://localhost:${MainNet.rpcPort}"),
2019-05-15 01:05:14 +02:00
authCredentials = authCredentials
)
}
2019-08-30 22:12:18 +02:00
val rpcCli = BitcoindRpcClient(bitcoindInstance)
2019-05-15 01:05:14 +02:00
rpcCli.getBalance.onComplete { case balance =>
println(s"Wallet balance=${balance}")
}
```
2019-07-11 14:58:17 +02:00
## Error handling
All errors returned by Bitcoin Core are mapped to a corresponding
[`BitcoindException` ](https://github.com/bitcoin-s/bitcoin-s/blob/master/bitcoind-rpc/src/main/scala/org/bitcoins/rpc/BitcoindException.scala ).
These exceptions contain an error code and a message. `BitcoindException` is a sealed
trait, which means you can easily pattern match exhaustively. Of course, other errors
could also happen: network errors, stack overflows or out-of-memory errors. The provided
class is only intended to cover errors returned by Bitcoin Core. An example of how error
handling could look:
```scala mdoc:compile-only
2019-08-30 22:12:18 +02:00
implicit val ec = ExecutionContext.global
2019-07-11 14:58:17 +02:00
// let's assume you have an already running client,
// so there's no need to start this one
2019-10-01 13:19:11 +02:00
val cli = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir"))
2019-07-11 14:58:17 +02:00
// let's also assume you have a bitcoin address
2021-07-01 13:34:10 +02:00
val address: BitcoinAddress = BitcoinAddress("bc1qm8kec4xvucdgtzppzvvr2n6wp4m4w0k8akhf98")
2019-07-11 14:58:17 +02:00
val txid: Future[DoubleSha256DigestBE] =
cli.sendToAddress(address, 3.bitcoins).recoverWith {
case BitcoindWalletException.UnlockNeeded(_) =>
cli.walletPassphrase("my_passphrase", 60).flatMap { _ =>
cli.sendToAddress(address, 3.bitcoins)
}
}
```