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 requestsimport mysql.connectorfrom datetime import datetimefrom solana.rpc.api import Clientfrom solders.keypair import Keypairfrom solana.transaction import Transaction, AccountMeta, Instruction, Pubkeyfrom solana.constants import SYSTEM_PROGRAM_IDfrom config import API_URL, PRIVATE_KEY, DB_HOST, DB_USER, DB_PASSWORD, DB_NAMEimport loggingimport base58import timefrom logging.handlers import RotatingFileHandler# Set up rotating log handler with timestamphandler = RotatingFileHandler("solbot.log", maxBytes=2000000, backupCount=5)formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')handler.setFormatter(formatter)# Configure root loggerroot_logger = logging.getLogger()root_logger.setLevel(logging.INFO)root_logger.addHandler(handler)# Configure httpx logger to ensure it uses the same handler and formathttpx_logger = logging.getLogger("httpx")httpx_logger.setLevel(logging.INFO)httpx_logger.addHandler(handler)client = Client(API_URL)# Decode the base58 private keytry: 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}") raisedef 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 Nonedef 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 0def 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 0def 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.