Issue: Cannot Figure Out SDK Instruction #7070
Description
Hello all,
I am new to coding with Python and Solana and I am making a very simple bot to trade Solana based on moving averages. I coded my whole bot and its close to finished, but I've spent all day trying to figure out these errors with the invalid instructions. I am not sure if this is the right place to ask but id be incredibly grateful to anyone who could help me out!
The error I am getting is: Error sending SOL: SendTransactionPreflightFailureMessage { message: "Transaction simulation failed: Error processing Instruction 0: invalid instruction data", data: RpcSimulateTransactionResult(RpcSimulateTransactionResult { err: Some(InstructionError(0, InvalidInstructionData)), logs: Some(["Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 failed: invalid instruction data"]), accounts: None, units_consumed: Some(150), return_data: None, inner_instructions: None }) }
The code I am using in my utils.py file is below:
import requests
import mysql.connector
from datetime import datetime
from solana.rpc.api import Client
from solders.keypair import Keypair
from solana.transaction import Transaction, AccountMeta, Instruction, Pubkey
from solana.constants import SYSTEM_PROGRAM_ID
from config import API_URL, PRIVATE_KEY, DB_HOST, DB_USER, DB_PASSWORD, DB_NAME
import logging
import base58
import time
from logging.handlers import RotatingFileHandler
# Set up rotating log handler with timestamp
handler = RotatingFileHandler("solbot.log", maxBytes=2000000, backupCount=5)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# Configure root logger
root_logger = logging.getLogger()
root_logger.setLevel(logging.INFO)
root_logger.addHandler(handler)
# Configure httpx logger to ensure it uses the same handler and format
httpx_logger = logging.getLogger("httpx")
httpx_logger.setLevel(logging.INFO)
httpx_logger.addHandler(handler)
client = Client(API_URL)
# Decode the base58 private key
try:
private_key_bytes = base58.b58decode(PRIVATE_KEY)
account = Keypair.from_bytes(private_key_bytes)
root_logger.info("Private key decoded successfully")
except ValueError as e:
root_logger.error(f"Error decoding PRIVATE_KEY from base58: {e}")
raise
def get_db_connection():
return mysql.connector.connect(
host=DB_HOST,
user=DB_USER,
password=DB_PASSWORD,
database=DB_NAME
)
def log_trade(action, sol_amount, usd_value):
try:
connection = get_db_connection()
cursor = connection.cursor()
timestamp = datetime.now()
sql = "INSERT INTO trade_logs (timestamp, action, sol_amount, usd_value) VALUES (%s, %s, %s, %s)"
values = (timestamp, action, sol_amount, usd_value)
cursor.execute(sql, values)
connection.commit()
cursor.close()
connection.close()
root_logger.info(f"Logged trade: {action} {sol_amount} SOL at {usd_value} USD")
except Exception as e:
root_logger.error(f"Error logging trade: {e}")
def get_market_data():
url = "https://api.coingecko.com/api/v3/coins/solana/market_chart?vs_currency=usd&days=90"
for attempt in range(5): # Retry 5 times
try:
response = requests.get(url)
response.raise_for_status() # Raise an exception for HTTP errors
data = response.json()
root_logger.info("Market data fetched successfully")
return data
except requests.RequestException as e:
root_logger.error(f"Error fetching market data (attempt {attempt + 1}): {e}")
time.sleep(5) # Wait for 5 seconds before retrying
root_logger.error(f"Failed to fetch market data after 5 attempts")
return None
def send_sol(destination, amount, action, target_currency):
try:
transaction = Transaction()
destination_pubkey = Pubkey(base58.b58decode(destination)) # Ensure correct decoding
if action == "buy" and target_currency == "SOL":
# Add instruction to swap USDC to SOL
transfer_instruction = Instruction(
program_id=SYSTEM_PROGRAM_ID, # Ensure correct decoding
accounts=[
AccountMeta(pubkey=account.pubkey(), is_signer=True, is_writable=True),
AccountMeta(pubkey=destination_pubkey, is_signer=False, is_writable=True)
],
data=int(amount * 1e9).to_bytes(8, byteorder='little') # lamports
)
elif action == "sell" and target_currency == "USDC":
# Add instruction to swap SOL to USDC
transfer_instruction = Instruction(
program_id=SYSTEM_PROGRAM_ID, # Ensure correct decoding
accounts=[
AccountMeta(pubkey=account.pubkey(), is_signer=True, is_writable=True),
AccountMeta(pubkey=destination_pubkey, is_signer=False, is_writable=True)
],
data=int(amount * 1e9).to_bytes(8, byteorder='little') # lamports
)
else:
root_logger.error("Invalid action or target currency specified")
return
transaction.add(transfer_instruction)
response = client.send_transaction(transaction, account)
root_logger.info(f"Transaction response: {response}")
usd_value = get_usd_value(amount)
log_trade(action, amount, usd_value)
except Exception as e:
root_logger.error(f"Error sending SOL: {e}")
def get_usd_value(sol_amount):
try:
market_data = get_market_data()
if market_data:
current_price = market_data['prices'][-1][1] # Last price in USD
root_logger.info(f"Current price of SOL: {current_price} USD")
return sol_amount * current_price
else:
return 0
except Exception as e:
root_logger.error(f"Error getting USD value: {e}")
return 0
def get_balance():
try:
balance = client.get_balance(account.pubkey())
root_logger.info(f"Account balance: {balance['result']['value'] / 1e9} SOL")
return balance['result']['value'] / 1e9 # Convert lamports to SOL
except Exception as e:
root_logger.error(f"Error getting balance: {e}")
return 0
def get_sol_balance():
try:
balance = client.get_balance(account.pubkey())
root_logger.info(f"SOL balance: {balance['result']['value'] / 1e9} SOL")
return balance['result']['value'] / 1e9 # Convert lamports to SOL
except Exception as e:
root_logger.error(f"Error getting SOL balance: {e}")
return 0
What am I doing wrong? I would be incredibly grateful if someone could correct my code or even point me in the right direction of how I would fix it!
Thank you all.