Exemples de Développement Solana

Exemples complets de développement blockchain Solana incluant les contrats intelligents Rust avec Anchor, les programmes haute performance, le développement NFT et le déploiement de programmes

Key Facts

Category
Blockchain
Items
4
Format Families
sample

Sample Overview

Exemples complets de développement blockchain Solana incluant les contrats intelligents Rust avec Anchor, les programmes haute performance, le développement NFT et le déploiement de programmes This sample set belongs to Blockchain and can be used to test related workflows inside Elysia Tools.

💻 Programme de Base Anchor rust

🟡 intermediate ⭐⭐⭐⭐

Introduction au développement Solana avec le framework Anchor, créant un contrat intelligent simple avec fonctionnalité de base

⏱️ 35 min 🏷️ anchor, solana, rust, smart-contract
Prerequisites: Rust programming, Solana basics, Anchor framework
// Anchor Framework Basic Program
// Cargo.toml dependencies:
// anchor-lang = "0.29.0"
// anchor-spl = "0.29.0"

use anchor_lang::prelude::*;
use anchor_spl::token::{self, Token, TokenAccount, Mint, Transfer};

declare_id!("11111111111111111111111111111111");

#[program]
pub mod basic_program {
    use super::*;

    /// Initialize the program
    pub fn initialize(ctx: Context<Initialize>, authority: Pubkey) -> Result<()> {
        let config = &mut ctx.accounts.config;
        config.authority = authority;
        config.counter = 0;
        config.is_initialized = true;

        msg!("Program initialized by authority: {}", authority);
        Ok(())
    }

    /// Increment counter
    pub fn increment_counter(ctx: Context<IncrementCounter>) -> Result<()> {
        let config = &mut ctx.accounts.config;
        config.counter += 1;

        msg!("Counter incremented to: {}", config.counter);
        Ok(())
    }

    /// Create a new token mint
    pub fn create_token_mint(
        ctx: Context<CreateTokenMint>,
        decimals: u8,
        name: String,
        symbol: String,
    ) -> Result<()> {
        let cpi_accounts = token::InitializeMint {
            mint: ctx.accounts.mint.to_account_info(),
            rent: ctx.accounts.rent.to_account_info(),
        };
        let cpi_program = ctx.accounts.token_program.to_account_info();
        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);

        token::initialize_mint(cpi_ctx, decimals, &ctx.accounts.authority.key(), None)?;

        // Store metadata (simplified example)
        let metadata = &mut ctx.accounts.metadata;
        metadata.name = name;
        metadata.symbol = symbol;
        metadata.decimals = decimals;
        metadata.mint = ctx.accounts.mint.key();

        msg!("Token created: {} ({})", metadata.name, metadata.symbol);
        Ok(())
    }

    /// Mint tokens to an account
    pub fn mint_tokens(
        ctx: Context<MintTokens>,
        amount: u64,
    ) -> Result<()> {
        let cpi_accounts = token::MintTo {
            mint: ctx.accounts.mint.to_account_info(),
            to: ctx.accounts.token_account.to_account_info(),
            authority: ctx.accounts.authority.to_account_info(),
        };
        let cpi_program = ctx.accounts.token_program.to_account_info();
        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);

        token::mint_to(cpi_ctx, amount)?;

        msg!("Minted {} tokens", amount);
        Ok(())
    }

    /// Transfer tokens between accounts
    pub fn transfer_tokens(
        ctx: Context<TransferTokens>,
        amount: u64,
    ) -> Result<()> {
        let cpi_accounts = Transfer {
            from: ctx.accounts.from.to_account_info(),
            to: ctx.accounts.to.to_account_info(),
            authority: ctx.accounts.authority.to_account_info(),
        };
        let cpi_program = ctx.accounts.token_program.to_account_info();
        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);

        token::transfer(cpi_ctx, amount)?;

        msg!("Transferred {} tokens", amount);
        Ok(())
    }
}

// Account structures
#[account]
pub struct Config {
    pub authority: Pubkey,
    pub counter: u64,
    pub is_initialized: bool,
}

#[account]
pub struct TokenMetadata {
    pub name: String,
    pub symbol: String,
    pub decimals: u8,
    pub mint: Pubkey,
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(
        init,
        payer = payer,
        space = 8 + 32 + 8 + 1 // discriminator + authority + counter + is_initialized
    )]
    pub config: Account<'info, Config>,

    #[account(mut)]
    pub payer: Signer<'info>,

    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct IncrementCounter<'info> {
    #[account(mut)]
    pub config: Account<'info, Config>,
    pub authority: Signer<'info>,
}

