A comprehensive Solana raffle program built with the Anchor framework, featuring escrow functionality and pNFT (Programmable NFT) support.
- π² Raffle System: Create, join, and draw winners for raffles
- π¦ Escrow Integration: Secure prize management with automatic escrow
- π¨ pNFT Support: Create and use Programmable NFTs as prizes
- π° Multiple Prize Types: SOL, SPL tokens, and pNFTs
- π Security: Built with Anchor's security best practices
- π± TypeScript SDK: Easy-to-use client library
- π§ͺ Comprehensive Tests: Full test coverage for all functionality
- Raffle Program: Main Anchor program handling raffle logic
- Escrow System: Secure holding of prizes until winner is determined
- pNFT Integration: Support for Programmable NFTs as prizes
- Client SDK: TypeScript library for easy integration
programs/solana-raffle/src/
βββ lib.rs # Main program logic
βββ instructions/ # Individual instruction handlers
βββ state/ # Account state definitions
βββ errors.rs # Custom error types
- Rust (latest stable)
- Solana CLI (v1.17.0+)
- Anchor Framework (v0.29.0+)
- Node.js (v18+)
- Yarn or npm
-
Clone the repository
git clone <repository-url> cd solana-raffle
-
Install dependencies
yarn install # or npm install -
Build the program
anchor build
-
Run tests
anchor test
./scripts/build-and-deploy.sh# Build the program
anchor build
# Deploy to devnet
anchor deploy
# Verify deployment
ts-node scripts/deploy.ts deployimport { SolanaRaffleClient } from './client';
import { Connection, Keypair } from '@solana/web3.js';
import { AnchorProvider, Wallet } from '@coral-xyz/anchor';
// Setup
const connection = new Connection('https://api.devnet.solana.com');
const wallet = new Wallet(Keypair.generate());
const client = new SolanaRaffleClient(connection, wallet);
// Create a SOL raffle
const { rafflePda, escrowPda, tx } = await client.createRaffle({
ticketPrice: 0.1, // 0.1 SOL per ticket
maxTickets: 100, // Maximum 100 tickets
endTime: Date.now() + 3600000, // Ends in 1 hour
prizeType: 'sol' // Prize is SOL
});
console.log(`Raffle created: ${rafflePda.toString()}`);// Join with 5 tickets
const joinTx = await client.joinRaffle(rafflePda, 5);
console.log(`Joined raffle: ${joinTx}`);// Draw winner (only after raffle ends)
const drawTx = await client.drawWinner(rafflePda);
// Claim prize (only by winner)
const claimTx = await client.claimPrize(rafflePda);// Create a pNFT
const { metadataPda } = await client.createPnftPrize(
'Rare Digital Art',
'RDA',
'https://arweave.net/metadata-hash'
);
// Create a pNFT raffle
const { rafflePda } = await client.createRaffle({
ticketPrice: 0.05,
maxTickets: 50,
endTime: Date.now() + 1800000,
prizeType: 'pnft'
});The project includes comprehensive tests covering:
- Basic Functionality: Create, join, draw, claim
- Escrow System: Fund management and security
- pNFT Operations: Creation and integration
- Edge Cases: Error handling and validation
- Integration Tests: End-to-end workflows
# Run all tests
anchor test
# Run specific test file
anchor test tests/solana-raffle.ts
# Run tests without local validator
anchor test --skip-local-validatortests/
βββ solana-raffle.ts # Main functionality tests
βββ escrow-tests.ts # Escrow system tests
βββ pnft-tests.ts # pNFT integration tests
[programs.devnet]
solana_raffle = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
[programs.mainnet]
solana_raffle = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
[provider]
cluster = "Devnet"
wallet = "~/.config/solana/id.json"# Solana network
export SOLANA_NETWORK=devnet
# Wallet path
export SOLANA_WALLET=~/.config/solana/id.json
# RPC endpoint
export SOLANA_RPC_URL=https://api.devnet.solana.comcreateRaffle(config: RaffleConfig): Create a new rafflejoinRaffle(rafflePda: PublicKey, ticketCount: number): Join a raffledrawWinner(rafflePda: PublicKey): Draw the winnerclaimPrize(rafflePda: PublicKey, ...): Claim the prizecreatePnftPrize(name: string, symbol: string, uri: string): Create pNFTgetRaffleInfo(rafflePda: PublicKey): Get raffle informationgetEscrowBalance(rafflePda: PublicKey): Get escrow balance
interface RaffleConfig {
ticketPrice: number; // SOL amount per ticket
maxTickets: number; // Maximum tickets
endTime: number; // Unix timestamp
prizeType: 'sol' | 'token' | 'pnft';
}
interface RaffleInfo {
authority: PublicKey;
ticketPrice: anchor.BN;
maxTickets: number;
ticketsSold: number;
endTime: anchor.BN;
prizeType: any;
winner: number | null;
claimed: boolean;
}- PDA Usage: All accounts use Program Derived Addresses
- Access Control: Proper authority checks on all operations
- Escrow Protection: Funds are held securely until winner claims
- Input Validation: All inputs are validated before processing
- Always verify program ID before interacting
- Check raffle state before joining or drawing
- Validate timestamps for raffle end times
- Use proper randomness for winner selection
- Handle errors gracefully in client applications
solana-raffle/
βββ programs/
β βββ solana-raffle/
β βββ Cargo.toml
β βββ src/
β βββ lib.rs
βββ tests/
β βββ solana-raffle.ts
β βββ escrow-tests.ts
β βββ pnft-tests.ts
βββ client/
β βββ index.ts
β βββ package.json
β βββ tsconfig.json
βββ scripts/
β βββ deploy.ts
β βββ build-and-deploy.sh
βββ examples/
β βββ basic-usage.ts
βββ Anchor.toml
βββ Cargo.toml
βββ package.json
# Build the program
anchor build
# Build client SDK
cd client && npm run build
# Clean build artifacts
anchor clean# Check Rust code
cargo clippy
# Check TypeScript code
cd client && npm run lint- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Rust and TypeScript best practices
- Add tests for new functionality
- Update documentation for API changes
- Ensure all tests pass before submitting
This project is licensed under the MIT License - see the LICENSE file for details.
- Documentation: Check this README and inline code comments
- Issues: Open an issue on GitHub for bugs or feature requests
- Discussions: Use GitHub Discussions for questions and ideas
- Anchor Framework for the development framework
- Solana for the blockchain platform
- Metaplex for NFT standards and tools