tenderly-rs

Crates.iotenderly-rs
lib.rstenderly-rs
version0.1.0
created_at2025-10-30 14:58:59.477905+00
updated_at2025-10-30 14:58:59.477905+00
descriptionAn unofficial Rust client library for the Tenderly API - Transaction simulation, contract verification, and wallet management
homepagehttps://docs.tenderly.co/
repositoryhttps://github.com/codeesura/tenderly-rs
max_upload_size
id1908392
size271,699
(codeesura)

documentation

https://docs.rs/tenderly-rs

README

Tenderly Rust SDK

License Crates.io Documentation

An unofficial Rust client library for the Tenderly API, providing transaction simulation, contract verification, and wallet management functionality.

Note: This is an unofficial, community-maintained Rust port of the Tenderly TypeScript SDK. It is not affiliated with or endorsed by Tenderly.

Features

  • Transaction Simulation - Simulate individual transactions or bundles
  • Contract Verification - Verify smart contracts on Tenderly
  • Wallet Management - Add and manage wallets
  • Contract Management - Add and track contracts
  • State Overrides - Simulate with custom state modifications
  • Async/Await - Built with Tokio for high-performance async operations
  • Type Safety - Strongly typed API with comprehensive error handling

Installation

Add this to your Cargo.toml:

[dependencies]
tenderly-rs = "0.1.0"
tokio = { version = "1", features = ["full"] }
dotenvy = "0.15"  # Optional, for environment variable support

Quick Start

Setup

Create a .env file with your Tenderly credentials:

TENDERLY_ACCESS_KEY=your_access_key
TENDERLY_ACCOUNT_NAME=your_account_name
TENDERLY_PROJECT_NAME=your_project_name

Or use environment variables directly:

use tenderly_rs::{Network, Tenderly, TenderlyConfiguration};

let tenderly = Tenderly::new(TenderlyConfiguration::new(
    "account_name".to_string(),
    "project_name".to_string(),
    "access_key".to_string(),
    Network::Mainnet,
))?;

Alternatively, load from environment variables:

use tenderly_rs::{Network, TenderlyConfiguration};
use dotenvy::dotenv;

dotenv().ok();
let config = TenderlyConfiguration::from_env(Network::Mainnet)?;
let tenderly = Tenderly::new(config)?;

Simulate a Transaction

use tenderly_rs::{Network, Tenderly, TenderlyConfiguration};
use tenderly_rs::executors::types::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let tenderly = Tenderly::new(TenderlyConfiguration::new(
        "account_name".to_string(),
        "project_name".to_string(),
        "access_key".to_string(),
        Network::Mainnet,
    ))?;

    let transaction = TransactionParameters {
        from: "0x...".to_string(),
        to: "0x...".to_string(),
        gas: 21000,
        gas_price: "0".to_string(),
        value: "0".to_string(),
        input: "0x...".to_string(),
        max_fee_per_gas: None,
        max_priority_fee_per_gas: None,
        access_list: None,
    };

    let simulation = SimulationParameters {
        transaction,
        block_number: 12345678,
        overrides: None,
    };

    let result = tenderly.simulator.simulate_transaction(&simulation).await?;
    println!("Gas used: {}", result.gas_used.unwrap_or(0));

    Ok(())
}

Simulate a Bundle

use tenderly_rs::executors::types::*;

let transactions = vec![
    TransactionParameters { /* ... */ },
    TransactionParameters { /* ... */ },
];

let bundle = SimulationBundleDetails {
    transactions,
    block_number: 12345678,
    overrides: None,
};

let results = tenderly.simulator.simulate_bundle(&bundle).await?;
println!("Simulated {} transactions", results.len());

Add a Contract

use tenderly_rs::ContractData;

let contract = tenderly.contracts.add(
    "0x6b175474e89094c44da98b954eedeac495271d0f",
    Some(&ContractData {
        display_name: Some("DAI".to_string()),
    }),
).await?;