#[derive(Accounts)]
pub struct CreateTokenMint<'info> {
    #[account(
        init,
        payer = payer,
        mint::decimals = 0,
        mint::authority = mint_authority,
    )]
    pub mint: Account<'info, Mint>,

    #[account(
        init,
        payer = payer,
        space = 8 + 64 + 8 + 8 + 32 // discriminator + name + symbol + decimals + mint
    )]
    pub metadata: Account<'info, TokenMetadata>,

    /// CHECK: This is the mint authority PDA
    #[account(seeds = [b"mint_authority"], bump)]
    pub mint_authority: UncheckedAccount<'info>,

    pub authority: Signer<'info>,
    #[account(mut)]
    pub payer: Signer<'info>,
    pub rent: Sysvar<'info, Rent>,
    pub system_program: Program<'info, System>,
    pub token_program: Program<'info, Token>,
}

#[derive(Accounts)]
pub struct MintTokens<'info> {
    #[account(mut)]
    pub mint: Account<'info, Mint>,

    #[account(
        init_if_needed,
        payer = payer,
        token::mint = mint,
        token::authority = authority,
    )]
    pub token_account: Account<'info, TokenAccount>,

    pub authority: Signer<'info>,
    #[account(mut)]
    pub payer: Signer<'info>,
    pub system_program: Program<'info, System>,
    pub token_program: Program<'info, Token>,
    pub rent: Sysvar<'info, Rent>,
}

#[derive(Accounts)]
pub struct TransferTokens<'info> {
    #[account(mut)]
    pub from: Account<'info, TokenAccount>,

    #[account(mut)]
    pub to: Account<'info, TokenAccount>,

    pub authority: Signer<'info>,
    pub token_program: Program<'info, Token>,
}

// Error handling
#[error_code]
pub enum ErrorCode {
    #[msg("Unauthorized access")]
    Unauthorized,
    #[msg("Invalid amount")]
    InvalidAmount,
    #[msg("Account already initialized")]
    AlreadyInitialized,
    #[msg("Account not initialized")]
    NotInitialized,
}

💻 Déploiement et Test de Programmes Solana bash

🟡 intermediate ⭐⭐⭐

Guide complet pour déployer, tester et gérer les programmes Solana avec outils CLI et scripts d'automatisation

⏱️ 20 min 🏷️ deployment, solana, anchor, automation
Prerequisites: Solana CLI, Anchor framework, Linux/Unix shell
#!/bin/bash
# Solana Program Deployment Script
# Simplified deployment automation for Solana programs

set -e

# Configuration variables
PROGRAM_NAME="my_program"
NETWORK="devnet"  # Options: devnet, testnet, mainnet-beta
KEYPAIR_PATH="./deploy-keypair.json"

# Color output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'

# Simple logging function
log() {
    echo -e "${GREEN}=> $1${NC}"
}

warn() {
    echo -e "${YELLOW}=> WARNING: $1${NC}"
}

error() {
    echo -e "${RED}=> ERROR: $1${NC}"
    exit 1
}

# Check if required tools are installed
check_tools() {
    log "Checking required tools..."

    command -v solana >/dev/null 2>&1 || error "Solana CLI not installed"
    command -v anchor >/dev/null 2>&1 || error "Anchor CLI not installed"
    command -v cargo >/dev/null 2>&1 || error "Rust/Cargo not installed"

    log "All required tools found"
}

# Setup Solana environment
setup_environment() {
    log "Setting up Solana environment..."

    # Set network
    case "${NETWORK}" in
        "devnet")
            solana config set --url devnet
            ;;
        "testnet")
            solana config set --url testnet
            ;;
        "mainnet-beta")
            solana config set --url mainnet-beta
            ;;
    esac

    log "Network set to: ${NETWORK}"
}

# Generate keypair if needed
setup_keypair() {
    if [[ ! -f "${KEYPAIR_PATH}" ]]; then
        log "Generating new keypair..."
        solana-keygen new --outfile "${KEYPAIR_PATH}" --no-bip39-passphrase
    fi

    # Show balance
    local balance=$(solana balance --keypair "${KEYPAIR_PATH}" | grep -o '[0-9.]*' | head -1)
    log "Current balance: ${balance} SOL"

    # Request airdrop on devnet/testnet if needed
    if [[ "${NETWORK}" != "mainnet-beta" ]] && (( $(echo "${balance} < 1" | bc -l) )); then
        log "Requesting airdrop..."
        solana airdrop 2 --keypair "${KEYPAIR_PATH}"
    fi
}

