SolanaPortal
  • ✨Welcome to SolanaPortal
  • Getting Started
    • ⭐Why SolanaPortal?
    • 📖Guide
    • 🗺️Best Practices
    • ❓FAQ
  • API Documentation
    • Swapping
      • Swapping with Node.js
      • Swapping with Python
      • Swapping with Rust
    • Token Creation
      • Pump.fun Token
      • Standard Token
  • Market Creation
  • ‼️Troubleshooting
  • Support
Powered by GitBook
On this page
  • Overview
  • Installing Prerequisites
  • Setting Up the Environment
  • Performing a Standard Token Swap
  • Performing a Jito Bundle Swap
  • Running the Code
  • Key Notes
  1. API Documentation
  2. Swapping

Swapping with Rust

PreviousSwapping with PythonNextToken Creation

Last updated 16 days ago

Overview

This guide provides a step-by-step explanation for using the SolanaPortal API to execute token swaps with Rust. Whether you're performing a standard token swap or a more complex Jito bundle transaction, this tutorial walks you through the process on how to swap using Node.js. We'll break down everything from setting up your environment to sending transactions.

Installing Prerequisites

Before you begin, ensure the following:

  1. Rust installed:

Download and install Rust using . Check your version with:

rustc --version                                                  

Ensure it is Rust 1.60 or later.

  1. Private Key:

Obtain the private key for your Solana wallet (Phantom Wallet). Keep this key secure as it is required to sign transactions.

Setting Up the Environment

  1. Create a new Rust project.

cargo new solana_swap
cd solana_swap
  1. Add the required dependencies to your Cargo.toml:

[dependencies]
reqwest = { version = "0.11", features = ["json"] }
base58 = "0.9.0"
solana-sdk = "1.14.11"
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
  1. Open main.rs in your editor and import the necessary modules:

use reqwest::Client;
use base58::FromBase58;
use solana_sdk::{
    signature::{Keypair, Signer},
    transaction::Transaction,
    pubkey::Pubkey,
    message::Message,
    system_instruction,
 };
 use std::error::Error;
 use serde_json::json;
 use tokio;

Performing a Standard Token Swap

A standard token swap involves using a single wallet to trade one token on a supported decentralized exchange (DEX).

Full code example
use reqwest::Client;
use base58::FromBase58;
use solana_sdk::{
    signature::{Keypair, Signer},
    transaction::Transaction,
    pubkey::Pubkey,
    message::Message,
    system_instruction,
};
use std::error::Error;
use serde_json::json;
use tokio;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // Replace with your private key
    let private_key = "your-private-key-here";
    let decoded_key = private_key.from_base58()?;
    let keypair = Keypair::from_bytes(&decoded_key)?;

    let mint = "3jzdrXXKxwkBk82u2eCWASZLCKoZs1LQTg87HBEAmBJw"; // Replace with token mint address
    println!("Wallet Address: {}", keypair.pubkey());

    // Parameters for the swap
    let param = json!({
        "wallet_address": keypair.pubkey().to_string(),
        "action": "buy",  // "buy" or "sell"
        "mint": mint,     // Mint address of the token to trade
        "dex": "raydium", // Supported values: "raydium", "jupiter", "pumpfun", "moonshot"
        "amount": 0.0001, // Amount of tokens to trade
        "slippage": 100,  // Maximum slippage allowed (in percentage)
        "tip": 0.0001,    // Priority fee
        "type": "jito",   // Use "jito" for prioritized execution
    });

    let client = Client::new();
    let url = "https://api.solanaportal.io/api/trading";

    // Send the POST request to the API
    let response = client.post(url)
        .json(&param)
        .send()
        .await?;

    if response.status().is_success() {
        let data: String = response.json().await?;
        println!("Transaction generated successfully: {}", data);

        // Decode and sign the transaction
        let txn_bytes = base64::decode(data)?;
        let mut txn = Transaction::deserialize(&txn_bytes)?;
        txn.sign(&[&keypair]);

        // Broadcast the signed transaction
        let jito_response = client.post("https://tokyo.mainnet.block-engine.jito.wtf/api/v1/transactions")
            .json(&json!({
                "jsonrpc": "2.0",
                "id": 1,
                "method": "sendTransaction",
                "params": [base64::encode(txn.serialize())],
            }))
            .send()
            .await?;

        if jito_response.status().is_success() {
            let result: serde_json::Value = jito_response.json().await?;
            let signature = result["result"].as_str().unwrap();
            println!("Transaction succeeded: https://solscan.io/tx/{}", signature);
        } else {
            println!("Transaction failed: {}", jito_response.text().await?);
        }
    } else {
        println!("API Error: {}", response.text().await?);
    }

    Ok(())
}

