use solana_client::rpc_client::RpcClient; use solana_sdk::pubkey::Pubkey; use bs58; use solana_sdk::instruction::Instruction; use solana_sdk::message::Message; use solana_client::rpc_response::RpcConfirmedTransactionStatusWithSignature; use solana_sdk::transaction::Transaction; use solana_transaction_status::UiTransactionEncoding; use solana_sdk::signature::Signature; use std::str::FromStr; use spl_token::state::Mint; use solana_transaction_status::EncodedTransaction::{Json, Binary}; use solana_transaction_status::UiMessage::{Parsed, Raw}; use base64::prelude::*; use solana_sdk::message::VersionedMessage; use solana_sdk::transaction::VersionedTransaction; use hex; use solana_transaction_status_client_types::option_serializer; fn main() { let rpc_url = "https://api.mainnet-beta.solana.com"; let client = RpcClient::new(rpc_url.to_string()); // Adresse du programme Token (SPL Token Program) let token_program_address = "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM"; let buy_router_address = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"; match base58_to_pubkey(token_program_address) { Ok(token_program) => { println!("Récupération des transactions pour le programme Token..."); // Récupérer les transactions associées au programme Token let transactions = client.get_signatures_for_address(&token_program); match transactions { Ok(sigs) => { println!("Nombre total de transactions trouvées : {}", sigs.len()); for sig in sigs.iter().take(1000) { // Limiter à 10 transactions pour commencer // Convertir la signature en Signature let signature = Signature::from_str(&sig.signature).unwrap(); let config = solana_client::rpc_config::RpcTransactionConfig { encoding: Some(UiTransactionEncoding::Base64), commitment: Some(solana_sdk::commitment_config::CommitmentConfig::confirmed()), max_supported_transaction_version: Some(0), }; // Récupérer les détails de la transaction match client.get_transaction_with_config(&signature, config) { Ok(tx) => { if let Some(meta) = tx.transaction.meta { if let solana_transaction_status::option_serializer::OptionSerializer::Some(inner_instructions) = meta.inner_instructions { //Vérifier si c'est une création de token let is_token_creation = inner_instructions.iter().any(|inner| { inner.instructions.iter().any(|ix| { //println!("ix: {:?}", ix); match ix { solana_transaction_status::UiInstruction::Compiled(instruction) => { is_token_creation(instruction) }, _ => false } }) }); // if is_token_creation { // println!("Création de token trouvée :"); // println!(" Signature: {}", sig.signature); // println!(" Slot: {}", sig.slot); // println!(" Block time: {:?}", sig.block_time); // println!(" Status: {:?}", meta.err); // println!("---"); // } //println!("tx.transaction.transaction: {:?}", tx.transaction.transaction); match tx.transaction.transaction { Binary(data, encoding) => { let decoded = BASE64_STANDARD.decode(data).unwrap(); // Try to deserialize as a VersionedTransaction if let Ok(versioned_tx) = bincode::deserialize::(&decoded) { // dbg!(&versioned_tx); // Try to deserialize the message if let Ok(message) = bincode::deserialize::(&versioned_tx.message.serialize()) { let account_keys = versioned_tx.message.static_account_keys(); println!("\nAccount Keys in Transaction:"); println!(" Payer (account_keys[0]): {}", account_keys[0]); println!(" Mint Account (account_keys[1]): {}", account_keys[1]); println!(" Rent Account (account_keys[2]): {}", account_keys[2]); println!(" Mint Authority (account_keys[3]): {}", account_keys[3]); println!(" Token Program (account_keys[4]): {}", account_keys[4]); // println!("Instructions: {:?}", message.compiled_instructions); match get_token_info(&client, account_keys[1].to_string().as_str()) { Ok(token_info) => { display_token_info(&token_info); } Err(e) => { println!("Erreur lors de la récupération des informations du token : {:?}", e); } } } } // If not a versioned transaction, try as a legacy transaction if let Ok(legacy_tx) = bincode::deserialize::(&decoded) { // dbg!(&legacy_tx); } println!("--------------------------------"); // match json_transaction.message { // Parsed(msg) => { // println!("binary msg: {:?}", msg); // // println!("Token trouvé : {}", &msg); // // println!("Supply total : {}", &msg.supply); // // println!("Decimals : {}", &msg.decimals); // }, // Raw(msg) => { // println!("Raw msg: {:?}", msg); // // println!("Token trouvé : {}", &msg); // // println!("Supply total : {}", &msg.supply); // // println!("Decimals : {}", &msg.decimals); // } // } }, _ => {} } } } } Err(err) => eprintln!("Erreur lors de la récupération de la transaction : {:?}", err), } } } Err(err) => eprintln!("Erreur lors de la récupération des transactions : {:?}", err), } } Err(err) => eprintln!("Erreur lors de la conversion de l'adresse : {:?}", err), } } fn base58_to_pubkey(address: &str) -> Result> { let decoded = bs58::decode(address).into_vec()?; if decoded.len() != 32 { return Err("Address must be 32 bytes long".into()); } let mut bytes = [0u8; 32]; bytes.copy_from_slice(&decoded); Ok(Pubkey::new_from_array(bytes)) } fn is_token_creation(instruction: &solana_transaction_status::UiCompiledInstruction) -> bool { // L'instruction de création de token a un discriminant de 0 if instruction.data.len() < 1 { return false; } // instruction.data == "0".to_string() println!("instruction: {:?}", instruction); true //instruction.data[0] == 0 } #[derive(Debug)] struct TokenInfo { mint_address: String, transaction_signature: String, slot: u64, block_time: Option, decimals: u8, mint_authority: Option, freeze_authority: Option, supply: u64, } fn get_token_info(client: &RpcClient, mint_address: &str) -> Result> { let mint_pubkey = Pubkey::from_str(mint_address)?; // Get the account data let account = client.get_account(&mint_pubkey)?; // Afficher les données brutes en hexadécimal pour le débogage println!("Données brutes en hex: {}", hex::encode(&account.data)); // Décoder les données en utilisant Mint::unpack let mint = Mint::unpack(&account.data)?; // Afficher les informations décodées println!("\nInformations du token décodées:"); println!("Decimals: {}", mint.decimals); println!("Supply: {}", mint.supply); println!("Mint Authority: {:?}", mint.mint_authority); println!("Freeze Authority: {:?}", mint.freeze_authority); Ok(TokenInfo { mint_address: mint_address.to_string(), transaction_signature: "".to_string(), slot: 0, block_time: None, decimals: mint.decimals, mint_authority: mint.mint_authority.map(|pk| pk.to_string()), freeze_authority: mint.freeze_authority.map(|pk| pk.to_string()), supply: mint.supply, }) } fn display_token_info(token: &TokenInfo) { println!("\nToken Information:"); println!(" Mint Address: {}", token.mint_address); println!(" Decimals: {}", token.decimals); println!(" Supply: {}", token.supply); match &token.mint_authority { Some(auth) => println!(" Mint Authority: {}", auth), None => println!(" Mint Authority: None (immutable)"), } match &token.freeze_authority { Some(auth) => println!(" Freeze Authority: {}", auth), None => println!(" Freeze Authority: None (unfrozen)"), } println!(" Transaction: {}", token.transaction_signature); println!(" Slot: {}", token.slot); if let Some(time) = token.block_time { println!(" Block Time: {}", time); } println!("---"); }