# Build the program
build_program() {
    log "Building ${PROGRAM_NAME}..."

    if [[ ! -f "Anchor.toml" ]]; then
        error "Anchor.toml not found"
    fi

    # Build with Anchor
    anchor build

    if [[ $? -eq 0 ]]; then
        log "Build successful!"

        # Get program ID
        local program_id=$(solana address -k target/deploy/${PROGRAM_NAME}-keypair.json)
        log "Program ID: ${program_id}"

        # Check if program ID needs updating in lib.rs
        if [[ -f "programs/${PROGRAM_NAME}/src/lib.rs" ]]; then
            local current_id=$(grep "declare_id!" "programs/${PROGRAM_NAME}/src/lib.rs" | grep -o '"[^"]*"' | tr -d '"')
            if [[ "${current_id}" != "${program_id}" ]]; then
                log "Updating program ID in lib.rs..."
                sed -i "s/${current_id}/${program_id}/g" "programs/${PROGRAM_NAME}/src/lib.rs"
                anchor build  # Rebuild with correct ID
            fi
        fi
    else
        error "Build failed"
    fi
}

# Deploy program to network
deploy_program() {
    log "Deploying to ${NETWORK}..."

    # Check program size
    local size_bytes=$(stat -c%s "target/deploy/${PROGRAM_NAME}.so" 2>/dev/null || echo "0")
    local max_size=1232832

    if [[ "${size_bytes}" -gt "${max_size}" ]]; then
        warn "Program size (${size_bytes} bytes) exceeds recommended maximum"
    fi

    # Confirm mainnet deployment
    if [[ "${NETWORK}" == "mainnet-beta" ]]; then
        echo "You are about to deploy to mainnet-beta. Continue? [y/N]"
        read -r confirm
        if [[ "${confirm}" != "y" && "${confirm}" != "Y" ]]; then
            log "Deployment cancelled"
            exit 0
        fi
    fi

    # Deploy
    anchor deploy --provider.cluster "${NETWORK}"

    if [[ $? -eq 0 ]]; then
        local program_id=$(solana address -k target/deploy/${PROGRAM_NAME}-keypair.json)
        log "Successfully deployed: ${program_id}"
    else
        error "Deployment failed"
    fi
}

# Test program on devnet
test_program() {
    if [[ "${NETWORK}" != "devnet" ]]; then
        warn "Testing is only available on devnet"
        return
    fi

    log "Testing program..."

    # Run Anchor tests
    anchor test --skip-local-validator

    if [[ $? -eq 0 ]]; then
        log "All tests passed!"
    else
        warn "Some tests failed"
    fi
}

# Show program information
show_info() {
    log "Program Information:"
    echo "Name: ${PROGRAM_NAME}"
    echo "Network: ${NETWORK}"
    echo "KeyPair: ${KEYPAIR_PATH}"

    if [[ -f "target/deploy/${PROGRAM_NAME}-keypair.json" ]]; then
        local program_id=$(solana address -k target/deploy/${PROGRAM_NAME}-keypair.json)
        echo "Program ID: ${program_id}"

        # Check if deployed
        if solana program show "${program_id}" >/dev/null 2>&1; then
            echo "Status: Deployed"
        else
            echo "Status: Not deployed"
        fi
    fi
}

# Main function
main() {
    echo "Solana Program Deployment Script"
    echo "================================"
    echo ""

    case "${1:-deploy}" in
        "setup")
            check_tools
            setup_environment
            setup_keypair
            ;;
        "build")
            build_program
            ;;
        "deploy")
            check_tools
            setup_environment
            setup_keypair
            build_program
            deploy_program
            ;;
        "test")
            test_program
            ;;
        "info")
            show_info
            ;;
        "all")
            check_tools
            setup_environment
            setup_keypair
            build_program
            deploy_program
            test_program
            ;;
        "help"|"-h"|"--help")
            echo "Usage: $0 [COMMAND]"
            echo ""
            echo "Commands:"
            echo "  setup   - Check tools and setup environment"
            echo "  build   - Build the program"
            echo "  deploy  - Deploy to network"
            echo "  test    - Run tests (devnet only)"
            echo "  info    - Show program information"
            echo "  all     - Run setup, build, deploy, and test"
            echo "  help    - Show this help"
            echo ""
            echo "Environment variables:"
            echo "  NETWORK    - Solana network (devnet, testnet, mainnet-beta)"
            echo "  PROGRAM_NAME - Program directory name"
            ;;
        *)
            error "Unknown command: ${1}"
            ;;
    esac
}

# Run main function with all arguments
main "$@

💻 Programme NFT Solana avec Metaplex rust

🔴 complex ⭐⭐⭐⭐⭐

Implémentation complète NFT sur Solana utilisant le standard Metaplex, incluant gestion des métadonnées et droits d'auteur

⏱️ 45 min 🏷️ nft, solana, metaplex, digital-collectibles
Prerequisites: Rust, Anchor framework, Metaplex standard, Solana programming
// Solana NFT Program with Metaplex Standard
// Cargo.toml dependencies:
// anchor-lang = "0.29.0"
// anchor-spl = "0.29.0"
// mpl-token-metadata = "3.0.0"

