How To Build A Bitcoin Custodial Wallet with Python
Tags: python, bitcoin, programming, blockchain
Published: 2023-04-23 09:21:29

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 add 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](https://github.com/BalogunMalikO/Bitcoin-custodial-wallet).

**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.