Guide to Creating a Wallet and Performing Transactions on Bitcoind with python-bitcoinrpc
Introduction
Have you ever wondered how to directly interact with a Bitcoin node using Python? This article serves as a simple guide, offering functionalities to get you started. It provides hands-on experience covering the creation of wallets, secure address generation, in-depth exploration of blocks, and the process of conducting transactions.
Ready to delve into the exciting world of Python-powered Bitcoin interactions? Let's get started!" :)
Prerequisites
Before proceeding, ensure that Bitcoin Core is set up and bitcoind is running. Follow this guide to achieve the setup.
To confirm whether bitcoind is running, execute the following command in your terminal:
$ps -aux | grep bitcoind
If Bitcoind is running, the output will display the Process ID of the active instance:
user 87889 0.6 0.4 1270160 50976 ? Ssl 23:38 0:00 bitcoind
The next step is to set up Python3. Follow this guide or use the [alternative method]. Once that's done, you can confirm that Python3 is installed by checking the version:
python3 --version
Now that Bitcoin Core and Python3 are both set up, the next step is to install python-bitcoinrpc.
But first, create a test file. Then navigate to the directory containing the test file and install python-bitcoinrpc :
touch testwallet.py pip install python-bitcoinrpc
All the prerequisites are in place, let's start working on the script! :)
Import the AuthServiceProxy
class into the testwallet.py
file.
Create an RPC connection to the running Bitcoind node. To achieve this, utilize the RPC credentials defined in the bitcoin.conf
file. Create a .env
file, store those variables in that file, and source them inside the testwallet file.
from bitcoinrpc.authproxy import AuthServiceProxy
wallet_connection = AuthServiceProxy(f"http://{rpc_user}:{rpc_password}@127.0.0.1:18332", timeout=290)
Create a wallet
Unlike in the past, Bitcoin Core no longer has a default wallet. So, let's start by creating our test wallet. The only required argument for the createwallet
method is the wallet name, which should be a string.
wallet_name = "testwallet80"
new_wallet = wallet_connection.createwallet(wallet_name)
Run the script again to create the test wallet. To view the details of the created wallet, execute the following command in a separate terminal window. Now, we can see that the wallet above has been successfully created.
$ bitcoin-cli getwalletinfo
The output of the command will display wallet details.
{
"walletname": "testwallet80",
"walletversion": 169900,
"format": "sqlite",
"balance": 0.00000000,
"unconfirmed_balance": 0.00000000,
}
Generate a new Address
Generate a new address by prompting the user to select the desired address type. Create a separate function, user_address
, to facilitate this selection.
def user_address():
"""
Get user address type.
"""
while True:
address_type = input("Select address type (legacy, p2sh-segwit, bech32): ").lower()
if address_type in ["legacy", "p2sh-segwit", "bech32"]:
return address_type
else:
print("Invalid address type. Please choose from legacy, p2sh-segwit, or bech32.")
Use the function above to generate the address:
wallet_address = wallet_connection.getnewaddress("GenerateAddress",user_address())
print("-")
print("Wallet Address: ", wallet_address)
Run the script again, and the user will be prompted to select an address. Once selected, print that address. Sample output:
Select address type (legacy, p2sh-segwit, bech32): bech32
-
Wallet Address: tb1qe0d6jh0x0v2qjhy8h7wylxjsv006sqdr4du47h
-
If Bitcoind is running on testnet, you can obtain some test coins from a testnet faucet using the previously generated address.
Generate blocks to the address
First, let's retrieve our wallet's spendable balance by adding the following to the script:
#Retrive wallet spendable balance
wallet_balance = wallet_connection.getbalance()
print("-------------------------------------------------------------------------------")
print("Wallet Balance:",wallet_balance)
print("-\n")
Run the script again to get the balance:
-------------------------------------------------------------------------------
Wallet Balance: 0E-8
-
Since our balance is insufficient generate blocks to the address using the generatetoaddress
method. Pass the number of blocks you'd like to generate and the address:
#generate blocks
# import pdb; pdb.set_trace()
blocks = wallet_connection.generatetoaddress(101, wallet_address)
print("-------------------------------------------------------------------------------")
print("Generating Blocks")
print("-\n")
Once that's done, check the wallet balance again:
#new balance
new_balance = wallet_connection.getbalance()
print("-")
print("New wallet Balance:",new_balance)
print("-")
The new output:
-------------------------------------------------------------------------------
Generating Blocks
-
New wallet Balance: 50.00000000
-
Note: Generating blocks takes time, and this might cause a socket timeout error. Before running the script again, consider increasing the timeout. If this error persists, you can create a separate RPC connection to Bitcoind for block generation using the same credentials.
Create a send to Address transaction
Now that the wallet balance is sufficient, the first transaction involves using the sendtoaddress
method. This method will send a certain amount to an address and the output will be a transaction ID.
set a transaction fee of 0.00001
to send 0.1
Note: This is not mandatory; however, it is useful to mitigate the fallback fee error."
wallet_connection.settxfee(0.00001)
Send to an address requires an address, as well as the amount and an optional comment
send_transaction = wallet_connection.sendtoaddress(wallet_address, 0.01, "test send")
print("-")
print("Transaction Id:",send_transaction)
print("-\n")
The output.
-
Transaction Id: 61a7f6fec3c18cdfd66f8e7efc1b9b4f8d01b34839ba2efdb22bf8153e9a203b
-
Congratulations!๐ You've successfully created a wallet and sent some test funds to an address. Next we'll dive deeper into transactions.