use anchor_lang::prelude::*;
use anchor_spl::{
    token::{self, Mint, Token, TokenAccount, Transfer, InitializeMint},
    associated_token::AssociatedToken,
};
use mpl_token_metadata::{
    instruction::{
        create_master_edition_v3,
        create_metadata_accounts_v3,
        mint_new_edition_from_master_edition_via_token,
    },
    state::{Metadata, MasterEditionV2, CollectionDetails, Key},
};

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkgMQhgY6H5o");

#[program]
pub mod nft_program {
    use super::*;

    /// Create a new NFT collection
    pub fn create_collection(
        ctx: Context<CreateCollection>,
        name: String,
        symbol: String,
        uri: String,
    ) -> Result<()> {
        let metadata_infos = vec![
            ctx.accounts.metadata.to_account_info(),
            ctx.accounts.mint.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.payer.to_account_info(),
            ctx.accounts.token_metadata_program.to_account_info(),
            ctx.accounts.token_program.to_account_info(),
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.rent.to_account_info(),
        ];

        let collection_details = Some(CollectionDetails::V1 { size: 0 });

        create_metadata_accounts_v3(
            CpiContext::new(
                ctx.accounts.token_metadata_program.to_account_info(),
                CreateMetadataAccountsV3 {
                    metadata: ctx.accounts.metadata.to_account_info(),
                    mint: ctx.accounts.mint.to_account_info(),
                    mint_authority: ctx.accounts.authority.to_account_info(),
                    update_authority: ctx.accounts.authority.to_account_info(),
                    payer: ctx.accounts.payer.to_account_info(),
                    system_program: ctx.accounts.system_program.to_account_info(),
                    rent: ctx.accounts.rent.to_account_info(),
                },
            ),
            name,
            symbol,
            uri,
            None,
            0,
            true,
            collection_details,
            None,
        )?;

        let master_edition_infos = vec![
            ctx.accounts.master_edition.to_account_info(),
            ctx.accounts.mint.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.payer.to_account_info(),
            ctx.accounts.token_metadata_program.to_account_info(),
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.rent.to_account_info(),
        ];

        create_master_edition_v3(
            CpiContext::new(
                ctx.accounts.token_metadata_program.to_account_info(),
                CreateMasterEditionV3 {
                    edition: ctx.accounts.master_edition.to_account_info(),
                    mint: ctx.accounts.mint.to_account_info(),
                    update_authority: ctx.accounts.authority.to_account_info(),
                    mint_authority: ctx.accounts.authority.to_account_info(),
                    payer: ctx.accounts.payer.to_account_info(),
                    system_program: ctx.accounts.system_program.to_account_info(),
                    token_program: ctx.accounts.token_program.to_account_info(),
                    rent: ctx.accounts.rent.to_account_info(),
                },
            ),
            Some(0), // Max supply
        )?;

        // Store collection info in program account
        let collection = &mut ctx.accounts.collection;
        collection.name = name;
        collection.symbol = symbol;
        collection.uri = uri;
        collection.mint = ctx.accounts.mint.key();
        collection.authority = ctx.accounts.authority.key();
        collection.item_count = 0;
        collection.created_at = Clock::get()?.unix_timestamp;

        msg!("Collection created: {} ({})", collection.name, collection.symbol);
        Ok(())
    }

