Interacting with the Blockchain with the Python Language
My first glimpse into blockchain programming came from Andreas M. Antonopoulous’ Mastering Bitcoin. The code snippets and examples in the book are illustrated in Python, C++, and utilize a simple command line for Unix-like operating systems like Linux or macOS. While certainly illustrative for interacting with the blockchain, there are some other, newer Python packages out there that allow an even more simplistic and digestively easier way of interacting directly with the blockchain.
The simple examples that follow use Python 3.6.x. They work off of readily available Python packages that vastly simplify the way you interact with the blockchain, through publicly available APIs by websites that interact directly with the blockchain such as blockchain.info and coinmarketcap.com You can use pip to install these libraries to Python 3 (either directly to your system or via a virtual environment):
pip3 install pandas
pip3 install matplotlib
pip3 install blockchain
pip3 install bitcoin
Pandas is a powerful data analysis library and one of the main reasons to use Python for analyzing data structures. It works with datasets including json and csv files which makes it ideal for data analytics. Python isn’t the fastest backend language, because after all it is an interpreted language, but for the following simple blockchain-interactive code it is more than sufficient.
Similar to Pandas, matplotlib is another Python library that makes data analysis illustratively simple. It is a 2D plotting library that can generate all manner of graphs, histograms, power spectra bar charts, etc with just a few lines of code.
The blockchain library used is the ‘official’ Python module for interacting with the blockchain.info API, the popular website that allows quick and reliable access to the blockchain. Through this library Python can interact with the public ledger API of the blockchain.info website.
And finally, the bitcoin library is a :
’SImple, common-sense Bitcoin-themed Python ECC library’
written for the language by none other than Vitalik Buterin. Interestingly, at the end of 2017, Buterin decided to wipe the repo off of github with a quick ‘bye bye’, thankfully the package is still available for us to use.
For the examples that follow, I am going to assume the reader has a basic understanding of Python and programming in general and am going to let the code speak for itself. A good portion of the following code came about after attending a class by Override Labs, Inc. a New York City-based blockchain learning organization and is derived under the Apache License, Version 2.0. The organization is paving the way in blockchain learning for the metro area.
Example 1: Interacting with the blockchain
In the first example with just a simple import of the blockchain package we are able to capture a blocks height and hash. As a fun iteration of this, we can capture the height and hash of the famous Laszlo pizza transaction, the first documented purchase of a good with bitcoin. At only 10,000 BTC back in 2010, this was a considerably bold, and successful, investment by the counter-party, as well as all the transactions tied to this wallet address.
from blockchain import blockexplorer as be
def main():
# Get the latest block (height & hash)
latest_block = be.get_latest_block()
print("Latest height: ",str(latest_block.height))
print("Latest hash: ",latest_block.hash)
# Get info on the Laszlo Domino’s Pizza transaction via blockchain.info API
# Capture the hash
pizza_block_hash = "00000000152340ca42227603908689183edc47355204e7aca59383b0aaac1fd8"
# Get the hash of the laszlo tx
pizza_tx_hash = "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d"
# Get the tx of the laszlo tx
pizza_block = be.get_block(pizza_block_hash)
print("The block height for the Laszlo tx ", pizza_block.height)
# get the tx
pizza_tx = be.get_tx(pizza_tx_hash)
print("That pizza cost ", satoshis_to_btc(pizza_tx.outputs.pop().value), " BTCs!")
# get Txs in Laszlo's address
laszlo_addr = "1XPTgDRhN8RFnzniWCddobD9iKZatrvH4"
print("Laszlo transaction list for address ", laszlo_addr)
laszlo_txs = be.get_address(laszlo_addr).transactions
for t in laszlo_txs:
for o in t.outputs:
print(satoshis_to_btc(o.value))
def satoshis_to_btc(satoshi):
return satoshi / 100000000 # one one hundred millionth
if __name__ == "__main__":
main()
Example 2 : Capturing Rates
A simple example of the current BTC/USD rate along with a several other currency rates dictated by the package, followed by how much BTC you can purchase with USD, once again utilizing the blockchain.info API.
from blockchain import exchangerates as er
symbols = er.get_ticker()
for k in symbols:
print(str(k), symbols[k].p15min)
# How much BTC can USD buy?
for d in range(0,100000, 10000):
print("$",d," = ",er.to_btc('USD',d)," BTC”)
Example 3 : Trade Volume
Taking a look at the BTC trade volume over the last 24 hours through the blockchain.info API as well as a peek into the miner revenues.
from blockchain import statistics as statistics
def main():
s = statistics.get()
print("Trade Volume:", s.trade_volume_btc)
print("# of Tx last 24 hours: ", s.number_of_transactions)
print("Total BTC Sent last 24 hours: ", '{:,.2f}'.format(satoshis_to_btc(s.total_btc_sent)))
print("Miners Revenue USD last 24 hours", '${:,.2f}'.format(s.miners_revenue_usd) )
#print(s.total_fees_btc)
def satoshis_to_btc(satoshi):
return satoshi / 100000000 # one one hundred millionth
if __name__ == "__main__":
main()
Example 4 : Private/Public Keys
We can use Vitalik’s bitcoin package to generate private/public keys natively with Python as follows. Note: Don't send money to these addresses!
from bitcoin import *
def main():
private_key = random_key()
public_key = privtopub(private_key)
bitcoin_address = pubtoaddr(public_key)
print("Private key: ",private_key)
print("Public key: ",public_key)
print("Bitcoin address: ", bitcoin_address)
if __name__ == "__main__":
main()
Example 5 : Multi-seg Wallet
Extending from the last snippet, we can generate a multi-seg wallet that allows for multiple keys as an added layer of security for wallets using Vitalik’s package once more. Note: Don't send money to these addresses!
from bitcoin import *
def main():
# 4 PPKs
private_key1 = random_key()
public_key1 = privtopub(private_key1)
private_key2 = random_key()
public_key2 = privtopub(private_key2)
private_key3 = random_key()
public_key3 = privtopub(private_key3)
private_key4 = random_key()
public_key4 = privtopub(private_key4)
# Multisig public key
multisig = mk_multisig_script(public_key1, public_key2, public_key3, public_key4,4)
print("Multisig: ", multisig)
# Bitcoin address
bitcoin_address = scriptaddr(multisig)
print("Bitcoin address: ",bitcoin_address)
if __name__ == "__main__":
main()
Example 6 : Coin Price via CoinMarketCap API
The popular site coinmarketcap.com has a publicly available API that we can use in conjunction with pandas to get some interesting data about specific coins. Using this API we can look at the first few coins in total in terms of their available columns through the pandas library, revealing their supply, market cap and percentage change over the last 24hrs among other data points. We can also drill down into specific coins, in this case Litecoin and begin streaming. Note: The example includes uncluttered header info that is excluded from the screenshot below for the sake of space but when run, shows the full range of data pulled through pandas.
import requests
import pandas as pd
import json
import time
def main():
print("Get list of tickers")
df = pd.read_json("https://api.coinmarketcap.com/v1/ticker/")
print(df.info())
print(df.head()) # Showcase the data columns
df = df.sort_values(by=['symbol'])
for i, r in df.iterrows():
print(r["symbol"]," ",r["price_usd"])
print("Stream litecoin price")
for n in range(0,2):
df = pd.read_json("https://api.coinmarketcap.com/v1/ticker/litecoin")
print(df["price_usd"])
time.sleep(15) # Pause between request for rate limit
if __name__ == "__main__":
main()
Example 7 : Ethereum blockchain
Similar to blockchain.info we can also look at the Ethereum block chain using the exposed endpoint over at etherscan.io. Note the different data pulls, csv versus json in use by etherscan.io and how pandas really comes in handy across multiple domains and datasets.
import requests
import pandas as pd
import json
import io
def main():
url = 'https://etherscan.io/chart/etherprice?output=csv'
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
response = requests.get(url, headers=headers)
# Data from Etherscan.io
df = pd.read_table(io.StringIO(response.content.decode("utf-8")),sep=",")
print(df.columns)
print(df.info())
print(df.head())
print(df.tail())
if __name__ == "__main__":
main()
Example 8 : Plotting our Data
Finally, we can import matplotlib into our code and generate a time-series plot of the price of Ethereum using the module. Depending on your particular system, your 2D graph may look a bit different. Combined with pandas and public endpoints, this snippet illustrates the power of the Python tools at our disposal!
import requests
import matplotlib.pyplot as plt
import pandas as pd
import json
import io
def main():
url = 'https://etherscan.io/chart/etherprice?output=csv'
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
response = requests.get(url, headers=headers)
# Data from Etherscan.io
df = pd.read_table(io.StringIO(response.content.decode("utf-8")),sep=",")
df.dropna()
# Drop UnixTimeStamp
df = df.drop(df.columns[1], axis=1)
# Convert Date from str to datetime
df['Date(UTC)'] = pd.to_datetime(df['Date(UTC)'],format = "%m/%d/%Y")
# Make Date the index
df.index = df['Date(UTC)']
# Remove dupe Date
df = df.drop(df.columns[0], axis=1)
# Plot
plt.plot(df)
plt.show()
if __name__ == "__main__":
main()
Thanks for reading and I hope you enjoyed this post and are able to start querying the blockchain using Python!
Coins mentioned in post: