In this tutorial, we will learn how to build a Solana Discord chat bot wallet with Python, discord.py, and the Solana Python SDK. This chat bot will be capable of creating an account, funding an account, checking an account balance, and sending Solana tokens to another account, all through Discord.
Solana is a public blockchain network that allows its users to create NFTs, finance applications, and other smart contract applications. Solana’s native token is called SOL, and according to coinmarketcap.com at the time of writing, has the seventh largest market cap among cryptocurrencies. A Solana wallet is an application that allows you to create Solana accounts, store, send, and receive SOL and other tokens, as well as interact with smart contracts.
Discord is a popular free voice, video, and text chat app with more than 350 million users that runs on Windows, macOS, Android, iOS, iPadOS, Linux, and in web browsers. A Discord chat bot is a bot that is capable of responding to commands and automating certain tasks, such as welcoming new members, moderating content, and banning rule breakers. The bot that we are going to create will help us create and manage a Solana wallet.
At the end of this tutorial you will have a Solana Discord wallet that looks like the following:
In this section, we will create a new Discord bot account, retrieve the bot token, and invite the bot to one of our servers.
Using your preferred browser, navigate to the Discord developer portal and use your Discord account to sign in. Navigate to the Applications page and click on the New Application button.
Give your application a name, such as “Solana wallet,” and then press Create.
Next, navigate to the Bot tab and click on the Add Bot button to create a bot user.
Scroll down to the Build-A-Bot section of the page and click on the Copy button to copy the bot token. We will use this bot token in the next section, so keep it somewhere safe. This token should be kept private because anyone with access to this token will be able to control your bot.
After following the steps above, you have successfully created a bot account! Now in order to be able to interact with this bot account, you need to invite it to your server.
Navigate to the OAuth2 tab, and then to the URL Generator sub tab. In the Scopes section, select bot.
In the Bot Permissions section that appears below, select all the fields in the Text Permissions column. Go to the section where says Generated URL and click the Copy button to copy the bot invite URL.
Paste the copied URL in a new tab, select the server where you would like to add the bot, and click the Continue button.
Review the bot’s permissions, and when you are satisfied, click the Authorize button.
Now your bot will be invited to your server and you will be able interact with it once we code it.
In this section, we will create our project directory. Inside this directory, we will create and activate a virtual environment, then install the Python packages needed to build this chat bot. Lastly, we will create a file named .env
and inside this file, store our Discord bot token.
Open a terminal window and enter the following commands:
mkdir solana-discord-wallet cd solana-discord-wallet
Inside our working directory, create a virtual environment and activate it. If you are using a Unix or MacOS system, run the following commands:
python3 -m venv venv source venv/bin/activate
If you are following the tutorial on Windows, run the following commands instead:
python -m venv venv venvScriptsactivate
Now that we have created and activated our virtual environment, we can install the libraries that we need to create our application:
pip install discord.py solana python-dotenv
In the command above we used pip
, the Python package installer, to install the following packages that we are going to use in this project:
.env
file and adds them as environment variables. We will use this module to retrieve our bot token that will be stored in the .env
fileNow let’s start building our application. Create a file called .env
, and paste in the Discord bot token that you saved in the previous section as BOT_TOKEN
.
main.py
fileIn this section, we will create the Python script that will allow our Discord chat bot to send and receive messages.
In the root directory of your project, create a file called main.py
. Open it using your favorite text editor and add the following code:
import os import discord from discord.ext import commands from dotenv import load_dotenv
Here, we imported all the packages that we are going to need to allow our chat bot application to send and receive messages:
os
will be used alongside python-dotenv
to retrieve our Discord bot token from the .env
filediscord
package will be used to interact with Discord’s API and create command handlers, thus allowing us to send and receive Discord messagesAdd the following code to the bottom of the main.py
file:
load_dotenv() description = ''' A bot that allows you to create and manage a Solana wallet ''' intents = discord.Intents.default() bot = commands.Bot(command_prefix='/', description=description, intents=intents) @bot.event async def on_ready(): print('Bot is online') print(bot.user.name) print(bot.user.id) print('------ n')
In the code above, we imported the environment variables stored in the .env
file with a call to load_dotenv()
.
After loading the variables, we created a basic description for our bot, and set the bot’s intents to default
. An intent is what allows a bot to subscribe to specific buckets of events, such as direct messages, reactions, or typing.
Then, we created a new bot instance and passed as arguments to the constructor a command prefix (/
), the description, and the intents. We stored the bot instance in a variable named bot
.
Lastly, we create an event listener for when the bot is running. When this event listener is triggered, we print a couple lines to the console saying that the bot is online, and showing the bot’s username and user ID.
Now, Add the following code below the on_ready()
function :
@bot.command(description='Create a new solana account') async def create(ctx): await ctx.send('Create account') @bot.command(description='Fund your account') async def fund(ctx): await ctx.send('Fund your account') @bot.command(description='Check account balance') async def balance(ctx): await ctx.send('Check account balance') @bot.command(description='Send SOL to another account') async def send(ctx): await ctx.send('Send SOL to another account') bot.run(os.environ['BOT_TOKEN'])
In the block of code above we created all the command handlers for our chat bot . The code above determines which command the user is trying to call and takes the appropriate action.
Please notice how we don’t need to specify the command prefix in each command handler because we already did that when we created the bot instance.
Our chat bot wallet will be able to handle the following commands:
/create
creates a new Solana account/fund amount
funds an existing Solana account with a certain amount of SOL/balance
checks the balance of an existing Solana account/send amount receiver
is responsible for sending a certain amount of SOL to another Solana accountFor now, each command handler will only send back a text describing the action that the user wants to perform. In order to send a message to the user, we used the send()
method provided by the context (ctx
) object available in each command handler.
Lastly, we called the run()
method provided by the bot
object and passed the bot token as an argument to start our chat bot.
Your main.py
file should look like the following:
import os import discord from discord.ext import commands from dotenv import load_dotenv load_dotenv() description = ''' A bot that allows you to create and manage a Solana wallet ''' intents = discord.Intents.default() bot = commands.Bot(command_prefix='/', description=description, intents=intents) @bot.event async def on_ready(): print('Bot is online') print(bot.user.name) print(bot.user.id) print('------ n') @bot.command(description='Create a new solana account') async def create(ctx): await ctx.send('Create account') @bot.command(description='Fund your account') async def fund(ctx): await ctx.send('Fund your account') @bot.command(description='Check account balance') async def balance(ctx): await ctx.send('Check account balance') @bot.command(description='Send SOL to another account') async def send(ctx): await ctx.send('Send SOL to another account') bot.run(os.environ['BOT_TOKEN'])
Go to your terminal, and run the following command in order to start the application:
python main.py
Using your preferred Discord client, send the /create
command to the bot, and you should get a response similar to the following :
wallet.py
fileIn this section, we will create the file that will allow us to create a Solana account, fund the account, check the balance of the account, and send funds from this account to another.
When you create a Solana account, a KeyPair object is generated. This object contains a public key and a corresponding private key for accessing the account.
A public key is analogous to an account number that can be publicly shared with anyone in order to receive funds, and a private key is what grants a Solana user ownership of the funds on a given account. As the name suggests, this private key should not be shared publicly.
A Solana account may hold funds called “lamports”. Lamports are fractional native tokens valued at 0.000000001 SOL.
In the root directory of your project, create a file named wallet.py
. Open it using your favorite text editor and then add the following code:
from solana.keypair import Keypair from solana.publickey import PublicKey from solana.rpc.api import Client from solana.transaction import Transaction from solana.system_program import TransferParams, transfer import json solana_client = Client("https://api.devnet.solana.com")
Here, we imported the following objects from the Solana
package :
Keypair
, which will be used to create a new Solana accountPublicKey
, which will convert a public key in a string format to a PublicKey
object in order to send Solana tokens to another accountClient
, to create a Solana client instance that will allow this application to interact with the Solana blockchainTransaction
, to create a Solana transaction. A transaction is instructions signed by a client using single or multiple KeyPairs and executed atomically with only two possible outcomes: success or failureTransferParams
, to create an object containing the parameters of a transfer funds transactiontransfer
, to create an object that allows an account to send funds to anotherAfter that, we imported json
, which is used to store the created Solana account public key and private key in a file.
Lastly, we created a Solana client instance in a variable named solana_client
and set the RPC endpoint to the devnet
. An RPC (remote procedure call) endpoint is a URL to which requests for blockchain data can be sent.
Add the following code to the bottom of the wallet.py
:
def create_account(sender_username): try: kp = Keypair.generate() public_key = str(kp.public_key) secret_key = kp.secret_key data = { 'public_key': public_key, 'secret_key': secret_key.decode("latin-1"), } file_name = '{}.txt'.format(sender_username) with open(file_name, 'w') as outfile: json.dump(data, outfile) return public_key except Exception as e: print('error:', e) return None
The create_account()
function created above receives as an argument the username of the user that sent the /create
command and it is responsible for creating a new Solana account and storing the account details in a local .txt
file.
We start the code by first generating a new Solana account KeyPair object and storing it in a variable called kp
.
We then store it in an object called data
, which is the stringified value of the generated account’s public_key
and secret_key
.
Lastly, we use the value stored in the variable called sender_username
to create a .txt
file, dump the data
in it, and return the account’s public_key
if there isn’t an exception. If something goes wrong, we return None
.
Add the following code below the create_account()
function:
def load_wallet(sender_username): try: file_name = '{}.txt'.format(sender_username) with open(file_name) as json_file: account = json.load(json_file) account['secret_key'] = account['secret_key'].encode("latin-1") return account except Exception as e: print(e) return None
Here, we created a function named load_wallet()
. This function receives as an argument the user’s username and uses it to retrieve his Solana account public and private key from a local .txt
file, which is created when the create_account()
function is called.
Add the following code below the load_wallet()
function:
def fund_account(sender_username, amount): try: amount = int(1000000000 * amount) account = load_wallet(sender_username) resp = solana_client.request_airdrop( account['public_key'], amount) print(resp) transaction_id = resp['result'] if transaction_id != None: return transaction_id else: return None except Exception as e: print('error:', e) return None
In the code above, we created a function named fund_account()
. This function is responsible for requesting SOL for a specific account, and receives as an argument the username of the user who sent the /fund
command, and the amount of SOL that the user is requesting.
First, we use some basic math to prevent Solana from converting the amount of SOL we wish to request to a fraction of what it should be. Say, for example, that we wish to request that one SOL is added to our account. If we just input “1” as the amount, Solana will convert this amount to 0.000000001. So in order to prevent this behavior, we multiply our desired amount by one billion (1,000,000,000).
Then, use the load_wallet()
function to get the user’s Solana account data and store it in a variable named account
.
Lastly, we use the request_airdrop()
method provided by the solana_client
object to request some SOL tokens for the account for which we provided the public key. If the request is successful, we return the transaction ID, but if something goes wrong we return None
.
For us to consider the request successful, the request_airdrop()
method should return a response similar to the following:
{ "jsonrpc": "2.0", "result":"uK6gbLbhnTEgjgmwn36D5BRTRkG4AT8r7Q162TLnJzQnHUZVL9r6BYZVfRttrhmkmno6Fp4VQELzL4AiriCo61U", "id": 1 }
The jsonrpc
that you see above is the protocol that was used, the id
is the request ID, the result
is the response results, and in this particular case, is a transaction ID.
You can check the details of a Solana transaction by first navigating to the Solana blockchain explorer, selecting the Devnet
network, and entering the transaction ID that you see in the result
property.
Add the following code below the fund_account()
method:
def get_balance(sender_username): try: account = load_wallet(sender_username) resp = solana_client.get_balance(account['public_key']) print(resp) balance = resp['result']['value'] / 1000000000 data = { "publicKey": account['public_key'], "balance": str(balance), } return data except Exception as e: print('error:', e) return None
Here we created a function named get_balance()
. This function receives as an argument the username of the user who sent the /balance
command, and it is responsible for retrieving the user’s Solana account balance.
First, we use the load_wallet()
method to get the user’s Solana account, and then we call the get_balance()
method provided by the Solana client to get an account balance, pass the account public key as an argument, and assign the response to a variable named resp
.
After retrieving the account balance, we divide the balance by one billion to make it more readable.
Lastly, we store the public key and account balance in an object named data
, and then we return this object.
If the request sent by the get_balance()
method was successful you should see a response similar to the following:
{ "jsonrpc": "2.0", "result": { "context": { "slot": 228 }, "value": 0 }, "id": 1 }
The context
that you see above is a RpcResponseContext
JSON structure including a slot
field at which the operation was evaluated. The value
is the value returned by the operation itself, and in this case, is the account balance.
Add the following code below the get_balance()
function:
def send_sol(sender_username, amount, receiver): try: account = load_wallet(sender_username) sender = Keypair.from_secret_key(account['secret_key']) amount = int(1000000000 * amount) txn = Transaction().add(transfer(TransferParams( from_pubkey=sender.public_key, to_pubkey=PublicKey(receiver), lamports=amount))) resp = solana_client.send_transaction(txn, sender) print(resp) transaction_id = resp['result'] if transaction_id != None: return transaction_id else: return None except Exception as e: print('error:', e) return None
The send_sol()
function created above receives as arguments the username of the user who sent the /send
command, the amount
of SOL that this user wishes to send, and the Solana account address where she wishes to send it. As the name suggests, this function is responsible for sending a certain amount of SOL to a Solana account address that the user provided.
First, we use the load_wallet()
function to get the user’s Solana account, and then we store the user’s Solana account KeyPair in a variable named sender
. The amount that she wishes to send is stored in a variable named amount
.
We then create a transaction object, add to it the sender’s and the receiver’s public key, add the amount of SOL that she wishes to send, and assign this object to a variable named txn
.
In order to send and sign the transaction, we call the send_transaction()
method provided by the Solana client, pass as arguments the transaction object and the sender’s KeyPair, and then store the response in a variable named resp
. The response of the request sent by the send_transaction()
method is similar to the request_airdrop()
method response that we saw earlier.
Lastly, we grab the transaction ID stored in the result
property of the resp
object, store it in a variable named transaction_id
, and return it.
The wallet.py
file should look similar to the following:
from solana.keypair import Keypair from solana.publickey import PublicKey from solana.rpc.api import Client from solana.transaction import Transaction from solana.system_program import TransferParams, transfer import json solana_client = Client("https://api.devnet.solana.com") def create_account(sender_username): try: kp = Keypair.generate() public_key = str(kp.public_key) secret_key = kp.secret_key data = { 'public_key': public_key, 'secret_key': secret_key.decode("latin-1"), } file_name = '{}.txt'.format(sender_username) with open(file_name, 'w') as outfile: json.dump(data, outfile) return public_key except Exception as e: print('error:', e) return None def load_wallet(sender_username): try: file_name = '{}.txt'.format(sender_username) with open(file_name) as json_file: account = json.load(json_file) account['secret_key'] = account['secret_key'].encode("latin-1") return account except Exception as e: print(e) return None def fund_account(sender_username, amount): try: amount = int(1000000000 * amount) account = load_wallet(sender_username) resp = solana_client.request_airdrop( account['public_key'], amount) print(resp) transaction_id = resp['result'] if transaction_id != None: return transaction_id else: return None except Exception as e: print('error:', e) return None def get_balance(sender_username): try: account = load_wallet(sender_username) resp = solana_client.get_balance(account['public_key']) print(resp) balance = resp['result']['value'] / 1000000000 data = { "publicKey": account['public_key'], "balance": str(balance), } return data except Exception as e: print('error:', e) return None def send_sol(sender_username, amount, receiver): try: account = load_wallet(sender_username) sender = Keypair.from_secret_key(account['secret_key']) amount = int(1000000000 * amount) txn = Transaction().add(transfer(TransferParams( from_pubkey=sender.public_key, to_pubkey=PublicKey(receiver), lamports=amount))) resp = solana_client.send_transaction(txn, sender) print(resp) transaction_id = resp['result'] if transaction_id != None: return transaction_id else: return None except Exception as e: print('error:', e) return None
In the previous section, we created the file that contains the functions that will allow our chat bot to perform transactions in the Solana blockchain. In this section, we will integrate these functions with our chat bot’s command handlers.
Go to your main.py
and add the following code to the import statements:
from wallet import create_account, fund_account, get_balance, send_sol
In the line of code above, we imported all the functions that we created in the previous sections in the wallet.py
file. Let’s go through each command to integrate them into our chat bot’s command handlers.
/create
commandIn the main.py
file, replace the code in the /create
command handler with the following:
async def create(ctx): sender_username = ctx.message.author try: public_key = create_account(sender_username) if public_key is not None: message = "Solana Account created successfully.n" message += "Your account public key is {}".format(public_key) await ctx.send(message) else: message = "Failed to create account.n" await ctx.send(message) except Exception as e: print('error:',e) await ctx.send('Failed to create account') return
Here, we get the username of the user who sent the /create
command and store it in a variable named sender_username
.
After that, we call the create_account()
function in the wallet.py
file, pass as an argument the user’s username, and store it in a variable named public_key
. The the newly created Solana account’s public key is returned by the create_account()
function.
We then use conditional logic to check if the value of public_key
is not equal to None
, and if this is the case, we store a message in a variable named message
, saying that the Solana account was created successfully and showing public key. After that, we use the send()
method to send the message to the user.
However, if the public_key
is equal to None
we send a message saying that the bot failed to create an account.
/fund
commandNow, replace the code in the /fund
command handler with the following:
async def fund(ctx): sender_username = ctx.message.author incoming_msg = ctx.message.content try: amount = float(incoming_msg.split(" ")[1]) if amount <= 2 : message = "Requesting {} SOL to your Solana account, please wait !!!".format(amount) await ctx.send(message) transaction_id = fund_account(sender_username, amount) if transaction_id is not None: message = "You have successfully requested {} SOL for your Solana account n".format( amount) message += "The transaction id is {}".format(transaction_id) await ctx.send(message) else: message = "Failed to fund your Solana account" await ctx.send(message) else: message = "The maximum amount allowed is 2 SOL" await ctx.send(message) except Exception as e: print('error:',e) await ctx.send('Failed to fund account') return
In the code above, we get the username of the user who sent the /fund
command and the message received, and then we store these values in variables named sender_username
and incoming_msg
, respectively.
We then retrieve the amount of SOL that the user would like to request from the message received and store it in a variable named amount
.
After retrieving the amount we check if the amount
isn’t greater than two, because at the time of writing this tutorial, two is the maximum amount of SOL that you can request. If the amount isn’t greater than two, we store a message in a variable named message
saying that the amount that the user requested is being added to his account, and asking him to wait. We then use the send()
method to send this message to the user.
After notifying the user, we call the fund_account()
function in the wallet.py
file. We pass as arguments the user’s username and the amount of SOL that he wishes to add to his account. After calling the fund_account()
function, we store the transaction ID returned in a variable named transaction_id
.
Lastly, we use conditional logic to check if the transaction ID isn’t equal to None
, and if that is the case, we store a message in a variable named message
, saying that the funds he requested were added to his account. We add to this message the transaction ID and then we send this message to the user.
However, if the transaction ID
is equal to None
we send a message saying that the bot failed to fund the account.
/balance
commandNow let’s do the /balance
command. Replace the code in the /balance
command handler with the following:
async def balance(ctx): sender_username = ctx.message.author try: data = get_balance(sender_username) if data is not None: public_key = data['publicKey'] balance = data['balance'] message = "Your Solana account {} balance is {} SOL".format( public_key, balance) await ctx.send(message) else: message = "Failed to retrieve balance" await ctx.send(message) except Exception as e: print('error:',e) await ctx.send('Failed to check account balance') return
Here, first, we get the username of the user who sent the /balance
command and store it in a variable named sender_username
.
We then call the get_balance()
function in the wallet.py
file. We pass as an argument the user’s username and store it in a variable named data
as the object returned by this function. This object should contain the user’s Solana account public key and balance.
Lastly, we use conditional logic to check if the value returned is not equal to None
. If that is the case we store a message in a variable named message
, containing the user’s Solana account public key and balance, and then we send the message to the user.
However, if the value returned by the get_balance()
is equal to None
we send a message saying that the bot failed to retrieve the account balance.
/send
commandMoving on, replace the code in the /send
command handler with the following:
async def send(ctx): sender_username = ctx.message.author incoming_msg = ctx.message.content try: split_msg = incoming_msg.split(" ") amount = float(split_msg[1]) receiver = split_msg[2] message = "Sending {} SOL to {}, please wait !!!".format( amount, receiver) await ctx.send(message) transaction_id = send_sol(sender_username, amount, receiver) if transaction_id is not None: message = "You have successfully sent {} SOL to {} n".format( amount, receiver) message += "The transaction id is {}".format(transaction_id) await ctx.send(message) else: message = "Failed to send SOL" await ctx.send(message) except Exception as e: print('error:',e) await ctx.send('Failed to send SOL') return
In the code above, we get the username of the user who sent the /send
command, the message received, and then we store these values in a variables named sender_username
and incoming_msg
respectively.
We then parse the incoming message, retrieve from it the amount of SOL that the user wishes to send and the receiver account’s address, and store these values in variables named amount
and receiver
, respectively.
After storing the amount
and receiver
, a message is sent to the user to notify that the amount of SOL she wishes to send is being sent to the receiver, and to ask the user to wait.
After notifying the user, we call the send_sol()
function in the wallet.py
file. We pass as arguments the user’s username, the amount of SOL she wishes to transfer, and the receiver’s address. We then store the transaction ID returned by this function in a variable named transaction_id
.
Lastly, we use conditional logic to check if the transaction ID isn’t equal to None
. If that is the case we store a message in a variable named message
saying that the user successfully sent SOL to the desired account. We attach the transaction ID to the message and we send the message to the user.
However, if the value returned by the send_sol()
function is equal to None
we send a message saying that the bot failed to send SOL.
After replacing the code in each command handler, the main.py
file should look like the following:
import os import discord from discord.ext import commands from dotenv import load_dotenv from wallet import create_account, fund_account, get_balance, send_sol load_dotenv() description = ''' A bot that allows you to create and manage a Solana wallet ''' intents = discord.Intents.default() bot = commands.Bot(command_prefix='/', description=description, intents=intents) @bot.event async def on_ready(): print('Bot is online') print(bot.user.name) print(bot.user.id) print('------ n') @bot.command(description='Create a new solana account') async def create(ctx): sender_username = ctx.message.author try: public_key = create_account(sender_username) if public_key is not None: message = "Solana Account created successfully.n" message += "Your account public key is {}".format(public_key) await ctx.send(message) else: message = "Failed to create account.n" await ctx.send(message) except Exception as e: print('error:',e) await ctx.send('Failed to create account') return @bot.command(description='Fund your account') async def fund(ctx): sender_username = ctx.message.author incoming_msg = ctx.message.content try: amount = float(incoming_msg.split(" ")[1]) if amount <= 2 : message = "Requesting {} SOL to your Solana account, please wait !!!".format(amount) await ctx.send(message) transaction_id = fund_account(sender_username, amount) if transaction_id is not None: message = "You have successfully requested {} SOL for your Solana account n".format( amount) message += "The transaction id is {}".format(transaction_id) await ctx.send(message) else: message = "Failed to fund your Solana account" await ctx.send(message) else: message = "The maximum amount allowed is 2 SOL" await ctx.send(message) except Exception as e: print('error:',e) await ctx.send('Failed to fund account') return @bot.command(description='Check your account balance') async def balance(ctx): sender_username = ctx.message.author try: data = get_balance(sender_username) if data is not None: public_key = data['publicKey'] balance = data['balance'] message = "Your Solana account {} balance is {} SOL".format( public_key, balance) await ctx.send(message) else: message = "Failed to retrieve balance" await ctx.send(message) except Exception as e: print('error:',e) await ctx.send('Failed to check account balance') return @bot.command(description='Send SOL to another account') async def send(ctx): sender_username = ctx.message.author incoming_msg = ctx.message.content try: split_msg = incoming_msg.split(" ") amount = float(split_msg[1]) receiver = split_msg[2] message = "Sending {} SOL to {}, please wait !!!".format( amount, receiver) await ctx.send(message) transaction_id = send_sol(sender_username, amount, receiver) if transaction_id is not None: message = "You have successfully sent {} SOL to {} n".format( amount, receiver) message += "The transaction id is {}".format(transaction_id) await ctx.send(message) else: message = "Failed to send SOL" await ctx.send(message) except Exception as e: print('error:',e) await ctx.send('Failed to send SOL') return bot.run(os.environ['BOT_TOKEN'])
Go back to the terminal window running the main.py
file, stop the process, and then run it again with the following command:
python main.py
Go to your preferred Discord client and send the /create
command to your bot to create a new Solana account. You should see something similar to the following:
Copy the public key and store it somewhere for later use. Send the /create
command again to generate a new Solana account.
Now, send the /fund 2
command to fund your Solana account with two SOL tokens. Feel free to change the amount to any value lower than two. You should see something similar to the following:
Make sure to test the other commands to make sure they each work as intended.
In this tutorial, you learned how to create a Solana Discord chat bot wallet capable of creating a Solana account, funding the account, retrieving the account’s balance, and sending SOL to another Solana account.
The Solana Discord wallet that we built in this tutorial isn’t ready for production yet, and I advise adding more features such as authentication and account balance checking before sending SOL to another account. The complete application code is available in this repository.
For more information about Solana and the discord.py package, please visit the Solana documentation and the discord.py documentation.
LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.
Modernize how you debug web and mobile apps — Start monitoring for free.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowBuild scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.
In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.
Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]
9 Replies to "How to build a Solana Discord wallet with Python"
Hey Carlos, thanks for the informative blog post. Would like you to clarify, did you mean 1 trillion or 1 billion, because the number and the words are contradicing themselves. I mean in the fund_account function. You put 1,000,000,000 but then say it as 1 trillion
Hey Dave, I think you misread, I didn’t write trillion anywhere.
“secret_key”: “\u00d1R>\u00fe5\u0088\u009bm\u0014\u0095$u\u00aa\u00e3^\u00e8\u00a0\u0097\b\u00c…
how to convert it to utf-8
‘charmap’ codec can’t encode character ‘\x9f’ in position 45: character maps to having this problem while decoding secret_key in create_account
This is super informative and would love to give it a try! I only have one question – is it possible to use a custom token built on the Solana chain, such as by using the custom token address/ID?
Hey, I have a question. Whenever I try to execute a command I get in my IDE, the error: ‘str’ object has no attribute ‘to_solders’. In discord I get the message “Failed to fund account”. Only the create command works for me. How can I solve this problem?
Yo,
After debbuging this a little bit, I found that the problem is when he is trying to use the public key,
you should use PublicKey(account[“public_key”])
instead of account[‘public_key’]
hope that it helps to you or anyone that try to follow this tutorial 🙂
The solana.py library was updated and because of that the code that used to work now doesn’t. In the future please refer to the documentation https://michaelhly.github.io/solana-py/rpc/api/ .
Wow, nice tutorial thanks for sharing it. Does this still work? I was trying another youtube tutorial on creating wallets and transactions using solana.py and it doesn’t work anymore.
Thanks!