scope/lib.rs
1//! # Scope Blockchain Analysis
2//!
3//! A command-line tool and library for blockchain data analysis,
4//! portfolio tracking, and transaction investigation.
5//!
6//! ## Features
7//!
8//! - **Address Analysis**: Query balances (with USD valuation), transaction history,
9//! and token holdings (ERC-20, SPL, TRC-20) for blockchain addresses across
10//! multiple chains. Chain auto-detection from address format.
11//!
12//! - **Transaction Analysis**: Look up and decode blockchain transactions across
13//! EVM chains (via Etherscan proxy API), Solana (via `getTransaction` RPC),
14//! and Tron (via TronGrid). Includes receipt data, gas usage, and status.
15//!
16//! - **Token Crawling**: Crawl DEX data for any token with price, volume,
17//! liquidity, holder analysis, and risk scoring. Markdown report generation.
18//!
19//! - **Live Monitoring**: Real-time TUI dashboard with price/volume/candlestick
20//! charts, buy/sell gauges, activity logs, and Unicode-rich visualization.
21//!
22//! - **Portfolio Management**: Track multiple addresses across chains with
23//! labels, tags, and aggregated balance views including ERC-20, SPL, and
24//! TRC-20 token balances.
25//!
26//! - **Data Export**: Export transaction history in JSON or CSV with date range
27//! filtering. Chain auto-detection for addresses.
28//!
29//! - **USD Valuation**: Native token prices via DexScreener for all supported
30//! chains (ETH, SOL, BNB, MATIC, etc.).
31//!
32//! ## Supported Chains
33//!
34//! ### EVM-Compatible
35//!
36//! - Ethereum Mainnet
37//! - Polygon
38//! - Arbitrum
39//! - Optimism
40//! - Base
41//! - BSC (BNB Smart Chain)
42//! - Aegis (Wraith)
43//!
44//! ### Non-EVM
45//!
46//! - Solana
47//! - Tron
48//!
49//! ## Quick Start (CLI)
50//!
51//! ```bash
52//! # Analyze an address
53//! scope address 0x742d35Cc6634C0532925a3b844Bc9e7595f1b3c2
54//!
55//! # Analyze a transaction
56//! scope tx 0xabc123...
57//!
58//! # Manage portfolio
59//! scope portfolio add 0x742d... --label "Main Wallet"
60//! scope portfolio list
61//!
62//! # Export data
63//! scope export --address 0x742d... --output history.json
64//! ```
65//!
66//! ## Library Usage
67//!
68//! The Scope library can be used programmatically in your Rust applications:
69//!
70//! ```rust,no_run
71//! use scope::{Config, chains::EthereumClient};
72//!
73//! #[tokio::main]
74//! async fn main() -> scope::Result<()> {
75//! // Load configuration
76//! let config = Config::load(None)?;
77//!
78//! // Create a chain client
79//! let client = EthereumClient::new(&config.chains)?;
80//!
81//! // Query an address balance (with USD valuation)
82//! let mut balance = client.get_balance("0x742d35Cc6634C0532925a3b844Bc9e7595f1b3c2").await?;
83//! client.enrich_balance_usd(&mut balance).await;
84//! println!("Balance: {} (${:.2})", balance.formatted, balance.usd_value.unwrap_or(0.0));
85//!
86//! // Look up a transaction
87//! let tx = client.get_transaction("0xabc123...").await?;
88//! println!("From: {}, Status: {:?}", tx.from, tx.status);
89//!
90//! // Fetch ERC-20 token balances
91//! let tokens = client.get_erc20_balances("0x742d35Cc6634C0532925a3b844Bc9e7595f1b3c2").await?;
92//! for token in &tokens {
93//! println!("{}: {}", token.token.symbol, token.formatted_balance);
94//! }
95//!
96//! Ok(())
97//! }
98//! ```
99//!
100//! ## Configuration
101//!
102//! Scope reads configuration from `~/.config/scope/config.yaml`:
103//!
104//! ```yaml
105//! chains:
106//! # EVM chains
107//! ethereum_rpc: "https://mainnet.infura.io/v3/YOUR_KEY"
108//! bsc_rpc: "https://bsc-dataseed.binance.org"
109//! aegis_rpc: "http://localhost:8545"
110//!
111//! # Non-EVM chains
112//! solana_rpc: "https://api.mainnet-beta.solana.com"
113//! tron_api: "https://api.trongrid.io"
114//!
115//! api_keys:
116//! etherscan: "YOUR_ETHERSCAN_KEY"
117//! polygonscan: "YOUR_POLYGONSCAN_KEY"
118//! bscscan: "YOUR_BSCSCAN_KEY"
119//! solscan: "YOUR_SOLSCAN_KEY"
120//! tronscan: "YOUR_TRONSCAN_KEY"
121//!
122//! output:
123//! format: table # table, json, csv
124//! color: true
125//!
126//! portfolio:
127//! data_dir: "~/.local/share/scope"
128//! ```
129//!
130//! ## Error Handling
131//!
132//! All fallible operations return [`Result<T>`], which uses [`ScopeError`]
133//! as the error type. This provides detailed error context for debugging
134//! and user-friendly error messages.
135//!
136//! ```rust
137//! use scope::{ScopeError, Result};
138//!
139//! fn validate_address(addr: &str) -> Result<()> {
140//! if !addr.starts_with("0x") || addr.len() != 42 {
141//! return Err(ScopeError::InvalidAddress(addr.to_string()));
142//! }
143//! Ok(())
144//! }
145//! ```
146//!
147//! ## Modules
148//!
149//! - [`chains`]: Blockchain client implementations (Ethereum/EVM, Solana, Tron, DexScreener)
150//! - [`cli`]: Command-line interface definitions (address, tx, crawl, monitor, portfolio, export)
151//! - [`config`]: Configuration management
152//! - [`display`]: Terminal output utilities and markdown report generation
153//! - [`error`]: Error types and result aliases
154//! - [`tokens`]: Token alias storage for friendly name lookups
155
156// Re-export commonly used types at crate root
157pub use config::Config;
158pub use error::{ConfigError, Result, ScopeError};
159
160/// Blockchain client implementations.
161///
162/// Provides abstractions and concrete clients for interacting with
163/// blockchain networks. See `ChainClient` for the common
164/// interface and `EthereumClient` for EVM chain support.
165pub mod chains;
166
167/// Command-line interface definitions.
168///
169/// Contains argument structures and command handlers for the Scope CLI.
170/// This module is primarily used by the binary crate but is exposed
171/// for programmatic CLI invocation. It provides the main `Cli` struct
172/// and `Commands` enum that define all available commands.
173pub mod cli;
174
175/// Configuration management.
176///
177/// Handles loading, merging, and validation of configuration from
178/// multiple sources (CLI args, environment variables, config files).
179pub mod config;
180
181/// Display utilities for terminal output and reports.
182///
183/// Provides ASCII chart rendering and markdown report generation
184/// for token analytics data.
185pub mod display;
186
187/// Error types and result aliases.
188///
189/// Defines [`ScopeError`] for all error conditions and provides a
190/// convenient [`Result`] type alias.
191pub mod error;
192
193/// Token alias storage for saving token lookups.
194///
195/// Allows users to reference tokens by friendly names instead
196/// of full contract addresses.
197pub mod tokens;
198
199/// Compliance and risk analysis module.
200///
201/// Provides risk scoring, transaction taint analysis, pattern detection,
202/// and compliance reporting for blockchain addresses.
203pub mod compliance;
204
205/// Library version string.
206pub const VERSION: &str = env!("CARGO_PKG_VERSION");
207
208/// Returns the library version.
209///
210/// # Examples
211///
212/// ```rust
213/// let version = scope::version();
214/// println!("Scope version: {}", version);
215/// ```
216pub fn version() -> &'static str {
217 VERSION
218}
219
220// ============================================================================
221// Integration Tests for Library API
222// ============================================================================
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 #[test]
229 fn test_version_not_empty() {
230 assert!(!version().is_empty());
231 }
232
233 #[test]
234 fn test_version_format() {
235 // Version should be semver-like (X.Y.Z)
236 let v = version();
237 let parts: Vec<&str> = v.split('.').collect();
238 assert!(parts.len() >= 2, "Version should have at least major.minor");
239 }
240
241 #[test]
242 fn test_config_reexport() {
243 // Verify Config is accessible from crate root
244 let config = Config::default();
245 assert!(config.chains.api_keys.is_empty());
246 }
247
248 #[test]
249 fn test_error_reexport() {
250 // Verify error types are accessible from crate root
251 let err = ScopeError::InvalidAddress("test".to_string());
252 assert!(err.to_string().contains("test"));
253 }
254
255 #[test]
256 fn test_result_type_alias() {
257 fn test_fn() -> Result<i32> {
258 Ok(42)
259 }
260 assert_eq!(test_fn().unwrap(), 42);
261 }
262
263 #[test]
264 fn test_config_error_reexport() {
265 use std::path::PathBuf;
266 let err = ConfigError::NotFound {
267 path: PathBuf::from("/test"),
268 };
269 assert!(err.to_string().contains("/test"));
270 }
271}