Performing a Jito Bundle Swap

For Jito bundles, you can batch multiple swaps into a single transaction. Each swap must have its own parameters, and you can use one or more wallets.

A single failed transaction in a Jito Bundle swap will cause the entire bundle to fail. Ensure all parameters and wallets are correctly configured to avoid issues

Full code example
use reqwest::Client;
use base58::FromBase58;
use solana_sdk::{
    signature::{Keypair, Signer},
    transaction::Transaction,
    pubkey::Pubkey,
};
use std::error::Error;
use serde_json::json;
use tokio;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // Replace with your private keys
    let private_keys = vec![
        "your-private-key-1",
        "your-private-key-2",
    ];

    let wallets: Vec<Keypair> = private_keys
        .into_iter()
        .map(|key| {
            let decoded_key = key.from_base58().unwrap();
            Keypair::from_bytes(&decoded_key).unwrap()
        })
        .collect();

    let bundle_params = vec![
        json!({
            "wallet_address": wallets[0].pubkey().to_string(),
            "mint": "GAT41Hbuq2QVFKJZZGrALegyU2UKsPApkNGSoS2TjTGR",
            "action": "buy",
            "dex": "jupiter",
            "amount": 0.001,
            "tip": 0.0001,
        }),
        json!({
            "wallet_address": wallets[1].pubkey().to_string(),
            "mint": "GAT41Hbuq2QVFKJZZGrALegyU2UKsPApkNGSoS2TjTGR",
            "action": "sell",
            "dex": "raydium",
            "amount": 0.002,
            "tip": 0.0002,
        }),
    ];

    let client = Client::new();
    let url = "https://api.solanaportal.io/api/jito-bundle";

    // Send the POST request to the API
    let response = client.post(url)
        .json(&bundle_params)
        .send()
        .await?;

    if response.status().is_success() {
        let data: Vec<String> = response.json().await?;

        let mut signed_transactions = Vec::new();
        for (i, txn_data) in data.iter().enumerate() {
            let txn_buffer = base64::decode(txn_data)?;
            let mut txn = Transaction::deserialize(&txn_buffer)?;
            txn.sign(&[&wallets[i]], txn.message.recent_blockhash);
            signed_transactions.push(base64::encode(txn.serialize()));
        }

        // Submit the bundle
        let jito_response = client.post("https://tokyo.mainnet.block-engine.jito.wtf/api/v1/bundles")
            .json(&json!({
                "jsonrpc": "2.0",
                "id": 1,
                "method": "sendBundle",
                "params": [signed_transactions],
            }))
            .send()
            .await?;

        if jito_response.status().is_success() {
            let result: serde_json::Value = jito_response.json().await?;
            for (i, signature) in result["result"].as_array().unwrap().iter().enumerate() {
                println!("Transaction {}: https://solscan.io/tx/{}", i, signature.as_str().unwrap());
            }
        } else {
            println!("Jito Error Response: {}", jito_response.text().await?);
        }
    } else {
        println!("API Error: {}", response.text().await?);
    }

    Ok(())
}

Running the Code

To run the code, follow these steps:

  1. Save your code in src/main.rs.

  2. Build the project:

cargo build
  1. Run the project:

cargo run

Ensure you have all dependencies installed and your private keys are configured correctly.

Key Notes

  1. Jito Bundle Limitation: A single failed transaction in a bundle will fail the entire bundle.

  2. Environment Setup: Ensure you are connected to the Solana mainnet.

  3. Security: Never hardcode sensitive information like private keys in production code. Use environment variables or secret management tools.

  4. Error Handling: Always validate API responses and handle errors gracefully.

To learn how to implement swaps programmatically, visit the language-specific guides:

rustup
Swapping with Node.js
Swapping with Python