How To Build A Bitcoin Custodial Wallet with Python

How To Build A Bitcoin Custodial Wallet with Python

A custodial wallet is a type of cryptocurrency wallet where the user's private keys are held by a third-party custodian. This can be a convenient option for users new to cryptocurrencies who may not feel comfortable managing their private keys. In this article, we'll walk through the process of building a custodial wallet with Python.

However, we will use an API in this implementation. So, before we get started, let's look at what an API is.

What is an API

API stands for application programming interface; it is the medium by which digital information is sent and received between software systems.

Prerequisites

Step 1:

BlockIO provides accessible services that can be leveraged to create a custodial Bitcoin wallet. Sign up on block.io and set up your account; upon completion, you will be given your API-KEY and SECRET-KEY.

Note: We will be using bitcoin test net during this development

Step 2:

To get started, we'll need to install a few Python libraries. Open your command prompt or terminal window and create your project directory using the below code

mkdir bitcoin_custodial_wallet

"bitcoin_custodial_wallet" is the name of the folder; you can change the above project name to your desired project name.

Change to the directory with the below code

cd bitcoin_custodial_wallet

Now, use the code below to install the necessary libraries.

pip install jmespath
pip install block-io

Now, let's jump into coding our wallet

As mentioned above, a custodial wallet does not require users to manage their private keys. What we are concerned with is the following:

  • The user's name should be associated with their Bitcoin wallet address

  • Users should be able to send Bitcoin from their wallet

  • Users should be able to receive Bitcoin in their wallet

  • Users should see their available Bitcoin balance

Coding The Wallet

First, create a Python file. We will import the necessary libraries using the below code.

Note: All the codes should be in a single Python file.

from block_io import BlockIo
import jmespath
import json

Now, to use the BlockIO API, we need to initialize it. To do so, use the below code

version = 2 #API version
block_io = BlockIo('Api-Key', "Secret-Key", version)

Now we dive into writing the code.

Create Bitcoin Wallet Address Associated With a Name

def username(name):
    return name

Name = username(input("Enter Username: "))

#greet user using created name
greet = ("HELLO" " " + username(name=Name))
print(greet)
# Generate a new wallet address with name
def gen_wallet(_name):
    generate_wa = block_io.get_new_address(label=_name)
    return generate_wa

gen_Wa = gen_wallet(Name)
print("++++++++++++++++Welcome!" + username(name=Name) + " " + "Your Account Details are below+++++++++")
print(gen_Wa)

In the above code, we defined two functions: one for the username and another for generating a wallet that will be mapped to the username. The first function (username) takes the user's desired username and uses that name in the second function (gen_wallet). The function gen_wallet computes a Bitcoin wallet that is mapped to the name argument given by the user using this call (block_io.get_new_address(label=_name)).

Receive Bitcoin

#get wallet address by username
def get_wallet_by_name(fill):
    lol = json.dumps(block_io.get_address_by_label(label=(fill)))
    lol_ = json.loads(lol)
    wallet_addy = jmespath.search("data.address", lol_)
    return wallet_addy + " 

g_w_name = (get_wallet_by_name(input("Please Enter your Username: ")))
print(g_w_name + " This is your wallet address")

The above code gets the wallet address associated with the user's name using block_io.get_address_by_label(label=(fill)). To fetch the precise address, the response to the call is searched using jmespath.search the jmespath.search function takes two arguments: what and where to search, and in this case, "data.address and lol_".

To test if the wallet can receive bitcoin, copy the wallet displayed as your wallet address and navigate to any bitcoin test net faucet of your choice. In my case, I used the testnet-faucet, which takes roughly 45 minutes to dispense to your wallet.

Display Available Bitcoin Balance

def get_wallet_balance_by_addy(wallet_add):
    gadd = block_io.get_address_balance(address=(wallet_add))
    gadd_ = jmespath.search("data.available_balance", gadd)
    return gadd_

g_wallet = (get_wallet_balance_by_addy(input("Please Enter Your Address: ")))
print(g_wallet)

Here, we call block_io.get_address_balance(address=(wallet_add)) . Using this call, we can get the available bitcoin balance in a user's wallet by passing the user's wallet address as the argument and searching the response with the jmespath.search() command.

Send Bitcoin

Before we proceed to define the code for this aspect, we will need to accept two inputs from the users:

  • The amount of bitcoin to be sent out of the wallet

  • The address to receive the bitcoin

#amount to be sent
Amount_to = (input("Enter amount to send: "))

#address to send bitcoin to
addy_to = (input("Address to send to: "))

These two inputs are passed to the function we are going to define to compute the transaction.

def send_transfer(amount, recipient_address):
    _amount = amount
    to_address = recipient_address
    preparetx = block_io.prepare_transaction(amounts=_amount, to_addresses=to_address)
    signtx = block_io.create_and_sign_transaction(preparetx)

    response = block_io.submit_transaction(transaction_data=signtx)
    return response


send_t = send_transfer(Amount_to, addy_to)
status = jmespath.search("status", send_t)
if status == "success":
    print("Transaction sent ✅🚀")
else:
    print("not successful❌")

To be able to send bitcoin out of the wallet, we need to pass the following steps:

  • Prepare the transaction

  • Sign the transaction

  • Submit the transaction

To prepare the transaction, we call block_io.prepare_transaction(amounts=_amount, to_addresses=to_address) which takes the amount to be sent and the address to receive the bitcoin.

Next is to sign the transaction; signing the transaction means you approve the bitcoin leaving your wallet. This is done using your wallet's private key, but here we will use this callblock_io.create_and_sign_transaction(preparetx). The call takes the prepared transaction as an argument and signs the transaction using your wallet's private key.

Finally, we submit the transaction for mining with this call block_io.submit_transaction(transaction_data=signtx).

Additionally, we added a condition to check if the transfer is successful, if it is not, it prompts the sender with a not successful message.

Source Code

The source code can be found here on GitHub; kindly give it a star🌟.

Summary

Congratulations! We have successfully built a custodial bitcoin wallet. In this article, we have created a custodial bitcoin wallet that can receive, send, and store bitcoin.

I hope you enjoyed this article. Additionally, I would like to mention that this article is part of my project task at Forward School

To enjoy more articles from me, kindly follow and subscribe to my newsletter to join the list of developers that gets notified whenever I upload new articles.