Using the Ethereum Web3 client in Python
Ethereum - Web3¶
Similar to the RPC client, I will use the web3 API to make a transaction on my private blockchain.
In [1]:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
I willl use the Python 2.7 environment since Python 3.6 is not yet supported.
In [2]:
import sys
sys.version
Out[2]:
(python2) jitsejan@jjvps:~$ pip install web3
Collecting web3
Requirement already satisfied: requests>=2.12.4 in /home/jitsejan/anaconda3/envs/python2/lib/python2.7/site-packages (from web3)
Collecting ethereum-utils>=0.2.0 (from web3)
Requirement already satisfied: pysha3>=0.3 in /home/jitsejan/anaconda3/envs/python2/lib/python2.7/site-packages (from web3)
Collecting ethereum-abi-utils>=0.4.0 (from web3)
Requirement already satisfied: rlp>=0.4.7 in /home/jitsejan/anaconda3/envs/python2/lib/python2.7/site-packages (from web3)
Collecting pylru>=1.0.9 (from web3)
Installing collected packages: ethereum-utils, ethereum-abi-utils, pylru, web3
Successfully installed ethereum-abi-utils-0.4.0 ethereum-utils-0.2.0 pylru-1.0.9 web3-3.8.1
Note: make sure geth
is started with arguments --rpc and --rpcapi="db,eth,net,web3,personal,web3"
jitsejan@jjvps:~$ geth --networkid 23 --nodiscover --maxpeers 0 --port 30333 --rpc --rpcapi="db,eth,net,web3,personal,miner"
In [3]:
import web3
from web3 import Web3, KeepAliveRPCProvider, IPCProvider
web3.__version__
Out[3]:
Setup RPC connection¶
In [4]:
web3 = Web3(KeepAliveRPCProvider(host='localhost', port='8545'))
Retrieve the accounts¶
In [5]:
web3.eth.accounts
Out[5]:
In [6]:
address = web3.eth.accounts[0]
Set the two other machines¶
In [7]:
address_vps_one = "0xc257beaea430afb3a09640ce7f020c906331f805"
address_vps_two = "0xe86ee31b7d32b743907fa7438c422a1803717deb"
Show their balances¶
In [8]:
print "Host has %d Ether"% web3.fromWei(web3.eth.getBalance(address), 'ether')
print "VPS 1 has %d Ether" % web3.fromWei(web3.eth.getBalance(address_vps_one), 'ether')
print "VPS 2 has %d Ether" % web3.fromWei(web3.eth.getBalance(address_vps_two), 'ether')
prev_host_amount = float(web3.fromWei(web3.eth.getBalance(address), 'ether'))
Transaction¶
Lets send 12 Ether from the main machine to VPS one.
In [9]:
amount = 12 # Ether
sending_address = address
receiving_address = address_vps_one
Get the password to unlock the sending account¶
In [10]:
from getpass import getpass
pw = getpass(prompt='Enter the password for the sender: ')
Unlock the account¶
In [11]:
web3.personal.unlockAccount(address, pw)
Out[11]:
Create the transaction¶
In [12]:
params = {}
params['to'] = receiving_address
params['from'] = sending_address
params['value'] = web3.toWei(amount, "ether")
tx_hash = web3.eth.sendTransaction(params)
Check the transaction¶
In [13]:
web3.eth.getTransaction(tx_hash)
Out[13]:
Check the receipt¶
The miner is not running, so the receipt returns nothing
In [14]:
web3.eth.getTransactionReceipt(tx_hash)
Start and stop the miner¶
Note: web3.admin.sleepBlocks seems not te be available so I use a simple sleep. Within this sleep it could be that there are more than 1 mining cycles.
In [15]:
import time
miner = web3.miner
miner.start(1)
time.sleep(5)
miner.stop()
Out[15]:
Check the receipt again¶
Now the transaction has taken place
In [16]:
web3.eth.getTransactionReceipt(tx_hash)
Out[16]:
Check the balances again¶
The host should have 12 Ether less, but received 5 Ether for each mining cycle. The first VPS should have received 12 Ether.
In [17]:
print "Host has %d Ether"% web3.fromWei(web3.eth.getBalance(address), 'ether')
print "VPS 1 has %d Ether" % web3.fromWei(web3.eth.getBalance(address_vps_one), 'ether')
print "VPS 2 has %d Ether" % web3.fromWei(web3.eth.getBalance(address_vps_two), 'ether')
In [18]:
mine_bonus = 5 # Ether
num_cycles = (float(web3.fromWei(web3.eth.getBalance(address), 'ether')) - prev_host_amount + amount)/mine_bonus
print "%d mining cycle(s) are elapsed" % num_cycles