The rockchain package provides simple interfaces to coinmarketcap.com ticker and market cap data and blockchain.info ticker and Bitcoin wallet data. The current package does not yet support additional blockchain APIs, but will in the future. For now, it offers cryptocurrency market data retrieval and Bitcoin wallet transaction data retrieval via the two currently available APIs.

Ticker and marketcap data

The default API for ticker and market cap data is the coinmarketcap.com API. The site provides up-to-date cryptocurrency prices for Bitcoin and over a thousand “altcoins” (non-Bitcoin cryptocurrencies). While Bitcoin enjoys a large percentage of the total global cryptocurrency market cap, a number of altcoins also have large market caps, at least by current cryptocurrency standards. These include altcoins such as Ethereum (ETH) and Litecoin (LTC). Many others do not. And many of these that also do not have much to offer in terms of known technological or practical value are sometimes referred to as shitcoins; Buyer beware.

The coinmarketcap.com ticker

To look at the entire ticker from coinmarketcap.com all you need is to call cap(). Below are several ways you can use cap. First return the entire ticker with cryptocurrency prices in USD.

library(rockchain)
cap()
#> # A tibble: 1,596 x 15
#>    id         name       symbol rank  price_usd price_btc `24h_volume_usd`
#>    <chr>      <chr>      <chr>  <fct>     <dbl>     <dbl>            <dbl>
#>  1 bitcoin    Bitcoin    BTC    1      6756     1.00            4087320000
#>  2 ethereum   Ethereum   ETH    2       379     0.0565          1085240000
#>  3 ripple     Ripple     XRP    3         0.493 0.0000736        223847000
#>  4 bitcoin-c~ Bitcoin C~ BCH    4       660     0.0984           286396000
#>  5 litecoin   Litecoin   LTC    5       113     0.0169           253058000
#>  6 eos        EOS        EOS    6         5.76  0.000859         204308000
#>  7 cardano    Cardano    ADA    7         0.148 0.0000221        108073000
#>  8 stellar    Stellar    XLM    8         0.200 0.0000299         64459900
#>  9 neo        NEO        NEO    9        48.2   0.00719           58079400
#> 10 iota       IOTA       MIOTA  10        1.06  0.000158          25621200
#> # ... with 1,586 more rows, and 8 more variables: market_cap_usd <dbl>,
#> #   available_supply <dbl>, total_supply <dbl>, max_supply <dbl>,
#> #   percent_change_1h <dbl>, percent_change_24h <dbl>,
#> #   percent_change_7d <dbl>, last_updated <dbl>

The first argument, crypto, is NULL by default. Alternatively, passing it an integer will return the top crypto number of cryptocurrencies by market cap as a tibble data frame.

cap(crypto = 5)
#> # A tibble: 5 x 15
#>   id          name       symbol rank  price_usd price_btc `24h_volume_usd`
#>   <chr>       <chr>      <chr>  <fct>     <dbl>     <dbl>            <dbl>
#> 1 bitcoin     Bitcoin    BTC    1      6756     1.00            4087320000
#> 2 ethereum    Ethereum   ETH    2       379     0.0565          1085240000
#> 3 ripple      Ripple     XRP    3         0.493 0.0000736        223847000
#> 4 bitcoin-ca~ Bitcoin C~ BCH    4       660     0.0984           286396000
#> 5 litecoin    Litecoin   LTC    5       113     0.0169           253058000
#> # ... with 8 more variables: market_cap_usd <dbl>, available_supply <dbl>,
#> #   total_supply <dbl>, max_supply <dbl>, percent_change_1h <dbl>,
#> #   percent_change_24h <dbl>, percent_change_7d <dbl>, last_updated <dbl>

If you want ticker data for specific cryptocurrencies, you can filter the results of cap() or you can specify them during the call. Passing a single cryptocurrency ticker symbol vs. more than one technically uses two different API endpoints but the results are formatted to what you would expect. Note that symbols are not case sensitive: e.g., "btc" is the same as "BTC".

cap(crypto = "BTC")
#> # A tibble: 1 x 15
#>   id      name    symbol rank  price_usd price_btc `24h_volume_usd`
#>   <chr>   <chr>   <chr>  <fct>     <dbl>     <dbl>            <dbl>
#> 1 bitcoin Bitcoin BTC    1          6756      1.00       4087320000
#> # ... with 8 more variables: market_cap_usd <dbl>, available_supply <dbl>,
#> #   total_supply <dbl>, max_supply <dbl>, percent_change_1h <dbl>,
#> #   percent_change_24h <dbl>, percent_change_7d <dbl>, last_updated <dbl>

cap(crypto = c("ETH", "LTC"))
#> # A tibble: 2 x 15
#>   id       name     symbol rank  price_usd price_btc `24h_volume_usd`
#>   <chr>    <chr>    <chr>  <fct>     <dbl>     <dbl>            <dbl>
#> 1 ethereum Ethereum ETH    2           379    0.0565       1085240000
#> 2 litecoin Litecoin LTC    5           113    0.0169        253058000
#> # ... with 8 more variables: market_cap_usd <dbl>, available_supply <dbl>,
#> #   total_supply <dbl>, max_supply <dbl>, percent_change_1h <dbl>,
#> #   percent_change_24h <dbl>, percent_change_7d <dbl>, last_updated <dbl>

The results always include USD and Bitcoin price, USD market cap and USD 24-hour trading volume by default. Using convert to obtain price, market cap and volume in other currencies adds new columns onto the end of the table. convert may be a vector. It may also include other cryptocurrency symbols, not just fiat currencies.

library(dplyr)
cap(crypto = "ETH", convert = c("EUR", "GBP")) %>% select(16:21)
#> # A tibble: 1 x 6
#>   price_eur  `24h_volume_eur` market_cap_eur price_gbp   `24h_volume_gbp`
#>   <chr>      <chr>            <chr>          <chr>       <chr>           
#> 1 307.253838 880129640.0      30278163596.0  270.2772972 774210216.0     
#> # ... with 1 more variable: market_cap_gbp <chr>

cap(crypto = "BTC", convert = "ETH") %>% select(16:18)
#> # A tibble: 1 x 3
#>   price_eth     `24h_volume_eth` market_cap_eth
#>   <chr>         <chr>            <chr>         
#> 1 17.6911817434 10703134.5788    299886972.0

Total global market cap

The easiest way to obtain the total global market cap of all cryptocurrencies is to use the global endpoint of the coinmarketcap.com API. This is done by passing crypto = "global".

cap(crypto = "global")
#> # A tibble: 1 x 7
#>   last_updated total_market_cap total_24h_volume bitcoin_percentage_of_ma~
#>          <int>            <dbl>            <dbl>                     <dbl>
#> 1   1522569267     253798766793      10051416887                      45.1
#> # ... with 3 more variables: active_currencies <int>, active_assets <int>,
#> #   active_markets <int>

At this point you have seen three different ways to specify crypto: either as NULL to yield the full ticker, an integer to yield to top coins by market cap, or as a character vector ticker symbols for the specific cryptocurrencies of interest.

blockchain.info ticker

If you are looking at Bitcoin only and working specifically with the blockchain.info API, you can also obtain ticker information for Bitcoin with bcinfo. There is only a fiat argument, analogous to convert, since blockchain.info is specific to Bitcoin and ticker results from the API are only available in fiat currencies.

bcinfo()
#> # A tibble: 22 x 6
#>      `15m`    last     buy    sell symbol currency
#>      <dbl>   <dbl>   <dbl>   <dbl> <chr>  <chr>   
#>  1    6703    6703    6703    6703 $      USD     
#>  2    8725    8725    8725    8725 $      AUD     
#>  3   22153   22153   22153   22153 R$     BRL     
#>  4    8649    8649    8649    8649 $      CAD     
#>  5    6396    6396    6396    6396 CHF    CHF     
#>  6 4047954 4047954 4047954 4047954 $      CLP     
#>  7   42140   42140   42140   42140 ¥      CNY     
#>  8   40543   40543   40543   40543 kr     DKK     
#>  9    5428    5428    5428    5428 €      EUR     
#> 10    4782    4782    4782    4782 £      GBP     
#> # ... with 12 more rows

bcinfo(fiat = "GBP")
#> # A tibble: 1 x 6
#>   `15m`  last   buy  sell symbol currency
#>   <dbl> <dbl> <dbl> <dbl> <chr>  <chr>   
#> 1  4782  4782  4782  4782 £      GBP

Wrappers for ticker function