    /// Mint a new NFT into a collection
    pub fn mint_nft(
        ctx: Context<MintNft>,
        name: String,
        symbol: String,
        uri: String,
        seller_fee_basis_points: u16,
    ) -> Result<()> {
        // Create metadata
        let metadata_infos = vec![
            ctx.accounts.metadata.to_account_info(),
            ctx.accounts.mint.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.payer.to_account_info(),
            ctx.accounts.token_metadata_program.to_account_info(),
            ctx.accounts.token_program.to_account_info(),
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.rent.to_account_info(),
        ];

        create_metadata_accounts_v3(
            CpiContext::new(
                ctx.accounts.token_metadata_program.to_account_info(),
                CreateMetadataAccountsV3 {
                    metadata: ctx.accounts.metadata.to_account_info(),
                    mint: ctx.accounts.mint.to_account_info(),
                    mint_authority: ctx.accounts.authority.to_account_info(),
                    update_authority: ctx.accounts.authority.to_account_info(),
                    payer: ctx.accounts.payer.to_account_info(),
                    system_program: ctx.accounts.system_program.to_account_info(),
                    rent: ctx.accounts.rent.to_account_info(),
                },
            ),
            name,
            symbol,
            uri,
            Some(ctx.accounts.authority.key()),
            seller_fee_basis_points,
            true,
            None,
            Some(Collection {
                key: Key::CollectionV1,
                verified: true,
            }),
        )?;

        // Create master edition
        let master_edition_infos = vec![
            ctx.accounts.master_edition.to_account_info(),
            ctx.accounts.mint.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.payer.to_account_info(),
            ctx.accounts.token_metadata_program.to_account_info(),
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.rent.to_account_info(),
        ];

        create_master_edition_v3(
            CpiContext::new(
                ctx.accounts.token_metadata_program.to_account_info(),
                CreateMasterEditionV3 {
                    edition: ctx.accounts.master_edition.to_account_info(),
                    mint: ctx.accounts.mint.to_account_info(),
                    update_authority: ctx.accounts.authority.to_account_info(),
                    mint_authority: ctx.accounts.authority.to_account_info(),
                    payer: ctx.accounts.payer.to_account_info(),
                    system_program: ctx.accounts.system_program.to_account_info(),
                    token_program: ctx.accounts.token_program.to_account_info(),
                    rent: ctx.accounts.rent.to_account_info(),
                },
            ),
            Some(0), // One of a kind
        )?;

        // Mint one token to the holder
        let cpi_accounts = token::MintTo {
            mint: ctx.accounts.mint.to_account_info(),
            to: ctx.accounts.token_account.to_account_info(),
            authority: ctx.accounts.authority.to_account_info(),
        };
        let cpi_program = ctx.accounts.token_program.to_account_info();
        let cpi_ctx = CpiContext::new_with_signer(
            cpi_program,
            cpi_accounts,
            &[&[b"mint_authority", &[ctx.bumps.mint_authority]]],
        );
        token::mint_to(cpi_ctx, 1)?;

        // Update collection item count
        let collection = &mut ctx.accounts.collection;
        collection.item_count += 1;

        // Store NFT info
        let nft_info = &mut ctx.accounts.nft_info;
        nft_info.mint = ctx.accounts.mint.key();
        nft_info.owner = ctx.accounts.owner.key();
        nft_info.collection_mint = collection.mint;
        nft_info.name = name;
        nft_info.uri = uri;
        nft_info.seller_fee_basis_points = seller_fee_basis_points;
        nft_info.created_at = Clock::get()?.unix_timestamp;

        msg!("NFT minted: {}", name);
        Ok(())
    }

    /// Transfer NFT to new owner
    pub fn transfer_nft(
        ctx: Context<TransferNft>,
        amount: u64,
    ) -> Result<()> {
        let cpi_accounts = Transfer {
            from: ctx.accounts.source_token_account.to_account_info(),
            to: ctx.accounts.destination_token_account.to_account_info(),
            authority: ctx.accounts.source_authority.to_account_info(),
        };
        let cpi_program = ctx.accounts.token_program.to_account_info();
        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);

        token::transfer(cpi_ctx, amount)?;

        // Update NFT ownership
        let nft_info = &mut ctx.accounts.nft_info;
        nft_info.owner = ctx.accounts.destination_authority.key();

        msg!("NFT transferred to new owner");
        Ok(())
    }
}

// Account structures
#[account]
pub struct Collection {
    pub name: String,
    pub symbol: String,
    pub uri: String,
    pub mint: Pubkey,
    pub authority: Pubkey,
    pub item_count: u64,
    pub created_at: i64,
}

#[account]
pub struct NftInfo {
    pub mint: Pubkey,
    pub owner: Pubkey,
    pub collection_mint: Pubkey,
    pub name: String,
    pub uri: String,
    pub seller_fee_basis_points: u16,
    pub created_at: i64,
}

#[derive(Accounts)]
pub struct CreateCollection<'info> {
    #[account(
        init,
        payer = payer,
        space = 8 + 32 + 32 + 64 + 32 + 8 + 8 // discriminator + name + symbol + uri + mint + authority + item_count + created_at
    )]
    pub collection: Account<'info, Collection>,

    #[account(mut)]
    pub metadata: UncheckedAccount<'info>,
    #[account(mut)]
    pub master_edition: UncheckedAccount<'info>,
    #[account(mut)]
    pub mint: Signer<'info>,
    pub authority: Signer<'info>,
    #[account(mut)]
    pub payer: Signer<'info>,

    pub token_metadata_program: UncheckedAccount<'info>,
    pub token_program: Program<'info, Token>,
    pub system_program: Program<'info, System>,
    pub rent: Sysvar<'info, Rent>,
}

