Switchboard Documentation
  • Switchboard On Demand
  • Understanding Switchboard
    • Introduction
      • Why Switchboard Oracles?
      • Vision & mission
      • Brief History and Key Achievements to Date
      • Switchboard’s Architecture, Tech Stack and Security
        • Trusted Execution Environments (TEEs)
        • Oracle Queues
        • Node Architecture
  • Product Documentation
    • Data Feeds
      • Getting Started with Switchboard Data Feeds
      • Solana / SVM
        • Part 1: Designing and Simulating Your Feed
          • Option 1: Drag-and-Drop Feed Builder
          • Option 2: Designing a Feed in Typescript
        • Part 2: Deploying your Feed On-Chain
        • Part 3: Integrating your Feed
          • Integrating your Feed On-Chain
          • Integrating into Frontends
        • Costs
        • Integrating on Eclipse
      • EVM
        • Part 1: Prerequisites and Quick Start Guide
        • Part 2: Designing and Creating Your Feed
          • Option 1: Drag-and-Drop Feed Builder
          • Option 2: Designing a Feed in Typescript
        • Part 3: Integrating your Feed
          • Integrating your Feed On-Chain
          • Integrating your Feed with Typescript
          • Integrating into Frontends (EVM)
      • Aptos
      • Sui
      • Movement
      • Starknet
      • Optional Features
        • Switchboard Secrets
    • Aggregator
      • How to use the Switchboard Oracle Aggregator
    • Randomness
      • Why Randomness is important?
      • Switchboard's Approach to Verifiable Randomness
      • Tutorials
        • Solana / SVM
        • EVM
  • Tooling and Resources
    • Crossbar
      • Run Crossbar with Docker Compose
    • Switchboard Command Line Interface
    • Technical Resources and Documentation
      • SDKs and Documentation
      • Solana Accounts
      • EVM Identifiers
      • Code Examples (Github)
  • Switchboard Protocol
    • (Re)staking
      • What is (re)staking?
      • What are Node Consensus Networks (NCNs)?
      • What are Vault Receipt Tokens (VRTs)?
      • The Node Partner Program
      • The Switchboard NCN
    • Running a Switchboard Oracle
      • Prerequisites
        • Knowledge about Linux, containers and Self-Hosting
        • Hardware Requirements and AMD SEV SNP
        • Software Requirements
        • Network Requirements
      • Hardware: tested providers and setup
        • OVH
      • Platform: Kubernetes + AMD SEV SNP
        • Bare Metal with Kubernetes (K3s)
      • The Git Repo: Clone Our Code
        • Repo Structure
      • Configuration: Tweaking Configurations
        • cfg/00-common-vars.cfg
        • cfg/00-devnet-vars.cfg and cfg/00-mainnet-vars.cfg
      • Installation: Setup Via Scripts
        • Bare Metal with Kubernetes (K3s) + AMD SEV SNP
  • Frequently Asked Questions and Glossary
    • FAQ
    • Glossary
Powered by GitBook
On this page
  1. Product Documentation
  2. Randomness
  3. Tutorials

Solana / SVM

Switchboard Randomness for Solana and SVM applications

Prerequisites

  • Basic understanding of Solana development and Anchor Framework.

  • A working Solana development environment (Solana tool suite, Anchor).

  • Solana CLI connected to the devnet.

  • Enough SOL tokens for devnet transactions.

Tooling:

Install Switchboard On-Demand in your program.

cargo add switchboard-on-demand

Install Switchboard On-Demand in your Javascript Client file:

npm i @switchboard-xyz/on-demand

