Sol.College

Full lesson

carbon

Carbon is an indexing framework on Solana.

What it does

From the project README:

Carbon is built around a pipeline: datasources stream Solana updates into the runtime, decoders turn raw account and transaction data into typed Rust structures, and processors handle the decoded output in order to build data pipelines and indexers for your applications. Each part is modular, so you can swap RPC streams for Geyser streams, generated decoders for custom ones, or logging processors for Postgres, GraphQL, analytics, bots, and other application-specific sinks.
Original
sevenlabs-hq/carbon
SuperStack fork
Blockchains/carbon @ bebd108
Stars
638
Last push (original)
2026-11-02
Languages
Rust, TypeScript, Nunjucks, JavaScript, Shell
Detected stack
Native Rust
Categories
DeFiInfrastructure & Tooling
Licence
MIT

Architecture

11233 source files. By extension: .rs ×11192, .ts ×41.

Top-level directorySource files
decoders11111
packages41
crates35
examples24
datasources18
metrics2
misc2

Dapp: deploying

This fork is queued for its own live dapp on Sol.College, with a Devnet/Mainnet switch. It appears here, at /dapps/carbon/, once it is deployed and checked on devnet. Until then, run it locally with the commands below.

Key code, explained

Excerpts chosen automatically where the code uses the most Solana concepts, pinned to the fork's commit.