#[derive(Accounts)]
pub struct MintNft<'info> {
    #[account(mut)]
    pub collection: Account<'info, Collection>,

    #[account(
        init,
        payer = payer,
        space = 8 + 32 + 32 + 32 + 64 + 64 + 2 + 8 // discriminator + mint + owner + collection_mint + name + uri + seller_fee + created_at
    )]
    pub nft_info: Account<'info, NftInfo>,

    #[account(mut)]
    pub metadata: UncheckedAccount<'info>,
    #[account(mut)]
    pub master_edition: UncheckedAccount<'info>,
    #[account(mut)]
    pub mint: Signer<'info>,

    /// CHECK: This is the mint authority PDA
    #[account(seeds = [b"mint_authority"], bump)]
    pub mint_authority: UncheckedAccount<'info>,

    #[account(
        init_if_needed,
        payer = payer,
        token::mint = mint,
        token::authority = mint_authority,
    )]
    pub token_account: Account<'info, TokenAccount>,

    pub owner: Signer<'info>,
    pub authority: Signer<'info>,
    #[account(mut)]
    pub payer: Signer<'info>,

    pub token_metadata_program: UncheckedAccount<'info>,
    pub token_program: Program<'info, Token>,
    associated_token_program: Program<'info, AssociatedToken>,
    pub system_program: Program<'info, System>,
    pub rent: Sysvar<'info, Rent>,
}

#[derive(Accounts)]
pub struct TransferNft<'info> {
    #[account(mut)]
    pub nft_info: Account<'info, NftInfo>,

    #[account(mut)]
    pub source_token_account: Account<'info, TokenAccount>,
    #[account(mut)]
    pub destination_token_account: Account<'info, TokenAccount>,

    pub source_authority: Signer<'info>,
    pub destination_authority: SystemAccount<'info>,

    pub token_program: Program<'info, Token>,
}

// Error handling
#[error_code]
pub enum NftErrorCode {
    #[msg("Invalid collection")]
    InvalidCollection,
    #[msg("NFT already minted")]
    NftAlreadyMinted,
    #[msg("Invalid royalty percentage")]
    InvalidRoyalty,
    #[msg("Unauthorized transfer")]
    UnauthorizedTransfer,
}

💻 Programme Solana Haute Performance rust

🔴 complex ⭐⭐⭐⭐⭐

Programme Solana optimisé pour applications haut débit avec structures de données efficaces et opérations batch

⏱️ 50 min 🏷️ performance, optimization, solana, high-throughput
Prerequisites: Advanced Rust, Solana optimization, Blockchain performance
// High-Performance Solana Program
// Optimized for throughput and efficiency
// Cargo.toml dependencies:
// anchor-lang = "0.29.0"
// anchor-spl = "0.29.0"
// solana-program = "1.16.0"

use anchor_lang::prelude::*;
use anchor_spl::token::{Token, TokenAccount};
use std::collections::BTreeMap;
use std::mem::size_of;

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkgMQhgY6H5o");

#[program]
pub mod high_performance_program {
    use super::*;

    /// Initialize high-performance storage
    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        let storage = &mut ctx.accounts.storage;
        storage.authority = ctx.accounts.authority.key();
        storage.item_count = 0;
        storage.total_volume = 0;
        storage.last_update = Clock::get()?.unix_timestamp;

        // Initialize batch processing state
        storage.batch_processing = false;
        storage.pending_operations = 0;

