2

Here is my entire main.rs,,

mod utils;

use actix_cors::Cors;
use actix_web::{web, App, HttpServer, Responder, HttpResponse, HttpRequest};
use serde::{Deserialize, Serialize};
use reqwest::Client;
use std::sync::Arc;
use tokio::sync::Mutex;
use solana_client::rpc_client::RpcClient;
use solana_program::{
    pubkey::Pubkey,
    system_instruction,
    account_info::{next_account_info, AccountInfo},
    entrypoint,
    entrypoint::ProgramResult,
    program::{invoke},
    program_error::ProgramError,
    msg,
};
use solana_sdk::signature::Keypair;
use solana_sdk::message::Message;
use solana_sdk::transaction::Transaction;
use utils::{get_launch_date, get_sol_price};
use std::str::FromStr;
use spl_token::instruction as token_instruction;

#[derive(Serialize, Deserialize, Debug)]
struct TransactionRequest {
    public_key: String,
    amount: f64,
    currency: String,
}

#[derive(Serialize)]
struct TransactionResponse {
    status: String,
    message: String,
    amount_in_lamports: u64,
    destination: String,
}

async fn process_transaction(
    _req: HttpRequest, // Prefixed with underscore to silence warning
    body: web::Json<TransactionRequest>,
    client: web::Data<Arc<Mutex<Client>>>,
) -> impl Responder {
    let transaction = body.into_inner();
    println!("Processing transaction: {:?}", transaction);

    let client_guard = client.lock().await;
    let sol_price = get_sol_price(&client_guard).await.unwrap();
    let amount_in_sol = transaction.amount / sol_price;
    let amount_in_lamports = (amount_in_sol * 1_000_000_000.0) as u64;

    let destination_pubkey = Pubkey::from_str("14fbryUnN5Px4GGg1MMgTKawpyvBXUzk4p8JGbtMfNud").unwrap();
    let sender_pubkey = Pubkey::from_str(&transaction.public_key).unwrap();

    let sender_keypair = Keypair::new();

    let rpc_client = RpcClient::new("https://api.mainnet-beta.solana.com");
    let recent_blockhash = rpc_client.get_latest_blockhash().unwrap();
    let transaction_instruction = system_instruction::transfer(
        &sender_pubkey,
        &destination_pubkey,
        amount_in_lamports,
    );

    let message = Message::new(&[transaction_instruction], Some(&sender_pubkey));
    let mut transaction = Transaction::new_unsigned(message);
    transaction.try_sign(&[&sender_keypair], recent_blockhash).unwrap();

    let signature = rpc_client.send_and_confirm_transaction(&transaction).unwrap();

    let response = TransactionResponse {
        status: "success".to_string(),
        message: format!("Transaction processed successfully: {}", signature),
        amount_in_lamports,
        destination: "14fbryUnN5Px4GGg1MMgTKawpyvBXUzk4p8JGbtMfNud".to_string(),
    };
    HttpResponse::Ok().json(response)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let client = Arc::new(Mutex::new(Client::new()));
    
    HttpServer::new(move || {
        App::new()
            .wrap(
                Cors::default().allow_any_origin().allow_any_method().allow_any_header()
            )
            .app_data(web::Data::new(client.clone()))
            .route("/launch-date", web::get().to(get_launch_date))
            .route("/process-transaction", web::post().to(process_transaction))
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

// Combined KRPL_Contract functions

entrypoint!(process_instruction);

pub fn process_instruction(
    _program_id: &Pubkey, // Prefixed with underscore to silence warning
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> ProgramResult {
    let account_iter = &mut accounts.iter();

    let sender = next_account_info(account_iter)?;
    let recipient = next_account_info(account_iter)?;
    let system_program = next_account_info(account_iter)?;
    let token_program = next_account_info(account_iter)?;
    let token_account = next_account_info(account_iter)?;

    let (transfer_type, amount) = parse_instruction_data(instruction_data)?;

    match transfer_type {
        TransferType::Sol => {
            let transfer_instruction = system_instruction::transfer(
                sender.key,
                recipient.key,
                amount,
            );

            msg!("Invoking transfer instruction...");
            invoke(
                &transfer_instruction,
                &[
                    sender.clone(),
                    recipient.clone(),
                    system_program.clone(),
                ],
            )?;
        },
        TransferType::Usdc => {
            let transfer_instruction = token_instruction::transfer(
                token_program.key,
                token_account.key,
                recipient.key,
                sender.key,
                &[&sender.key],
                amount,
            )?;

            msg!("Invoking token transfer instruction...");
            invoke(
                &transfer_instruction,
                &[
                    token_program.clone(),
                    token_account.clone(),
                    recipient.clone(),
                    sender.clone(),
                ],
            )?;
        },
    }

    Ok(())
}

enum TransferType {
    Sol,
    Usdc,
}

fn parse_instruction_data(data: &[u8]) -> Result<(TransferType, u64), ProgramError> {
    if data.len() != 9 {
        return Err(ProgramError::InvalidInstructionData);
    }

    let transfer_type = match data[0] {
        0 => TransferType::Sol,
        1 => TransferType::Usdc,
        _ => return Err(ProgramError::InvalidInstructionData),
    };

    let amount = u64::from_le_bytes(data[1..].try_into().unwrap());

    Ok((transfer_type, amount))
}

pub fn create_transfer_instruction(
    sender_pubkey: &Pubkey,
    recipient_pubkey: &Pubkey,
    amount: u64,
) -> solana_program::instruction::Instruction {
    solana_program::system_instruction::transfer(sender_pubkey, recipient_pubkey, amount)
}

the full error below:

error: linking with `link.exe` failed: exit code: 1169
  |
  = note: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX64\\x64\\link.exe" "/NOLOGO" "C:\\Users\\Keola\\AppData\\Local\\Temp\\rustcsit7vP\\symbols.o" "C:\\Users\\Keola\\Desktop\\MyToken-ICOWidget\\Main\\ProjectV2\\BackendV2\\target\\debug\\deps\\BackendV2.02w35narb1wcyx3f48a9qcf74.rcgu.o" "C:\\... [etc]

  = note: libspl_token-9c38dd82029194be.rlib(spl_token-9c38dd82029194be.spl_token.26961209c36bf507-cgu.0.rcgu.o) : error LNK2005: entrypoint already defined in BackendV2.91eirpl2uxknzk9n40oimifb8.rcgu.o
          C:\Users\Keola\Desktop\MyToken-ICOWidget\Main\ProjectV2\BackendV2\target\debug\deps\BackendV2.exe : fatal error LNK1169: one or more multiply defined symbols found


warning: `BackendV2` (bin "BackendV2") generated 2 warnings
error: could not compile `BackendV2` (bin "BackendV2") due to 1 previous error; 2 warnings emitted
PS C:\Users\Keola\Desktop\MyToken-ICOWidget\Main\ProjectV2\BackendV2>

my cargo.toml:

cargo-features = ["profile-rustflags"]

[package]
name = "BackendV2"
version = "0.1.0"
edition = "2021"

[dependencies]
actix-web = "4.6.0"
actix-cors = "0.7.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1", features = ["full"] }

# Use compatible versions of Solana dependencies
solana-program = "1.18.14"
spl-token = "3.5.0"
solana-client = "1.18.14"
solana-sdk = "1.18.14"

[profile.dev]
rustflags = ["-C", "link-args=/STACK:16777216"]

[profile.release]
rustflags = ["-C", "link-args=/STACK:16777216", "-C", "target-cpu=native"]

[unstable]
profile-rustflags = true

[target.x86_64-pc-windows-msvc]
linker = "rust-lld"

I think I've narrowed down the problem being somewhere in,

entrypoint!(process_instruction);

pub fn process_instruction(
    _program_id: &Pubkey, // Prefixed with underscore to silence warning
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> ProgramResult {
    let account_iter = &mut accounts.iter();

    let sender = next_account_info(account_iter)?;
    let recipient = next_account_info(account_iter)?;
    let system_program = next_account_info(account_iter)?;
    let token_program = next_account_info(account_iter)?;
    let token_account = next_account_info(account_iter)?;

    let (transfer_type, amount) = parse_instruction_data(instruction_data)?;

    match transfer_type {
        TransferType::Sol => {
            let transfer_instruction = system_instruction::transfer(
                sender.key,
                recipient.key,
                amount,
            );

            msg!("Invoking transfer instruction...");
            invoke(
                &transfer_instruction,
                &[
                    sender.clone(),
                    recipient.clone(),
                    system_program.clone(),
                ],
            )?;
        },
        TransferType::Usdc => {
            let transfer_instruction = token_instruction::transfer(
                token_program.key,
                token_account.key,
                recipient.key,
                sender.key,
                &[&sender.key],
                amount,
            )?;

            msg!("Invoking token transfer instruction...");
            invoke(
                &transfer_instruction,
                &[
                    token_program.clone(),
                    token_account.clone(),
                    recipient.clone(),
                    sender.clone(),
                ],
            )?;
        },
    }

    Ok(())
}

enum TransferType {
    Sol,
    Usdc,
}

fn parse_instruction_data(data: &[u8]) -> Result<(TransferType, u64), ProgramError> {
    if data.len() != 9 {
        return Err(ProgramError::InvalidInstructionData);
    }

    let transfer_type = match data[0] {
        0 => TransferType::Sol,
        1 => TransferType::Usdc,
        _ => return Err(ProgramError::InvalidInstructionData),
    };

    let amount = u64::from_le_bytes(data[1..].try_into().unwrap());

    Ok((transfer_type, amount))
}

pub fn create_transfer_instruction(
    sender_pubkey: &Pubkey,
    recipient_pubkey: &Pubkey,
    amount: u64,
) -> solana_program::instruction::Instruction {
    solana_program::system_instruction::transfer(sender_pubkey, recipient_pubkey, amount)
}

I've been dealing with this error for two days. I have no idea what I'm doing, I'm following guides and chat-gpt.4o

I did the front end, then started having errors when trying to initiate a transaction so, I said "hey lets do rust then a circumvent this bug all together." like holy hell I'm so close to making this damn thing yet I'm having the most stupid unreversible bugs last minute and it's driving me crazy so PLEASE help.

please and thank you.

3
  • Maybe try update spl token to v4.0.1. Maybe 1.18 is not compatible with 3.x anymore.
    – Jonas H.
    Commented May 27 at 10:41
  • if you has disc0rd, my name is keolamation. Send me a FQ. yeah, to fix it. I seperated krpl_contract to its own project, but now I'm not able to deploy it. it's issue after issue. I could really use a coding partner for this.
    – Keola
    Commented May 27 at 23:58
  • For deploying, if you have problems try: solana version: 1.18.13 command: solana program deploy target/deploy/your_program.so --with-compute-unit-price 10000 --max-sign-attempts 1000 --use-rpc
    – Jonas H.
    Commented May 28 at 9:41

1 Answer 1

1

The error says that a symbol is defined multiple times between two different libraries:

  = note: libspl_token-9c38dd82029194be.rlib(spl_token-9c38dd82029194be.spl_token.26961209c36bf507-cgu.0.rcgu.o) : error LNK2005: entrypoint already defined in BackendV2.91eirpl2uxknzk9n40oimifb8.rcgu.o

Specifically, entrypoint is defined multiple times. Typically, when you build a solana program, you need to define a function called entrypoint, but if it is multiply defined, the build will fail.

Typically, program crates come with a no-entrypoint feature which will remove the entrypoint function, allowing the program to link successfully. I'm not sure about the other dependencies in your build, but you might be able to fix this by specifying the spl-token dependency as:

spl-token = { version = "3.5.0", features = ["no-entrypoint"] }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.