Step 1: Coin Flip Program (Solana)

  1. Define the Player State

    Make sure to store the user's randomness_account in your program.

    #[account]
    pub struct PlayerState {
        allowed_user: Pubkey,
        latest_flip_result: bool,
        randomness_account: Pubkey,
        current_guess: bool,
        wager: u64,
        bump: u8,
    }
  • Commit to a Future Slot

    Commit to the game by locking the randomness_account.

    pub fn coin_flip(ctx: Context<CoinFlip>, randomness_account: Pubkey, guess: bool) -> Result<()> {
        // Load clock to check data from the future        
        let clock = Clock::get()?;
        // Update player_state's randomness_account
        let randomness_data = RandomnessAccountData::parse(ctx.accounts.randomness_account_data.data.borrow()).unwrap();    
        if randomness_data.seed_slot != clock.slot - 1 {
            msg!("seed_slot: {}", randomness_data.seed_slot);
            msg!("slot: {}", clock.slot);
            return Err(ErrorCode::RandomnessAlreadyRevealed.into());
        }
    
        // **IMPORTANT**:
        // Remember in Switchboard Randomness, game collateral MUST be taken upon randomness request, not on reveal.
        // ***
        transfer(
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.user.to_account_info(),
            ctx.accounts.escrow_account.to_account_info(),
            player_state.wager,
            None,
        )?;
    
        // Store flip commitment to the future slot byt referencing the randomness account
        player_state.randomness_account = randomness_account;
    }
  • Settle the Flip

    Resolve randomness through the settle_flip function.

    pub fn settle_flip(ctx: Context<SettleFlip>) -> Result<()> {
        // Load clock to check data from the future
        let clock = Clock::get()?;
    
        // Parsing the oracle's scroll Call the switchboard on-demand parse function to get the randomness data
        let randomness_data = RandomnessAccountData::parse(ctx.accounts.randomness_account_data.data.borrow()).unwrap();
        
        // Call the switchboard on-demand get_value function to get the revealed random value
        let revealed_random_value = randomness_data.get_value(&clock)
            .map_err(|_| ErrorCode::RandomnessNotResolved)?;
    }

Step 2: TypeScript Client

  1. Setup and Environment Configuration:

import * as anchor from "@coral-xyz/anchor";
import {
  Connection,
  PublicKey,
  Keypair,
  Transaction,
  SystemProgram,
  VersionedTransaction,
} from "@solana/web3.js";
import {
  AnchorUtils,
  InstructionUtils,
  Queue,
  Randomness,
  SB_ON_DEMAND_PID,
  sleep,
} from "@switchboard-xyz/on-demand";
import dotenv from "dotenv";
import * as fs from "fs";
import reader from "readline-sync";

(async function () {
  dotenv.config();
  console.clear();
  
  const { keypair, connection, provider, wallet } = await AnchorUtils.loadEnv();
  const payer = wallet.payer;
  // Switchboard sbQueue fixed
  const sbQueue = new PublicKey("FfD96yeXs4cxZshoPPSKhSPgVQxLAJUT3gefgh84m1Di");
  const sbProgramId = SB_ON_DEMAND_PID;
  const sbProgram = await anchor.Program.at(sbProgramId, sbProgramId, provider);
  const queueAccount = new Queue(sbProgram, sbQueue);

  // setup
  const path = "sb-randomness/target/deploy/sb_randomness-keypair.json";
  
  const [_, myProgramKeypair] = await AnchorUtils.initWalletFromFile(path);
  const coinFlipProgramId = myProgramKeypair.publicKey;
  const coinFlipProgram = await myAnchorProgram(provider, coinFlipProgramId);
  1. Creating a Randomness Account: Before flipping that coin, start with a clean randomness account.

const rngKp = Keypair.generate();
const [randomness, ix] = await Randomness.create(sbProgram, rngKp, sbQueue);
  1. Committing to Randomness: Use randomness account to commit to the oracle.

const commitIx = await randomness.commitIx(sbQueue);
// Add this instruction to your coinFlip transaction and send it
  1. Revealing the Vision: Once the slot is generated, invoke to generate randomness for the committed slot.

const revealIx = await randomness.revealIx();
// Execute the reveal instruction, followed by your program's settle_flip function

Note: here is an optional way to save the revealIx()transaction .

randomness.serializeIxToFile(
  [revealIx, SettleFlipIx],
  "serializedIx.bin"
);
  1. Settling the Flip: Finally, record the coin flip in the randomness account.

const settleFlipIx = await coinFlipProgram.instruction.settleFlip(
    escrowBump,
    {
      accounts: {
        playerState: playerStateAccount,
        randomnessAccountData: randomness.pubkey,
        escrowAccount: escrowAccount,
        user: provider.wallet.publicKey,
        systemProgram: SystemProgram.programId,
      },
    }
  );
// Add the revealIx and this instruction together and execute

You've just integrated randomness into your Solana application.

PreviousTutorialsNextEVM

Last updated 2 months ago

For more details, refer to the example

repository