        msg!("High-performance storage initialized");
        Ok(())
    }

    /// Batch process multiple operations for efficiency
    pub fn batch_process_operations(
        ctx: Context<BatchProcessOperations>,
        operations: Vec<Operation>,
    ) -> Result<()> {
        require!(operations.len() <= 100, ErrorCode::BatchTooLarge);

        let storage = &mut ctx.accounts.storage;
        storage.batch_processing = true;
        storage.pending_operations = operations.len() as u32;

        // Pre-allocate result array
        let mut results: Vec<OperationResult> = Vec::with_capacity(operations.len());

        // Process operations in chunks for better performance
        for chunk in operations.chunks(10) {
            for operation in chunk {
                let result = match operation.operation_type {
                    0 => process_create_user(&mut ctx.accounts.user_storage, &operation.data),
                    1 => process_update_balance(&mut ctx.accounts.balance_storage, &operation.data),
                    2 => process_transfer(&mut ctx.accounts.balance_storage, &operation.data),
                    _ => return Err(ErrorCode::InvalidOperationType.into()),
                };

                results.push(result);
            }

            // Yield CPU every 10 operations to avoid hitting compute limits
            solana_program::program::invoke(
                &solana_program::system_instruction::transfer(
                    &ctx.accounts.authority.key(),
                    &ctx.accounts.authority.key(),
                    0,
                ),
                &[
                    ctx.accounts.authority.to_account_info(),
                    ctx.accounts.authority.to_account_info(),
                ],
            )?;
        }

        // Update statistics
        storage.item_count += operations.len() as u64;
        storage.total_volume += calculate_total_volume(&results);
        storage.last_update = Clock::get()?.unix_timestamp;
        storage.batch_processing = false;
        storage.pending_operations = 0;

        emit!(BatchProcessed {
            operation_count: operations.len() as u64,
            success_count: results.iter().filter(|r| r.success).count() as u64,
            total_volume: calculate_total_volume(&results),
        });

        msg!("Processed {} operations successfully", operations.len());
        Ok(())
    }

    /// Create optimized user account with compressed storage
    pub fn create_user_optimized(
        ctx: Context<CreateUserOptimized>,
        user_id: [u8; 32],
        username: String,
        metadata: UserMetadata,
    ) -> Result<()> {
        require!(username.len() <= 32, ErrorCode::UsernameTooLong);

        let user_data = &mut ctx.accounts.user_data;
        user_data.user_id = user_id;
        user_data.username = username;
        user_data.metadata = metadata;
        user_data.balance = 0;
        user_data.nonce = 0;
        user_data.created_at = Clock::get()?.unix_timestamp;
        user_data.last_active = Clock::get()?.unix_timestamp;

        // Use bit flags for efficient boolean storage
        user_data.flags = 0;
        if metadata.is_verified {
            user_data.flags |= 1 << 0;
        }
        if metadata.is_premium {
            user_data.flags |= 1 << 1;
        }

        emit!(UserCreated {
            user_id,
            username: user_data.username.clone(),
        });

        msg!("User created efficiently: {}", user_data.username);
        Ok(())
    }

    /// High-frequency trading operations
    pub fn execute_trade(
        ctx: Context<ExecuteTrade>,
        trade_data: TradeData,
    ) -> Result<()> {
        let clock = Clock::get()?;
        let current_slot = clock.slot;

        // Validate trade window (reduced compute cost)
        require!(
            current_slot <= trade_data.expiry_slot,
            ErrorCode::TradeExpired
        );

        let order_book = &mut ctx.accounts.order_book;
        let trade_history = &mut ctx.accounts.trade_history;

        // Find matching order efficiently using binary search
        let match_result = find_matching_order(order_book, &trade_data)?;

        if let Some(matching_order) = match_result {
            // Execute trade
            let trade = execute_trade_logic(
                &trade_data,
                &matching_order,
                current_slot,
            )?;

            // Store trade in circular buffer for efficiency
            let index = (trade_history.count % MAX_TRADES) as usize;
            trade_history.trades[index] = trade;
            trade_history.count += 1;

            // Update order book
            remove_order(order_book, matching_order.order_id)?;

            // Update statistics
            let storage = &mut ctx.accounts.storage;
            storage.total_volume += trade.volume;

            emit!(TradeExecuted {
                order_id: trade_data.order_id,
                matched_order_id: matching_order.order_id,
                volume: trade.volume,
                price: trade.price,
            });
        }

        Ok(())
    }
}

// Optimized data structures
#[account]
pub struct HighPerformanceStorage {
    pub authority: Pubkey,
    pub item_count: u64,
    pub total_volume: u128,
    pub last_update: i64,
    pub batch_processing: bool,
    pub pending_operations: u32,
}

