Carbon is a lightweight indexing framework on Solana. It provides a modular pipeline for sourcing data, decoding updates and processing them in order to build end-to-end indexers.
The core of the framework. It orchestrates data flow from data sources through indexing pipes.
A consumable datasource that will provide updates to the pipeline. These can either be AccountUpdate
, TransactionUpdate
or AccountDeletion
.
Process specific updates:
- Account Pipes handle account updates. Each contains an
AccountDecoder
and aProcessor
. - Account Deletion Pipes handle account deletions. Each contains a
Processor
. - Instruction Pipes handle transaction updates, instruction by instruction. Each contains an
InstructionDecoder
and aProcessor
. - Transaction Pipes handle transaction updates, after schema-matching the whole transaction. Each contains a
Schema
and aProcessor
.
Collect and report on pipeline performance and operational data.
Our premade metrics crates assist with common use cases:
Crate Name | Description | Ease of Setup |
---|---|---|
carbon-log-metrics |
Logs useful program info to the terminal | Easy |
carbon-prometheus-metrics |
Provides a way of exporting default and custom metrics to a Prometheus server | Medium |
use carbon_core::pipeline::Pipeline;
use carbon_rpc_block_subscribe_datasource::{RpcBlockSubscribe, Filters};
use solana_client::{
rpc_config::{RpcBlockSubscribeConfig, RpcBlockSubscribeFilter},
};
use crate::{
MyAccountDecoder, MyAccountProcessor,
MyInstructionDecoder, MyInstructionProcessor,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let pipeline = Pipeline::builder()
.datasource(
RpcBlockSubscribe::new(
env::var("RPC_URL")?,
Filters::new(RpcBlockSubscribeFilter::MentionsAccountOrProgram(env::var("MY_PROGRAM_ID")?), None)
)
)
.instruction(MyInstructionDecoder::new(), MyInstructionProcessor)
.metrics(Arc::new(LogMetrics::new()))
.build()?;
pipeline.run().await?;
Ok(())
}
Decoders implementations allow the pipeline to input raw account or instruction data and to receive deserialized account or instruction data. They are the backbone of indexing with Carbon.
Carbon provides a CLI tool to generate decoders based on IDL files (Anchor, Codama) or from a provided program address with a network specified to fetch an on-chain PDA IDL. This can significantly speed up the process of creating custom decoders for your Solana programs.
You can install the Carbon CLI by downloading the pre-built binary for your operating system:
curl -LO https://github.com/sevenlabs-hq/carbon/releases/latest/download/carbon-cli-linux-amd64
chmod +x carbon-cli-linux-amd64
sudo mv carbon-cli-linux-amd64 /usr/local/bin/carbon-cli
curl -LO https://github.com/sevenlabs-hq/carbon/releases/latest/download/carbon-cli-macos-amd64
chmod +x carbon-cli-macos-amd64
sudo mv carbon-cli-macos-amd64 /usr/local/bin/carbon-cli
- Download the latest release from https://github.com/sevenlabs-hq/carbon/releases/latest/download/carbon-cli-windows-amd64.exe
- Rename the downloaded file to
carbon-cli.exe
- Move the file to a directory in your PATH
Alternatively, you can build from source using Cargo:
cargo install --git https://github.com/sevenlabs-hq/carbon.git carbon-cli
$ carbon-cli parse [OPTIONS] --idl <IDL> --output <OUTPUT>
-i, --idl <IDL>
: Path to an IDL json file or a Solana program address.-o, --output <OUTPUT>
: Path to the desired output directory.-c, --as-crate
: Generate a directory or a crate.-s, --standard
: Specify the IDL standard to parse. Default: 'anchor' if not specified..-e, --event-hints
: Comma-separated names of defined types to parse as CPI Events (for '--standard codama' option only).-u, --url
: Network URL to fetch the IDL from. Required if input is a program address.-h, --help
: Print help information.
- To generate a decoder from an Anchor IDL file:
$ carbon-cli parse --idl my_program.json --output ./src/decoders
This will parse the my_program.json Anchor IDL file and generate the corresponding decoder code in the ./src/decoders directory.
- To generate a decoder from an Anchor PDA IDL, specify a program address (Meteora DLMM program in this case):
$ carbon-cli parse --idl LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo -u mainnet-beta --output ./src/decoders
This will fetch Meteora DLMM program's IDL from chain and generate the corresponding decoder code in the ./src/decoders directory.
- To generate a decoder from a Codama IDL:
$ carbon-cli parse --idl my_program_codama.json --output ./src/decoders --standard codama
This will parse the my_program_codama.json Codama IDL file and generate the corresponding decoder code in the ./src/decoders directory.
Note: in order to parse CPI Events for a provided Codama IDL, add --event-hints
option with comma-separated names of corresponding defined Codama types:
$ carbon-cli parse --idl my_program_codama.json --output ./src/decoders --standard codama --event-hints event1,event2,event3
use carbon_core::account::{AccountDecoder, AccountMetadata, AccountProcessorInputType, DecodedAccount};
use crate::MyCustomAccountData;
struct MyAccountProcessor;
#[async_trait]
impl Processor for MyAccountProcessor {
type InputType = AccountProcessorInputType<MyCustomAccountData>;
async fn process(
&mut self,
input: Self::InputType,
metrics: Arc<MetricsCollection>,
) -> CarbonResult<()> {
// Implement processing logic
}
}
For most use cases, we recommend choosing from one of our datasource crates:
Crate Name | Description | Affordability | Ease of Setup |
---|---|---|---|
carbon-block-subscribe |
Uses blockSubscribe with Solana WS JSON RPC to listen to real-time on-chain transactions |
Cheap (just RPC) | Easy |
carbon-program-subscribe |
Uses programSubscribe with Solana WS JSON RPC to listen to real-time on-chain account updates |
Cheap (just RPC) | Easy |
carbon-transaction-crawler |
Crawls historical successful transactions for a specific address in reverse chronological order using Solana JSON RPC | Cheap (just RPC) | Easy |
carbon-helius-atlas-ws |
Utilizes Helius Geyser-enhanced WebSocket for streaming account and transaction updates | Medium (Helius Plan) | Medium |
carbon-yellowstone-grpc |
Subscribes to a Yellowstone gRPC Geyser plugin enhanced full node to stream account and transaction updates | Expensive (Geyser Fullnode) | Complex |
You can still implement custom datasources in the following manner:
use carbon_core::datasource::{Datasource, Update, UpdateType};
struct MyDataSource;
#[async_trait]
impl Datasource for MyDataSource {
async fn consume(
&self,
sender: &tokio::sync::mpsc::UnboundedSender<Update>,
cancellation_token: CancellationToken,
) -> CarbonResult<()> {
// Implement data fetching and sending logic
}
fn update_types(&self) -> Vec<UpdateType> {
vec![UpdateType::AccountUpdate, UpdateType::Transaction]
}
}
Decoders for most popular Solana programs are published and maintained:
Crate Name | Description | Program ID |
---|---|---|
carbon-jupiter-dca-decoder |
Jupiter DCA Program Decoder | DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M |
carbon-jupiter-limit-order-decoder |
Jupiter Limit Order Program Decoder | jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu |
carbon-jupiter-limit-order-2-decoder |
Jupiter Limit Order 2 Program Decoder | j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X |
carbon-jupiter-swap-decoder |
Jupiter Swap Program Decoder | JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 |
carbon-meteora-dlmm-decoder |
Meteora DLMM Program Decoder | LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo |
carbon-mpl-core-decoder |
MPL Core Program Decoder | CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d |
carbon-mpl-token-metadata-decoder |
MPL Token Metadata Program Decoder | metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s |
carbon-orca-whirlpool-decoder |
Orca Whirlpool Program Decoder | whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc |
carbon-pumpfun-decoder |
Pumpfun Program Decoder | 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P |
carbon-raydium-amm-v4-decoder |
Raydium AMM V4 Program Decoder | 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 |
carbon-raydium-clmm-decoder |
Raydium CLMM Program Decoder | CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK |
carbon-raydium-cpmm-decoder |
Raydium CPMM Program Decoder | CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C |
carbon-system-program-decoder |
System Program Decoder | 11111111111111111111111111111111 |
carbon-token-program-decoder |
Token Program Decoder | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA |
carbon-kamino-lending-decoder |
Kamino Lend Decoder | KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD |
carbon-kamino-vault-decoder |
Kamino Vault Decoder | kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr |
carbon-openbook-v2-decoder |
Openbook V2 Decoder | opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb |
carbon-sharky-decoder |
SharkyFi Decoder | SHARKobtfF1bHhxD2eqftjHBdVSCbKo9JtgK71FhELP |
carbon-moonshot-decoder |
Moonshot Decoder | MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG |
We are under the MIT license.