Skip to main content

🚀 Rust SDK

Build high-performance blockchain applications with Cedra's native Rust SDK. Designed for system-level integrations, the SDK provides zero-cost abstractions and compile-time safety for production blockchain development. Whether you're building trading bots, validator tools, or infrastructure services, Rust gives you the performance and reliability you need.

Start Building in Minutes

use cedra_sdk::{Client, LocalAccount};

// That's it! You're ready to build on Cedra
let client = Client::new("https://testnet.cedra.dev");
let account = LocalAccount::generate(&mut rand::rngs::OsRng);

Ready to dive deeper? Let's explore what makes the Rust SDK powerful.

📦 Installation

Add the Cedra SDK to your Rust project by updating your Cargo.toml:

Cargo.toml
[dependencies]
cedra-sdk = { git = "https://github.com/cedra-labs/cedra-network", branch = "testnet" }

[patch.crates-io]
merlin = { git = "https://github.com/cedra-labs/merlin" }

Create a .cargo/config.toml file in your project root:

.cargo/config.toml
[build]
rustflags = ["--cfg", "tokio_unstable"]
Production Deployment

For production applications, pin to specific commit hashes to ensure reproducible builds:

cedra-sdk = { git = "https://github.com/cedra-labs/cedra-network", rev = "abc123..." }

🎯 Your First Transaction

This complete example walks you through a typical token transfer workflow on Cedra:

  • Account Generation - Create two new accounts with cryptographic keypairs
  • Faucet Integration - Fund Alice's account with testnet tokens
  • Balance Queries - Check account balances at each step
  • Token Transfers - Send tokens between accounts with automatic gas handling
  • Transaction Confirmation - Wait for transactions to finalize on-chain
src/main.rs
use anyhow::{Context, Result};
use cedra_sdk::{
coin_client::CoinClient,
rest_client::{Client, FaucetClient},
types::LocalAccount,
};
use std::{str::FromStr, sync::LazyLock};
use url::Url;

static NODE_URL: LazyLock<Url> = LazyLock::new(|| {
Url::from_str(
std::env::var("CEDRA_NODE_URL")
.as_ref()
.map(|s| s.as_str())
.unwrap_or("https://testnet.cedra.dev"),
)
.unwrap()
});

static FAUCET_URL: LazyLock<Url> = LazyLock::new(|| {
Url::from_str(
std::env::var("CEDRA_FAUCET_URL")
.as_ref()
.map(|s| s.as_str())
.unwrap_or("https://faucet-api.cedra.dev"),
)
.unwrap()
});

#[tokio::main]
async fn main() -> Result<()> {
let rest_client = Client::new(NODE_URL.clone());
let faucet_client = FaucetClient::new(FAUCET_URL.clone(), NODE_URL.clone());

let coin_client = CoinClient::new(&rest_client);

let mut alice = LocalAccount::generate(&mut rand::rngs::OsRng);
let bob = LocalAccount::generate(&mut rand::rngs::OsRng);

// Print account addresses.
println!("\n=== Addresses ===");
println!("Alice: {}", alice.address().to_hex_literal());
println!("Bob: {}", bob.address().to_hex_literal());

// Create the accounts on chain, but only fund Alice.
faucet_client
.fund(alice.address(), 100_000_000)
.await
.context("Failed to fund Alice's account")?;
faucet_client
.create_account(bob.address())
.await
.context("Failed to create Bob's account")?;

// Print initial balances.
println!("\n=== Initial Balances ===");
println!(
"Alice: {:?}",
coin_client
.get_account_balance(&alice.address())
.await
.context("Failed to get Alice's account balance")?
);
println!(
"Bob: {:?}",
coin_client
.get_account_balance(&bob.address())
.await
.context("Failed to get Bob's account balance")?
);

// Have Alice send Bob some coins.
let txn_hash = coin_client
.transfer(&mut alice, bob.address(), 1_000, None)
.await
.context("Failed to submit transaction to transfer coins")?;
rest_client
.wait_for_transaction(&txn_hash)
.await
.context("Failed when waiting for the transfer transaction")?;

// Print intermediate balances.
println!("\n=== Intermediate Balances ===");
println!(
"Alice: {:?}",
coin_client
.get_account_balance(&alice.address())
.await
.context("Failed to get Alice's account balance the second time")?
);
println!(
"Bob: {:?}",
coin_client
.get_account_balance(&bob.address())
.await
.context("Failed to get Bob's account balance the second time")?
);

// Have Alice send Bob some more coins.
let txn_hash = coin_client
.transfer(&mut alice, bob.address(), 1_000, None)
.await
.context("Failed to submit transaction to transfer coins")?;

rest_client
.wait_for_transaction(&txn_hash)
.await
.context("Failed when waiting for the transfer transaction")?;

// Print final balances.
println!("\n=== Final Balances ===");
println!(
"Alice: {:?}",
coin_client
.get_account_balance(&alice.address())
.await
.context("Failed to get Alice's account balance the third time")?
);
println!(
"Bob: {:?}",
coin_client
.get_account_balance(&bob.address())
.await
.context("Failed to get Bob's account balance the third time")?
);

Ok(())
}

That's it! The SDK handles all the complexity - sequence numbers, gas estimation, signing, and confirmation. Notice how Rust's type system ensures you can't make mistakes like sending to an invalid address or using the wrong amount format.

While our TypeScript SDK is perfect for web applications, the Rust SDK is your choice when performance and reliability are non-negotiable.

🚀 Next Steps

Now that you've set up the SDK and sent your first transaction, here's your path to mastering Cedra development with Rust:

Core SDK Features

  • Account Management - Generate wallets, manage keys, and work with account resources
  • Transaction Guide - Build complex transactions, handle gas estimation, and understand the transaction lifecycle

Build Real Applications

Expand Your Knowledge