Add a Wallet

use tenderly_rs::WalletData;

let wallet = tenderly.wallets.add(
    "0x...",
    Some(&WalletData {
        display_name: Some("My Wallet".to_string()),
    }),
).await?;

Verify a Contract

use tenderly_rs::services::contracts::types::*;

let verification_request = VerificationRequest {
    contract_to_verify: "Counter.sol:Counter".to_string(),
    solc: solc_config,
    config: VerificationConfig {
        mode: VerificationMode::Public,
    },
};

let verified = tenderly.contracts.verify(
    "0x...",
    &verification_request
).await?;

Examples

Run the included examples:

# Simulate a single transaction
cargo run --example simulate_transaction

# Simulate a bundle of transactions
cargo run --example simulate_bundle

# Simple bundle simulation
cargo run --example simulate_bundle_simple

# Add contracts to your project
cargo run --example add_contracts

# Add wallets to your project
cargo run --example add_wallets

# Verify a contract
cargo run --example verify_contract

Testing

Run all tests using the provided scripts:

# Run all tests (unit + doc + integration if credentials are set)
./run_tests.sh
# or using Make
make test-all

# Run quick tests (unit + doc only, no integration tests)
./quick_test.sh
# or using Make
make test-quick

# Run only unit tests
make test

# Run only doc tests
make test-doc

# Run only integration tests (requires Tenderly credentials)
make test-integration

Integration Tests

Integration tests require valid Tenderly credentials set in environment variables:

  • TENDERLY_ACCESS_KEY
  • TENDERLY_ACCOUNT_NAME
  • TENDERLY_PROJECT_NAME

Integration tests are marked with #[ignore] and can be run with:

cargo test --test simulator_test -- --ignored
cargo test --test contracts_test -- --ignored
cargo test --test wallets_test -- --ignored

Supported Networks

The SDK supports all networks supported by Tenderly, including:

  • Ethereum: Network::Mainnet, Network::Sepolia, Network::Holesky
  • L2s: Network::ArbitrumOne, Network::Optimism, Network::Base
  • Polygon: Network::Polygon, Network::PolygonAmoy
  • And 70+ more networks

See the Network enum for the complete list.

State Overrides

Simulate with custom state modifications:

use std::collections::HashMap;
use tenderly_rs::executors::types::*;

let mut overrides: SimulationParametersOverrides = HashMap::new();
let mut state_override = serde_json::Map::new();

state_override.insert(
    "balance".to_string(),
    serde_json::json!("0x1000000000000000000"),
);

overrides.insert(
    "0x...".to_string(),
    SimulationParametersOverride {
        nonce: None,
        code: None,
        balance: Some("1000000000000000000".to_string()),
        state: Some(serde_json::Value::Object(state_override)),
    },
);

let simulation = SimulationParameters {
    transaction,
    block_number: 12345678,
    overrides: Some(overrides),
};

Error Handling

The SDK provides comprehensive error types:

use tenderly_rs::errors::GeneralError;

match tenderly.simulator.simulate_transaction(&params).await {
    Ok(result) => println!("Success: {:?}", result),
    Err(e) => match e {
        GeneralError::ApiError(api_err) => {
            eprintln!("API Error ({}): {}", api_err.status, api_err.error.message);
        }
        GeneralError::Encoding(enc_err) => {
            eprintln!("Encoding Error: {}", enc_err.error.message);
        }
        GeneralError::NotFound(not_found) => {
            eprintln!("Not Found: {}", not_found.message);
        }
        GeneralError::Compilation(comp_err) => {
            eprintln!("Compilation Error: {}", comp_err.message);
        }
        _ => eprintln!("Error: {:?}", e),
    },
}

API Documentation

Full API documentation is available at docs.rs/tenderly-rs.

Requirements

  • Rust 1.70 or higher
  • Tokio runtime (for async operations)

Author

Developed by codeesura

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Links

Commit count: 0

cargo fmt