Both of these functions wrap around ticker and exist to provide some basic separation of the different behavior of the two APIs and the kind of data they provide. If you use ticker directly, more attention should be paid to the different handling of ticker arguments depending on whether you specify the default api = "coinmarketcap.com" or the alternative api = "blockchain.info". Using the default API, the two functions are essentially the same, and slightly different with the alternative. See the help documentation for details. The following pairs are equivalent calls.

ticker()
cap()

ticker(crypto = 5)
cap(crypto = 5)

ticker(crypto = c("ETH", "LTC"), convert = c("EUR", "GBP", "BTC"))
cap(crypto = c("ETH", "LTC"), convert = c("EUR", "GBP", "BTC"))

ticker(convert = NULL, api = "blockchain.info")
bcinfo()

Wallet transaction data

The current version of rockchain supports Bitcoin wallet data retrieval from the Bitcoin blockchain using the blockchain.info API. Future package versions will add support for other blockchains and currencies.

Wallet structure and accessor functions

The wallet function returns a list. This list also has class wallet. The length of the wallet list is equal to the number of wallet addresses you pass to id. The wallet will be a list even if you only pass a single address. This keeps the object structure consistent. It is also convenient to attach the wallet class to the outer list rather than the inner tibbles; rockchain functions operate on the former whereas a user is more likely to alter the latter after extracting from the wallet list.

Several convenient accessors are provided. These are simple getter functions. They are vectorized to return information pertaining to all elements of a wallet list.

id <- c("115p7UMMngoj1pMvkpHijcRdfJNXj6LrLn", "1KennyH9grzif79WbaQDHpqgTnm25j4rRj")
w <- wallet(id)  # a wallet list with two addresses
#> Recent API call. Waiting for turn. 9.98 seconds until next API call...
#> Recent API call. Waiting for turn. 9.94 seconds until next API call...
#> Recent API call. Waiting for turn. 9.98 seconds until next API call...
#> Recent API call. Waiting for turn. 9.86 seconds until next API call...
balance(w)  # check the balance, vectorized
#> [1] 0.2694557 0.0000000

Here are all of the available getter functions.

hash(w)
#> [1] "00e8fd98ca34f195b020af4a8b1c7238663d4212"
#> [2] "cc97e1638381758e58d7e5885bb001d08d35f06d"
address(w)
#> [1] "115p7UMMngoj1pMvkpHijcRdfJNXj6LrLn"
#> [2] "1KennyH9grzif79WbaQDHpqgTnm25j4rRj"
received(w)  # total Bitcoin received
#> [1] 14.68013  0.00001
sent(w)  # total Bitcoin sent
#> [1] 14.41068  0.00001
balance(w)  # final Bitcoin balance
#> [1] 0.2694557 0.0000000
txn(w)  # total number of transactions
#> [1] 118   2
transactions(w)  # transaction details
#> # A tibble: 102 x 16
#>      ver inputs   weight block_height relayed_by  out    lock_time  result
#>    <int> <list>    <int>        <int> <chr>       <list>     <int>   <int>
#>  1     1 <data.f~   1000       509162 0.0.0.0     <data~         0  0     
#>  2     1 <data.f~  32599       498751 0.0.0.0     <data~         0  6.00e6
#>  3     1 <data.f~  49944       498750 0.0.0.0     <data~         0  1.08e7
#>  4     1 <data.f~   1164       479819 85.224.105~ <data~    479808  1.17e6
#>  5     1 <data.f~  42088       478796 193.49.43.~ <data~         0  9.00e6
#>  6     1 <data.f~  24516       478796 176.9.110.4 <data~         0 -7.07e8
#>  7     1 <data.f~    900       471511 73.153.220~ <data~    471510 -7.34e8
#>  8     1 <data.f~   1344       471189 136.243.13~ <data~         0  4.00e6
#>  9     1 <data.f~    904       470322 217.111.66~ <data~         0  5.00e5
#> 10     1 <data.f~   1360       470040 176.126.85~ <data~         0  7.69e6
#> # ... with 92 more rows, and 8 more variables: size <int>, time <int>,
#> #   tx_index <int>, vin_sz <int>, hash <chr>, vout_sz <int>, rbf <lgl>,
#> #   address <chr>

Note the discrepancy between the number of transactions reported by txn and the number of rows in the transaction details tibble returned by transactions for the second wallet address: 101 vs. 115. There are two important things to note going on here.

