This script demonstrates essential Solana operations, including interacting with token accounts, managing virtual reserves, and performing token swaps using the SPL Token program. The script highlights functions like fetching token data, buying and selling tokens, and calculating portfolio performance.
Ensure you have the following Python libraries installed:
solders
for Solana data structuressolana
for Solana RPC APIrequests
for API callsconstruct
for data parsing
You can install them using:
pip install solders solana requests construct
- Environment Variables: Store sensitive data like private keys and RPC URLs in a
.env
file. - Constants: Define key program IDs and addresses for Solana operations in a constants file.
# config.py
from solana.rpc.api import Client
from solders.keypair import Keypair
import os
from dotenv import load_dotenv
load_dotenv()
PRIV_KEY = os.getenv("PrivateKey")
RPC = os.getenv("RPC_HTTPS_URL")
client = Client(RPC)
payer_keypair = Keypair.from_base58_string(PRIV_KEY)
# constants.py
from solders.pubkey import Pubkey
PUMP_FUN_PROGRAM = Pubkey.from_string("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P")
TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
This function reads on-chain data from a bonding curve account.
from solders.pubkey import Pubkey
from construct import Struct, Int64ul, Padding, Flag
from config import client
bonding_curve_struct = Struct(
Padding(8),
"virtualTokenReserves" / Int64ul,
"virtualSolReserves" / Int64ul,
"realTokenReserves" / Int64ul,
"realSolReserves" / Int64ul,
"tokenTotalSupply" / Int64ul,
"complete" / Flag
)
def get_virtual_reserves(bonding_curve: Pubkey):
try:
account_info = client.get_account_info(bonding_curve)
data = account_info.value.data
parsed_data = bonding_curve_struct.parse(data)
return parsed_data
except Exception as e:
print("Error fetching virtual reserves:", e)
return None
Derives accounts related to the bonding curve using Solana program-derived addresses (PDAs).
from spl.token.instructions import get_associated_token_address
def derive_bonding_curve_accounts(mint_str: str):
try:
mint = Pubkey.from_string(mint_str)
bonding_curve, _ = Pubkey.find_program_address(
["bonding-curve".encode(), bytes(mint)], PUMP_FUN_PROGRAM
)
associated_bonding_curve = get_associated_token_address(bonding_curve, mint)
return bonding_curve, associated_bonding_curve
except Exception as e:
print("Error deriving bonding curve accounts:", e)
return None, None
A function to purchase tokens from the bonding curve.
from solana.transaction import Transaction
from solders.instruction import Instruction
from solders.compute_budget import set_compute_unit_limit, set_compute_unit_price
from config import client, payer_keypair, UNIT_BUDGET, UNIT_PRICE
def buy(mint_str: str, sol_in: float = 0.01, slippage: int = 25) -> bool:
try:
coin_data = get_coin_data(mint_str)
if not coin_data:
print("Failed to retrieve coin data.")
return False
owner = payer_keypair.pubkey()
mint = Pubkey.from_string(mint_str)
token_account = get_associated_token_address(owner, mint)
sol_in_lamports = int(sol_in * 10**9)
amount = int(sol_in_lamports * coin_data['virtual_token_reserves'] / coin_data['virtual_sol_reserves'])
max_sol_cost = int(sol_in_lamports * (1 + slippage / 100))
keys = [
AccountMeta(pubkey=GLOBAL, is_signer=False, is_writable=False),
AccountMeta(pubkey=FEE_RECIPIENT, is_signer=False, is_writable=True),
AccountMeta(pubkey=mint, is_signer=False, is_writable=False),
AccountMeta(pubkey=coin_data['bonding_curve'], is_signer=False, is_writable=True),
AccountMeta(pubkey=coin_data['associated_bonding_curve'], is_signer=False, is_writable=True),
AccountMeta(pubkey=token_account, is_signer=False, is_writable=True),
AccountMeta(pubkey=owner, is_signer=True, is_writable=True),
AccountMeta(pubkey=TOKEN_PROGRAM, is_signer=False, is_writable=False),
]
data = struct.pack('<Q', amount) + struct.pack('<Q', max_sol_cost)
swap_instruction = Instruction(PUMP_FUN_PROGRAM, data, keys)
txn = Transaction(fee_payer=owner)
txn.add(set_compute_unit_limit(UNIT_BUDGET))
txn.add(set_compute_unit_price(UNIT_PRICE))
txn.add(swap_instruction)
txn.sign(payer_keypair)
txn_sig = client.send_transaction(txn, payer_keypair).value
print("Transaction confirmed:", txn_sig)
return True
except Exception as e:
print("Error buying tokens:", e)
return False
Implements the selling logic for tokens held in a bonding curve account.
def sell(mint_str: str, percentage: int = 100, slippage: int = 25) -> bool:
try:
coin_data = get_coin_data(mint_str)
if not coin_data:
print("Failed to retrieve coin data.")
return False
owner = payer_keypair.pubkey()
mint = Pubkey.from_string(mint_str)
token_account = get_associated_token_address(owner, mint)
token_balance = get_token_balance(mint_str)
if token_balance == 0:
print("No tokens available to sell.")
return False
amount = int(token_balance * (percentage / 100))
min_sol_output = int((amount / coin_data['virtual_token_reserves']) * coin_data['virtual_sol_reserves'] * (1 - slippage / 100))
keys = [
AccountMeta(pubkey=GLOBAL, is_signer=False, is_writable=False),
AccountMeta(pubkey=FEE_RECIPIENT, is_signer=False, is_writable=True),
AccountMeta(pubkey=mint, is_signer=False, is_writable=False),
AccountMeta(pubkey=coin_data['bonding_curve'], is_signer=False, is_writable=True),
AccountMeta(pubkey=coin_data['associated_bonding_curve'], is_signer=False, is_writable=True),
AccountMeta(pubkey=token_account, is_signer=False, is_writable=True),
AccountMeta(pubkey=owner, is_signer=True, is_writable=True),
AccountMeta(pubkey=TOKEN_PROGRAM, is_signer=False, is_writable=False),
]
data = struct.pack('<Q', amount) + struct.pack('<Q', min_sol_output)
swap_instruction = Instruction(PUMP_FUN_PROGRAM, data, keys)
txn = Transaction(fee_payer=owner)
txn.add(set_compute_unit_limit(UNIT_BUDGET))
txn.add(set_compute_unit_price(UNIT_PRICE))
txn.add(swap_instruction)
txn.sign(payer_keypair)
txn_sig = client.send_transaction(txn, payer_keypair).value
print("Transaction confirmed:", txn_sig)
return True
except Exception as e:
print("Error selling tokens:", e)
return False
- Fetch token balances
def get_token_balance(mint_str: str):
try:
owner = payer_keypair.pubkey()
response = client.get_token_accounts_by_owner(owner, TokenAccountOpts(mint=mint_str))
return response.value[0].account.data.parsed.info.tokenAmount.uiAmount
except Exception as e:
print("Error fetching token balance:", e)
return 0
- Confirm transactions
def confirm_txn(txn_sig: str):
try:
response = client.get_transaction(txn_sig, commitment="confirmed")
return response.value.transaction.meta.err is None
except Exception as e:
print("Error confirming transaction:", e)
return False
This script integrates key Solana blockchain functions, enabling efficient interactions with token accounts and bonding curves. Modify the code as needed for specific use cases like portfolio management, trading bots, or DeFi applications.
To expand this tutorial, you can integrate additional features like:
- Automating trades based on market conditions.
- Tracking and reporting portfolio performance.
- Adding more robust error handling and logging.
Feel free to reach out for further enhancements or explanations!
Can probably run this through ai to create a walk through of interacting with solana using python