bitcoin-s/docs/rpc/bitcoind.md
Chris Stewart 89f1db6ca7
Make imports in chain.md invisible (#1213)
* Make imports in chain.md invisible

* Hide imports in wallet.md

* Make all core module md files imports hidden

* Cleanup imports on rpc markdown docs

* Try and figure weird travis behavior

* Get rid of uneeded nest qualifiers on mdoc
2020-03-10 12:49:22 -05:00

4 KiB

id title
rpc-bitcoind bitcoind/Bitcoin Core

Note: bitcoin-s-bitcoind-rpc requires you to have bitcoind (Bitcoin Core daemon) installed. Grab this at bitcoincore.org

The Bitcoin Core RPC client in Bitcoin-S currently supports the Bitcoin Core 0.16, 0.17, 0.18, and 0.19 version lines. It can be set up to work with both local and remote Bitcoin Core servers.

You can fetch them using bitcoin-s by running the following sbt command

sbt downloadBitcoind

The binaries will be stored in $HOME/.bitcoin-s/binaries/bitcoind/

Connecting to a local bitcoind instance

Getting started quickly, with default options:

import scala.concurrent._

import org.bitcoins.{rpc, core}
import rpc.client.common._
import java.io._
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
import org.bitcoins.core.crypto._
import org.bitcoins.core.protocol._
import org.bitcoins.core.currency._


implicit val ec: ExecutionContext = ExecutionContext.global

// this reads authentication credentials and
// connection details from the default data
// directory on your platform
val client = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir"))

val balance: Future[Bitcoins] = for {
  _ <- client.start()
  balance <- client.getBalance
} yield balance

Connecting to a remote bitcoind

First, we create a secure connection to our bitcoind instance by setting up a SSH tunnel:

$ ssh -L 8332:localhost:8332  \
         my-cool-user@my-cool-website.com

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


implicit val ec: ExecutionContext = ExecutionContext.global

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

val authCredentials = BitcoindAuthCredentials.PasswordBased(
  username = username,
  password = password
)

val bitcoindInstance = {
  BitcoindInstance (
    network = MainNet,
    uri = new URI(s"http://localhost:${MainNet.port}"),
    rpcUri = new URI(s"http://localhost:${MainNet.rpcPort}"),
    authCredentials = authCredentials
  )
}

val rpcCli = BitcoindRpcClient(bitcoindInstance)

rpcCli.getBalance.onComplete { case balance =>
  println(s"Wallet balance=${balance}")
}

Error handling

All errors returned by Bitcoin Core are mapped to a corresponding BitcoindException. 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:


implicit val ec = ExecutionContext.global

// let's assume you have an already running client,
// so there's no need to start this one
val cli = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir"))

// let's also assume you have a bitcoin address
val address: BitcoinAddress = ???

val txid: Future[DoubleSha256DigestBE] =
  cli.sendToAddress(address, 3.bitcoins).recoverWith {
    case BitcoindWalletException.UnlockNeeded(_) =>
      cli.walletPassphrase("my_passphrase", 60).flatMap { _ =>
        cli.sendToAddress(address, 3.bitcoins)
      }
  }