First, txn always provides the total number of wallet transactions. However, wallet does not automatically retrieve the complete transaction details history from the blockchain.info API. In fact, it only gives you 50 transactions by default. wallet makes repeated calls to the API for you, breaking calls up using a series of transaction offsets, so that you are not only given the first 50 if there are more available. wallet still imposes a safety cap at 100 total transactions in the event you are carelessly requesting all transactions from a wallet that has an extensive transaction history. You can override this by setting a higher cap beyond the default tx_max = 100 or set it to NULL for “unlimited”, though for large transaction records there is not real intent to support to NULL option. You will always be constrained by the limits imposed by the API.

But that brings the total to 100 whereas the total transactions in the table is 101. The final transaction comes from a row bind of the two wallets. These can be filtered using the final column, address, that has been added to the table.

API connection issues

If you have trouble connecting, wallet will retry for you, up to max_attempts times. The default is ten attempts. It is not unusual to be rejected by the API if you make many calls. Notifications are printed to the console if wallet has to try more than once as well as if it fails max_attempts times. By default, wallet will not call the blockchain.info API more than once every ten seconds. You can adjust this with, e.g., options(rockchain_antiddos = 1), but if you make many calls it may make sense to request your own API key from blockchain.info.

Other wallet arguments

By default, the blockchain.info API returns Bitcoin values in Satoshis. One Satoshi is the smallest unit of value, equal to \(`1 / 10^7`\) Bitcoin. But since many APIs and websites report value in Bitcoin, rockchain does the same. This can be switched with satoshi = TRUE. This affects the total received, total sent, final balance, and the value column inside the out data frames that appear in the transaction details table.

id <- "115p7UMMngoj1pMvkpHijcRdfJNXj6LrLn"
w <- wallet(id)
#> Recent API call. Waiting for turn. 9.74 seconds until next API call...
#> Recent API call. Waiting for turn. 9.89 seconds until next API call...
#> Recent API call. Waiting for turn. 9.93 seconds until next API call...
w2 <- wallet(id, satoshi = TRUE)
#> Recent API call. Waiting for turn. 9.86 seconds until next API call...
#> Recent API call. Waiting for turn. 9.95 seconds until next API call...
#> Recent API call. Waiting for turn. 9.96 seconds until next API call...
balance(w2) == balance(w) * 100000000
#> [1] TRUE

An offset can used passed to shift the starting point of the transaction record. The default offset is zero.

w2 <- wallet(id, offset = 10)
#> Recent API call. Waiting for turn. 9.88 seconds until next API call...
#> Recent API call. Waiting for turn. 9.93 seconds until next API call...
#> Recent API call. Waiting for turn. 9.95 seconds until next API call...
transactions(w2)$tx_index[1] == transactions(w)$tx_index[11]
#> [1] TRUE

Simple Bitcoin unit conversions

The package provides one complete and three shorthand convenience functions for converting among different units of measure for Bitcoin. As the value of Bitcoin has grown by orders of magnitude, there is an increasing push for valuation to be expressed in larger, more intuitive numbers using smaller units. Other units include mBTC, bits, and satoshi. Satoshi is the smallest, non-divisible unit of a Bitcoin. There are 100 million satoshi in a Bitcoin. Many people are advocating for the use of bits. One bit is equal to 100 satoshi. Therefore bits can have at most the familiar two decimal places. mBTC are one one-thousandth of a Bitcoin. Bits can also be thought of as one one-millionth of a Bitcoin, or as micro BTC.

convert_btc(1, from = "BTC", to = "mBTC")
#> [1] 1000
convert_btc(1, "BTC", "bits")
#> [1] 1000000
convert_btc(1, "BTC", "satoshi")
#> [1] 100000000
convert_btc(0.001, "mBTC", "bits")
#> [1] 1
convert_btc(1, "mBTC", "bitcoin")
#> [1] 0.001
convert_btc(100, "satoshi", "bits")
#> [1] 1

# Shorthand functions assume value is in Bitcoin
satoshi(0.00000001)
#> [1] 1
bits(0.000001)
#> [1] 1
mbtc(0.001)
#> [1] 1

Plotting data

While packages like ggplot2 can be leveraged to plot the data directly however you see fit, there are some stock plot functions available in rockchain.

More content to be added…