#[account]
pub struct UserDataOptimized {
    pub user_id: [u8; 32],
    // Use fixed-size arrays for better performance
    pub username: [u8; 32], // Truncated/encoded username
    pub balance: u64,
    pub nonce: u64,
    pub created_at: i64,
    pub last_active: i64,
    pub flags: u8, // Bit flags for boolean values
    pub metadata_bytes: [u8; 64], // Compressed metadata
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct UserMetadata {
    pub is_verified: bool,
    pub is_premium: bool,
    pub level: u8,
    pub experience: u32,
}

#[account]
pub struct OrderBook {
    pub orders: Vec<Order>, // Consider using custom serialization for better efficiency
    pub count: u64,
    pub last_updated: i64,
}

#[account]
pub struct TradeHistory {
    pub trades: [Trade; MAX_TRADES], // Circular buffer
    pub count: u64,
    pub head: u64,
}

// Struct definitions
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct Operation {
    pub operation_type: u8,
    pub data: Vec<u8>,
    pub priority: u8,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct OperationResult {
    pub success: bool,
    pub error_code: Option<u32>,
    pub gas_used: u64,
    pub result_data: Vec<u8>,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct Order {
    pub order_id: [u8; 32],
    pub user_id: [u8; 32],
    pub order_type: u8, // 0 = bid, 1 = ask
    pub amount: u64,
    pub price: u64,
    pub expiry_slot: u64,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct TradeData {
    pub order_id: [u8; 32],
    pub user_id: [u8; 32],
    pub order_type: u8,
    pub amount: u64,
    pub price: u64,
    pub expiry_slot: u64,
    pub slippage_tolerance: u16, // basis points
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct Trade {
    pub trade_id: [u8; 32],
    pub order_id: [u8; 32],
    pub matched_order_id: [u8; 32],
    pub amount: u64,
    pub price: u64,
    pub volume: u128,
    pub slot: u64,
    pub timestamp: i64,
}

// Constants
const MAX_TRADES: usize = 1000;

// Helper functions
fn process_create_user(
    user_storage: &mut Account<UserDataOptimized>,
    data: &[u8],
) -> OperationResult {
    // Efficient user creation logic
    OperationResult {
        success: true,
        error_code: None,
        gas_used: 1000,
        result_data: vec![],
    }
}

fn process_update_balance(
    balance_storage: &mut Account<UserDataOptimized>,
    data: &[u8],
) -> OperationResult {
    // Efficient balance update
    OperationResult {
        success: true,
        error_code: None,
        gas_used: 500,
        result_data: vec![],
    }
}

fn process_transfer(
    balance_storage: &mut Account<UserDataOptimized>,
    data: &[u8],
) -> OperationResult {
    // Efficient transfer logic
    OperationResult {
        success: true,
        error_code: None,
        gas_used: 1500,
        result_data: vec![],
    }
}

fn find_matching_order(
    order_book: &OrderBook,
    trade_data: &TradeData,
) -> Result<Option<Order>> {
    // Binary search implementation for efficiency
    Ok(None) // Placeholder
}

fn execute_trade_logic(
    trade: &TradeData,
    matching_order: &Order,
    current_slot: u64,
) -> Result<Trade> {
    let volume = (trade.amount as u128).saturating_mul(matching_order.price as u128);

    Ok(Trade {
        trade_id: [0u8; 32], // Generate unique ID
        order_id: trade.order_id,
        matched_order_id: matching_order.order_id,
        amount: trade.amount,
        price: trade.price,
        volume,
        slot: current_slot,
        timestamp: Clock::get()?.unix_timestamp,
    })
}

fn remove_order(order_book: &mut OrderBook, order_id: [u8; 32]) -> Result<()> {
    // Efficient order removal
    Ok(())
}

fn calculate_total_volume(results: &[OperationResult]) -> u128 {
    // Calculate total volume from results
    0
}

// Context definitions
#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(
        init,
        payer = authority,
        space = 8 + 32 + 8 + 16 + 8 + 1 + 4 // discriminator + authority + item_count + total_volume + last_update + batch_processing + pending_operations
    )]
    pub storage: Account<'info, HighPerformanceStorage>,

    #[account(mut)]
    pub authority: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct BatchProcessOperations<'info> {
    #[account(mut)]
    pub storage: Account<'info, HighPerformanceStorage>,

    #[account(mut)]
    pub user_storage: Account<'info, UserDataOptimized>,

    #[account(mut)]
    pub balance_storage: Account<'info, UserDataOptimized>,

    pub authority: Signer<'info>,
}

#[derive(Accounts)]
pub struct CreateUserOptimized<'info> {
    #[account(
        init,
        payer = authority,
        space = 8 + 32 + 32 + 8 + 8 + 8 + 8 + 1 + 64 // discriminator + optimized structure
    )]
    pub user_data: Account<'info, UserDataOptimized>,

    #[account(mut)]
    pub authority: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct ExecuteTrade<'info> {
    #[account(mut)]
    pub storage: Account<'info, HighPerformanceStorage>,

    #[account(mut)]
    pub order_book: Account<'info, OrderBook>,

    #[account(mut)]
    pub trade_history: Account<'info, TradeHistory>,

    pub authority: Signer<'info>,
}

// Event definitions
#[event]
pub struct BatchProcessed {
    pub operation_count: u64,
    pub success_count: u64,
    pub total_volume: u128,
}

#[event]
pub struct UserCreated {
    pub user_id: [u8; 32],
    pub username: String,
}

#[event]
pub struct TradeExecuted {
    pub order_id: [u8; 32],
    pub matched_order_id: [u8; 32],
    pub volume: u128,
    pub price: u64,
}

// Error handling
#[error_code]
pub enum ErrorCode {
    #[msg("Batch size too large")]
    BatchTooLarge,
    #[msg("Invalid operation type")]
    InvalidOperationType,
    #[msg("Username too long")]
    UsernameTooLong,
    #[msg("Trade expired")]
    TradeExpired,
    #[msg("Insufficient balance")]
    InsufficientBalance,
    #[msg("Order not found")]
    OrderNotFound,
    #[msg("Invalid price")]
    InvalidPrice,
}