sevenlabs-hq/carbon · decoders/token-2022-decoder/src/instructions/mod.rs L121–144 @ bebd108 · MIT · original
    initialize_token_group_member::*, initialize_token_metadata::*,    initialize_transfer_fee_config::*, initialize_transfer_hook::*, mint_to::*, mint_to_checked::*,    pause::*, permissioned_burn::*, permissioned_burn_checked::*, reallocate::*,    remove_token_metadata_key::*, resume::*, revoke::*, set_authority::*, set_transfer_fee::*,    sync_native::*, thaw_account::*, transfer::*, transfer_checked::*,    transfer_checked_with_fee::*, ui_amount_to_amount::*, unwrap_lamports::*,    update_confidential_transfer_mint::*, update_default_account_state::*,    update_group_member_pointer::*, update_group_pointer::*, update_metadata_pointer::*,    update_multiplier_scaled_ui_mint::*, update_rate_interest_bearing_mint::*,    update_token_group_max_size::*, update_token_group_update_authority::*,    update_token_metadata_field::*, update_token_metadata_update_authority::*,    update_transfer_hook::*, withdraw_excess_lamports::*,    withdraw_withheld_tokens_from_accounts::*,    withdraw_withheld_tokens_from_accounts_for_confidential_transfer_fee::*,    withdraw_withheld_tokens_from_mint::*,    withdraw_withheld_tokens_from_mint_for_confidential_transfer_fee::*,}; #[derive(Debug, Clone, PartialEq)]#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]#[cfg_attr(feature = "serde", serde(tag = "type", content = "data"))]pub enum Token2022Instruction {    AmountToUiAmount {        program_id: solana_pubkey::Pubkey,
  1. Line 122 initialize_transfer_fee_config::*, initialize_transfer_hook::*, mint_to::*, mint_to_checke: Mints new tokens. The mint authority must sign.
  2. Line 125 sync_native::*, thaw_account::*, transfer::*, transfer_checked::*,: A checked token transfer, which also verifies the mint and decimals.
  3. Line 142 pub enum Token2022Instruction {: Targets the Token-2022 program instead of the original Token Program.
sevenlabs-hq/carbon · decoders/token-2022-decoder/src/instructions/postgres/mod.rs L337–360 @ bebd108 · MIT · original
                let row = thaw_account_row::ThawAccountRow::from_parts(data.clone(), metadata.clone(), raw_accounts.clone());                row.insert(pool).await?;                Ok(())            }            Token2022Instruction::TransferChecked { data, .. } => {                let row = transfer_checked_row::TransferCheckedRow::from_parts(data.clone(), metadata.clone(), raw_accounts.clone());                row.insert(pool).await?;                Ok(())            }            Token2022Instruction::ApproveChecked { data, .. } => {                let row = approve_checked_row::ApproveCheckedRow::from_parts(data.clone(), metadata.clone(), raw_accounts.clone());                row.insert(pool).await?;                Ok(())            }            Token2022Instruction::MintToChecked { data, .. } => {                let row = mint_to_checked_row::MintToCheckedRow::from_parts(data.clone(), metadata.clone(), raw_accounts.clone());                row.insert(pool).await?;                Ok(())            }            Token2022Instruction::BurnChecked { data, .. } => {                let row = burn_checked_row::BurnCheckedRow::from_parts(data.clone(), metadata.clone(), raw_accounts.clone());                row.insert(pool).await?;                Ok(())            }
  1. Line 341 Token2022Instruction::TransferChecked { data, .. } => {: A checked token transfer, which also verifies the mint and decimals.
  2. Line 341 Token2022Instruction::TransferChecked { data, .. } => {: Targets the Token-2022 program instead of the original Token Program.
  3. Line 351 Token2022Instruction::MintToChecked { data, .. } => {: Mints new tokens. The mint authority must sign.
sevenlabs-hq/carbon · decoders/jupiter-perpetuals-decoder/src/accounts/stake_info.rs L1–24 @ bebd108 · MIT · original
//! This code was AUTOGENERATED using the Codama library.use solana_pubkey::Pubkey; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]#[derive(Debug, Clone, borsh::BorshSerialize, borsh::BorshDeserialize, PartialEq)]pub struct StakeInfo {    pub pool: Pubkey,    pub stake_account: Pubkey,    pub current_staked_amount_lamports: u64,    pub total_staking_rewards_lamports: u64,    pub last_updated_at: i64,    pub deactivating: bool,    pub stake_account_index: u64,    pub bump: u8,} impl StakeInfo {    pub fn decode(data: &[u8]) -> Option<Self> {        if data.len() < 8 {            return None;        }        let discriminator = &data[0..8];        if discriminator != [66, 62, 68, 70, 108, 179, 183, 235] {            return None;
  1. Line 10 pub total_staking_rewards_lamports: u64,: Touches staking state: the amount locked and when it was locked.
  2. Line 14 pub bump: u8,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
sevenlabs-hq/carbon · decoders/jupiter-perpetuals-decoder/src/accounts/postgres/stake_info_row.rs L1–24 @ bebd108 · MIT · original
//! This code was AUTOGENERATED using the Codama library.use carbon_core::{    account::AccountMetadata,    postgres::{        metadata::AccountRowMetadata,        primitives::{Pubkey, U64, U8},    },}; #[derive(sqlx::FromRow, Debug, Clone)]pub struct StakeInfoRow {    #[sqlx(flatten)]    pub account_metadata: AccountRowMetadata,    pub pool: Pubkey,    pub stake_account: Pubkey,    pub current_staked_amount_lamports: U64,    pub total_staking_rewards_lamports: U64,    pub last_updated_at: i64,    pub deactivating: bool,    pub stake_account_index: U64,    pub bump: U8,} impl StakeInfoRow {
  1. Line 17 pub total_staking_rewards_lamports: U64,: Touches staking state: the amount locked and when it was locked.
  2. Line 21 pub bump: U8,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.

How to run, build and test

These commands come from the repo's own manifests (package.json scripts, Anchor.toml, Cargo, go.mod, Makefile). Check the README for prerequisites and environment variables.

DirectoryCommandRuns
.npm run devturbo run dev
.npm run buildturbo run build
.npm run testturbo run test
.npm run lintturbo run lint
packages/renderernpm run devtsup --watch
packages/renderernpm run buildtsup && cp -r templates dist/
packages/renderernpm run testnode --test tests/*.test.mjs
packages/renderernpm run lintecho 'No linting configured'
packages/versionsnpm run devtsup --watch
packages/versionsnpm run buildtsup
packages/versionsnpm run testnode --test tests/*.test.mjs
packages/clinpm run devtsup --watch
packages/clinpm run buildtsup
packages/clinpm run testnode --test tests/*.test.mjs
.cargo buildRust workspace build
.cargo testRust tests

What you could build from it

Used in lessons