#![deny(unreachable_pub)]
#![warn(missing_docs)]
mod analyze;
mod bundled_idls;
mod check;
mod compute;
mod cpi_tree;
mod decode;
mod diagnose;
mod diffs;
mod error;
mod fixture;
pub mod idl;
mod idl_encode;
mod idl_model;
mod invariant;
pub(crate) mod ixname;
mod preflight;
#[cfg(feature = "profiler")]
pub mod profile;
mod program;
pub mod reconstruct;
mod replay;
pub mod report;
pub mod scan;
mod scope;
mod search;
pub mod spec;
mod submit;
mod trace;
pub(crate) mod utils;
#[cfg(test)]
mod wire_format_tests;
pub use analyze::{
AccountDiff, AccountOverview, Analysis, Explanation, FieldDiff, Overview, ProgramInfo, SigInfo,
SimulationReport,
};
pub use check::{AccountCheck, Check, Cmp, Scenario};
pub use compute::CuUsage;
pub use cpi_tree::{CpiEntry, IxAccount, IxArg};
pub use decode::{AccountInfo, DecodedAccount, Field};
pub use diagnose::Diagnosis;
pub use diffs::{BalanceChange, TokenChange};
pub use error::{Error, Result};
pub use fixture::{Fixture, FixtureEntry, FIXTURE_VERSION};
pub use invariant::Invariant;
pub use preflight::{compute_breakdown, AccountRole, PreflightIx, PreflightOverview};
pub use program::{MethodBuilder, ProgramClient};
pub use replay::{
AssertOutcome, FeatureToggle, Mutation, ReplayResult, ScenarioOutcome, TimeTravel,
};
pub use scan::{scan_breaking_points, BreakingPoint, ScanOptions};
pub use scope::{
AccountProvenance, AccountState, Fidelity, FidelityCertificate, OnchainRecord, PatchComparison,
Provenance, Replay, Replayed, Scope,
};
pub use search::Threshold;
pub use submit::CapturedTransaction;
pub use trace::{
DecodedEvent, ReturnData, Step, StepAccountState, StepDiff, StepError, StepSummary, Trace,
TraceDiff,
};
#[cfg(doctest)]
#[doc = include_str!("../README.md")]
pub struct ReadmeDoctests;
pub fn resolve_rpc_url(cluster: Option<&str>, rpc: Option<&str>, default: &str) -> Result<String> {
if let Some(u) = rpc {
if u.starts_with("http") {
return Ok(u.to_string());
}
}
match cluster.map(|c| c.trim().to_ascii_lowercase()).as_deref() {
None | Some("") => Ok(default.to_string()),
Some("mainnet") | Some("mainnet-beta") | Some("m") => {
Ok("https://api.mainnet-beta.solana.com".into())
}
Some("devnet") | Some("d") => Ok("https://api.devnet.solana.com".into()),
Some("testnet") | Some("t") => Ok("https://api.testnet.solana.com".into()),
Some("localnet") | Some("local") | Some("localhost") | Some("l") => {
Ok("http://127.0.0.1:8899".into())
}
Some(other) if other.starts_with("http") => Ok(other.to_string()),
Some(other) => Err(Error::InvalidSpec(format!(
"unknown cluster '{other}' (expected mainnet, devnet, testnet, or localnet)"
))),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resolve_rpc_url_precedence() {
assert_eq!(
resolve_rpc_url(Some("devnet"), Some("http://my"), "http://def").unwrap(),
"http://my"
);
assert_eq!(
resolve_rpc_url(Some("devnet"), None, "http://def").unwrap(),
"https://api.devnet.solana.com"
);
assert_eq!(
resolve_rpc_url(Some("m"), None, "http://def").unwrap(),
"https://api.mainnet-beta.solana.com"
);
assert_eq!(
resolve_rpc_url(Some("localnet"), None, "http://def").unwrap(),
"http://127.0.0.1:8899"
);
assert_eq!(
resolve_rpc_url(None, None, "http://def").unwrap(),
"http://def"
);
assert!(matches!(
resolve_rpc_url(Some("nope"), None, "http://def"),
Err(Error::InvalidSpec(_))
));
assert_eq!(
resolve_rpc_url(None, Some("garbage"), "http://def").unwrap(),
"http://def"
);
}
}