25 releases

0.0.58 Oct 25, 2024
0.0.57 Sep 24, 2024
0.0.40 Aug 29, 2024
0.0.3 Jul 29, 2024

#260 in Network programming

Download history 278/week @ 2024-07-28 82/week @ 2024-08-04 1206/week @ 2024-08-11 399/week @ 2024-08-18 426/week @ 2024-08-25 1326/week @ 2024-09-01 3442/week @ 2024-09-08 3708/week @ 2024-09-15 6503/week @ 2024-09-22 7170/week @ 2024-09-29 7130/week @ 2024-10-06 7110/week @ 2024-10-13 7148/week @ 2024-10-20 6417/week @ 2024-10-27 6742/week @ 2024-11-03 7102/week @ 2024-11-10

28,466 downloads per month

MIT license

260KB
3.5K SLoC

cargo install:

cargo install mempool_space

cargo install --git:

cargo install --git https:github.com/RandyMcMillan/mempool_space.git

mempool-space --option arg1 ... --option argn

mempool-space --option

mempool-space --option arg

mempool-space --option arg --option arg

mempool-space_option arg1 ... argn

mempool-space_option

mempool-space_option arg

mempool-space_option arg arg

mempool-space_option_string arg1 ... argn

mempool-space_option_string

mempool-space_option_string arg

mempool-space_option_string arg arg

GENERAL

mempool-space --difficulty_adjustment

mempool-space_difficulty_adjustment

mempool-space --prices

mempool-space_prices

mempool-space --historical_price --currency [USD, CAD, GBP, CHF, AUD, JPY] --timestamp utc_sec

mempool-space --historical_price --currency EUR --timestamp 1500000000

mempool-space --historical_price --currency USD --timestamp $(date +%s)

ADDRESSES

mempool-space --address 1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv

mempool-space_address 1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv

mempool-space --address_txs 1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv

mempool-space_address_txs 1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv

mempool-space --address_txs_chain 1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv

mempool-space_address_txs_chain 1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv

mempool-space --address_txs_mempool 1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv

mempool-space_address_txs_mempool 1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv

mempool-space --address_utxo 1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv

mempool-space_address_utxo 1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv

mempool-space --validate_address 1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY

mempool-space_validate_address 1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY

BLOCKS

mempool-space --block 000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce

mempool-space_block 000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce

mempool-space --block_header 0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2

mempool-space_block_header 0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2

mempool-space --block_height 615615

mempool-space_block_height 615615

mempool-space --blocks_timestamp 1672531200

mempool-space_blocks_timestamp 1672531200

mempool-space --block_raw 0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2

mempool-space_block_raw 0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2

mempool-space --block_status 0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2

mempool-space_block_status 0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2

mempool-space --blocks_tip_height

mempool-space_blocks_tip_height

mempool-space --blocks_tip_hash

mempool-space_blocks_tip_hash

mempool-space --block_txid 000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce --block_txindex 218

mempool-space_block_txid 000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce 218

mempool-space --block_txids 000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce

mempool-space_block_txids 000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce

mempool-space --block_txs 000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce --start_index 0

mempool-space --block_txs 000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce --start_index 25

mempool-space_block_txs 000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce 0

mempool-space_block_txs 000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce 25

mempool-space --blocks 730000

mempool-space_blocks 730000

mempool-space --blocks_bulk --min_height 730000 --max_height 840000

mempool-space_blocks_bulk 730000 840000

MINING

mempool-space --mining_pools --timeperiod [24h 3d 1w 1m 3m 6m 1y 2y 3y]

mempool-space_mining_pools [24h 3d 1w 1m 3m 6m 1y 2y 3y]

mempool-space --mining_pool --slug unknown

mempool-space_mining_pool unknown

mempool-space --mining_hashrate_pools --timeperiod [1m, 3m, 6m, 1y, 2y, 3y]

mempool-space_mining_hashrate_pools 1m

mempool-space --mining_pool_hashrate --slug foundryusa

mempool-space_mining_pool_hashrate foundryusa

mempool-space --mining_pool_hashrate --slug unknown

mempool-space_mining_pool_hashrate unknown

more

mempool-space --mining_pool_blocks --slug luxor --blockheight 730000

mempool-space_mining_pool_blocks luxor 730000

mempool-space --blocks_audit_score --block_hash 00000000000000000002352696778fc14532ccb923fde167fc754de26e6adbcd

mempool-space_blocks_audit_score 00000000000000000002352696778fc14532ccb923fde167fc754de26e6adbcd

mempool-space --blocks_audit_scores --blockheight 820000

mempool-space_blocks_audit_scores 820000

mempool-space --block_audit_summary --blockhash 00000000000000000000f218ceda7a5d9c289040b9c3f05ef9f7c2f4930e0123

mempool-space_block_audit_summary 00000000000000000000f218ceda7a5d9c289040b9c3f05ef9f7c2f4930e0123

FEES

mempool-space_fees_mempool_blocks

mempool-space --fees_mempool_blocks

mempool-space_fees_recommended

mempool-space --fees_recommended

MEMPOOL

mempool-space_mempool

mempool_space --mempool

mempool-space_mempool_full_rbf_transactions

mempool-space --mempool_full_rbf_transactions

mempool-space_mempool_rbf_transactions

mempool-space --mempool_rbf_transactions

mempool-space_mempool_recent

mempool-space --mempool_recent

mempool-space_mempool_txids

mempool-space --mempool_txids

TRANSACTIONS

LIGHTNING

ACCELERATOR PUBLIC

ACCELERATOR AUTHENTICATED

#![warn(missing_docs, clippy::unwrap_used)]

#[warn(missing_docs, clippy::unwrap_used)]

pub mod api

pub mod api;

pub mod error

pub mod error;

pub mod resolve_policy

pub mod resolve_policy;

pub mod target

pub mod target;

pub use error::{CheckTargetError, ParseTargetError, ResolveTargetError};

pub use resolve_policy::ResolvePolicy;

pub use target::{Fqhn, IcmpTarget, Port, Status, Target, TcpTarget};

Command-line argument parser.

pub mod args;

#[cfg(feature = "async")]

pub mod async_target;

pub mod async_target;

#[cfg(feature = "async")]

pub use async_target::{AsyncTarget, AsyncTargetExecutor, BoxedHandler, BoxedTarget, OldStatus};

pub use async_target::{AsyncTarget, AsyncTargetExecutor, BoxedHandler, BoxedTarget, OldStatus};

Configuration file parser.

pub mod config;

Custom error implementation.

pub mod this_error;

Upload handler.

pub mod upload;

use crate::args::Args;

use crate::config::Config;

use crate::this_error::{Error, Result};

use crate::upload::Uploader;

use crossterm::style::Stylize;

use std::fs;

use std::io::IsTerminal;

use std::io::Read;

use std::io::{self};

const CONFIG_FILE: &str = "config.toml";

const CONFIG_FILE: &str = "config.toml";

pub fn run(args: Args) -> Result<()>

pub fn run(args: Args) -> Result<()> {

let mut config = Config::default();


if let Some(ref config_path) = args.config {
    
    config = toml::from_str(&fs::read_to_string(config_path)?)?

} else {
    
    for path in [
        dirs_next::home_dir().map(|p| p.join(".mempool").join(CONFIG_FILE)),
        dirs_next::home_dir().map(|p| p.join(".config").join(CONFIG_FILE)),
        dirs_next::config_dir().map(|p| p.join(".config").join(CONFIG_FILE)),
    ]
    .iter()
    .filter_map(|v| v.as_ref())
    {
        if path.exists() {
            config = toml::from_str(&fs::read_to_string(path)?)?;
            break;
        }
    }
}
config.update_from_args(&args);

if config.server.address.is_empty() {
    return Err(Error::NoServerAddressError);
}

let uploader = Uploader::new(&config);

if args.print_server_version {
    println!("TODO: {}", uploader.retrieve_version()?.trim());

    return Ok(());
}

if args.list_files {
    let prettify = args.prettify || config.style.as_ref().map(|style| style.prettify).unwrap_or(false);

    uploader.retrieve_list(&mut io::stdout(), prettify)?;

    return Ok(());
}

let mut results = Vec::new();

if let Some(ref url) = args.url {
    TODO TOR_URL etc...
    results.push(uploader.upload_url(url));
} else if let Some(ref remote_url) = args.remote {
    results.push(uploader.upload_remote_url(remote_url));
} else if !std::io::stdin().is_terminal() || args.files.contains(&String::from("-")) {
    let mut buffer = Vec::new();

    let mut stdin = io::stdin();

    stdin.read_to_end(&mut buffer)?;

    results.push(uploader.upload_stream(&*buffer));
} else {
    for file in args.files.iter() {
        if !args.delete {
            results.push(uploader.upload_file(file))
        } else {
            results.push(uploader.delete_file(file))
        }
    }
}
let prettify = args.prettify || config.style.as_ref().map(|style| style.prettify).unwrap_or(false);

let format_padding = prettify
    .then(|| results.iter().map(|v| v.0.len()).max())
    .flatten()
    .unwrap_or(1);

for (data, result) in results.iter().map(|v| (v.0, v.1.as_ref())) {
    let data = if prettify {
        format!(
            "{:p$} {} ",
            data,
            if result.is_ok() {
                "=>".green().bold()
            } else {
                "=>".red().bold()
            },
            p = format_padding,
        )
    } else {
        String::new()
    };
    match result {
        Ok(url) => println!("{}{}", data, url.trim()),
        Err(e) => eprintln!("{data}{e}"),
    }
}

Ok(())

}

pub fn reachable()

pub fn reachable() -> bool { use api::{blocking, URL}; use std::time::Instant; let start = Instant::now(); let blocks_tip_height = String::from("blocks/tip/height"); let res = blocking(&blocks_tip_height); let mut reachable = false; if !res.unwrap().to_string().is_empty() { println!( "\n\n{:?}:\nGET {}/{:} {:?}\n\n", start, URL[0], res.unwrap(), start.elapsed() ); reachable = true; } let start = Instant::now(); let blocks_tip_height = String::from("blocks_tip_height"); let res = api::api(&blocks_tip_height, "", false); if !res.is_empty() && reachable { println!("\n\n{:?}:\nAPI {}/{:} {:?}\n\n", start, URL[0], res, start.elapsed()); reachable = true; } else { reachable = false; }

reachable

}

pub fn wait(sleep: &str)

pub fn wait(sleep: &str) { use std::process::Command; let sleep_cmd = Command::new("sleep").arg(sleep).output().expect("wait:sleep failed"); let _result = String::from_utf8(sleep_cmd.stdout) .map_err(|non_utf8| String::from_utf8_lossy(non_utf8.as_bytes()).into_owned()) .unwrap(); println!(); }

cargo test -- --nocapture

#[cfg(test)] mod tests {

###  TESTS
use super::*;
use crate::api::{api, blocking};

###  REACHABLE

#[test]
fn test_reachable() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    wait("1");
}
#[test]
#[should_panic]
fn test_reachable_panic() {
    let reachable = reachable();
    assert_eq!(reachable, false);
    wait("1");
}

###  GENERAL

#[test]
fn test_difficulty_adjustment() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/v1/difficulty-adjustment
    let binding = format!("v1/difficulty-adjustment").clone();
    let get_difficulty_adjustment: &str = blocking(&binding).expect("REASON");
    let get_difficulty_adjustment = api("difficulty_adjustment", "extraneous_arg", true);
    wait("1");
}
#[test]
fn test_price() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/v1/prices
    let binding = format!("v1/prices").clone();
    let get_prices: &str = blocking(&binding).expect("REASON");
    let get_prices = api("prices", "extraneous_arg", true);
    wait("1");
}
#[test]
fn test_historical_price() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    use crate::args::historical_price;
     GET /api/v1/historical-price?currency=EUR&timestamp=1500000000
    let get_historical_price = historical_price(&"EUR", &"1500000000");
    let get_historical_prices = api("historical_price", "USD", true);
    wait("1");
}

###  ADDRESSES TESTS

#[test]
fn test_address() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/address/:address
    let binding = format!("address/1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv").clone();
    let get_address: &str = blocking(&binding).expect("test_address failed");
    let get_address = api("address", "1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv", true);
    wait("1");
}
#[test]
fn test_address_txs() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/address/:address/txs
    let binding = format!("address/1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv/txs").clone();
    let get_address_txs: &str = blocking(&binding).expect("test_address_txs failed");
    let get_address_txs = api("address_txs", "1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv", true);
    wait("1");
}
#[test]
fn test_address_txs_chain() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/address/:address/txs/chain
    let binding = format!("address/1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv/txs/chain").clone();
    let get_address_txs_chain: &str = blocking(&binding).expect("REASON");
    let get_address_txs_chain = api("address_txs_chain", "1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv", true);
    wait("1");
}
#[test]
fn test_address_txs_mempool() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/address/:address/txs/mempool
    let binding = format!("address/1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv/txs/mempool").clone();
    let get_address_txs_mempool: &str = blocking(&binding).expect("REASON");
    let get_address_txs_mempool = api("address_txs_mempool", "1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv", true);
    wait("1");
}
#[test]
fn test_address_utxo() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/address/:address/utxo
    let binding = format!("address/1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY/utxo").clone();
    let get_address_utxo: &str = blocking(&binding).expect("existing valid address needed");
    let get_address_utxo = api("address_utxo", "1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv", true);
    wait("1");
}
#[test]
fn test_validate_address() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/v1/validate-address/:address
    let binding = format!("v1/validate-address/1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY").clone();
    let get_valid_address: &str = blocking(&binding).expect("valid address needed");
    wait("1");
}

###  BLOCKS TESTS

#[test]
fn test_block() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/block/:hash
    let binding = format!("block/000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce").clone();
    let get_block: &str = blocking(&binding).expect("an existing block hash is needed");
    let get_block = api(
        "block",
        "000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce",
        true,
    );
    wait("1");
}
#[test]
fn test_block_header() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/block/:hash/header
    let binding = format!("block/000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce").clone();
    let get_block_header: &str = blocking(&binding).expect("an existing block hash is needed");
    let get_block_header = api(
        "block_header",
        "000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce",
        true,
    );
    wait("1");
}
#[test]
fn test_block_height() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/block-height:height
    let binding = format!("block-height/615615").clone();
    let get_block_height: &str = blocking(&binding).expect("an existing block hash is needed");
    let get_block_height = api("block_height", "615615", true);
    wait("1");
}
#[test]
fn test_blocks_timestamp() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/v1/mining/blocks/timestamp/:timestamp
    let binding = format!("v1/mining/blocks/timestamp/1672531200").clone();
    let get_timestamp: &str = blocking(&binding).expect("an existing block hash is needed");
    let get_timestamp = api("blocks_timestamp", "1672531200", true);
    wait("1");
}
#[test]
fn test_block_raw() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/block/:hash/raw
    let binding = format!("block/0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2").clone();
    let get_block_raw: &str = blocking(&binding).expect("an existing block hash is needed");
    let get_block_raw = api(
        "block_raw",
        "0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2",
        true,
    );
    wait("1");
}
#[test]
fn test_block_status() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/block/:hash/status
    let binding = format!("block/0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2").clone();
    let get_block_status: &str = blocking(&binding).expect("an existing block hash is needed");
    let get_block_status = api(
        "block_status",
        "0000000000000000000065bda8f8a88f2e1e00d9a6887a43d640e52a4c7660f2",
        true,
    );
    wait("1");
}
#[test]
fn test_blocks_tip_height() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/blocks/tip/height
    let binding = format!("blocks/tip/height").clone();
    let get_blocks_tip_height: &str = blocking(&binding).expect("returns current block_height");
    let get_blocks_tip_height = api("blocks_tip_height", "extraneous_arg", true);
    wait("1");
}
#[test]
fn test_blocks_tip_hash() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/blocks/tip/hash
    let binding = format!("blocks/tip/hash").clone();
    let get_blocks_tip_hash: &str = blocking(&binding).expect("returns current block/tip/hash");
    let get_block_tip_hash = api("blocks_tip_hash", "extraneous_arg", true);
    wait("1");
}
#[test]
fn test_block_txid() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/block/:hash/txid/:index
    let binding =
        format!("block/000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce/txid/218").clone();
    let get_block_txid: &str = blocking(&binding).expect("returns current txid from block index");
    let get_block_txid = api(
        "block_txid",
        "000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce/txid/218",
        true,
    );
    use crate::args::block_txid;
    block_txid(
        &"000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce",
        &"218",
    );
    wait("1");
}
#[test]
fn test_block_txids() {
    let reachable = reachable();
    assert_eq!(reachable, true);
     GET /api/block/:hash/txids
    let binding = format!("block/000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce/txids").clone();
    let get_block_txids: &str = blocking(&binding).expect("returns current txids from block");
    let get_block_txids = api(
        "block_txid",
        "000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce/txids",
        true,
    );
    use crate::args::block_txids;
    block_txids(&"000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce");
    wait("1");
}
#[test]
fn test_block_txs() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    let binding = format!("block/000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce/txs").clone();
    let get_block_txs: &str = blocking(&binding).expect("returns current txids from block");
    let get_block_txs = api(
        "block_txs",
        "000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce/txs",
        true,
    );
    let get_block_txs = api(
        "block_txs",
        "000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce/txs/0",
        true,
    );
    let get_block_txs = api(
        "block_txs",
        "000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce/txs/1", test if start_index_int % 25 == 0
        true,
    );
    let get_block_txs = api(
        "block_txs",
        "000000000000000015dc777b3ff2611091336355d3f0ee9766a2cf3be8e4b1ce/txs/25",
        true,
    );
}
#[test]
fn test_blocks() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    let binding = format!("v1/blocks/730000").clone();
    let get_block_txid: &str = blocking(&binding).expect("returns current txid from block index");
    let get_block_txid = api("blocks", "730000", true);
    let get_blocks_tip_height = api("blocks_tip_height", "extraneous_arg", true);
    use crate::args::blocks;
    blocks(&"", true);
    wait("1");
    blocks(&"0", true);
    wait("1");
    blocks(&"25", true);
    wait("1");
    blocks(&"730000", true);
    wait("1");
    blocks(&get_blocks_tip_height, true);
    wait("1");
}
#[test]
#[should_panic]
fn test_blocks_bulk() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    let binding = format!("v1/blocks-bulk/730000/840000").clone();
    let get_block_bulk: &str = blocking(&binding).expect("returns current txid from block index");
    let get_block_bulk = api("blocks_bulk", "730000/840000", true);
    let get_blocks_tip_height = api("blocks_tip_height", "extraneous_arg", true);
    use crate::args::blocks_bulk;
    blocks_bulk(&"0", &"0", true);
    wait("1");
    blocks_bulk(&"0", &"1", true);
    wait("1");
    blocks_bulk(&"730000", &"840000", true);
    wait("1");
    blocks_bulk(&"730000", &get_blocks_tip_height, true);
    wait("1");
}

###  MINING TESTS

#[test]
fn test_mining_pools() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  [24h 3d 1w 1m 3m 6m 1y 2y 3y]
    let binding = format!("v1/mining/pools/24h").clone();
    let get_mining_pools: &str = blocking(&binding).expect("returns current v1/mining/pools/1d");
    let get_mining_pools = api("mining_pools", "24h", true);
    wait("1");
    let binding = format!("v1/mining/pools/1d").clone();
    let get_mining_pools: &str = blocking(&binding).expect("returns current v1/mining/pools/1d");
    let get_mining_pools = api("mining_pools", "1d", true);
    wait("1");
    let binding = format!("v1/mining/pools/3d").clone();
    let get_mining_pools: &str = blocking(&binding).expect("returns current v1/mining/pools/3d");
    let get_mining_pools = api("mining_pools", "3d", true);
    wait("1");
    let binding = format!("v1/mining/pools/1w").clone();
    let get_mining_pools: &str = blocking(&binding).expect("returns current v1/mining/pools/1w");
    let get_mining_pools = api("mining_pools", "1w", true);
    wait("1");
    let binding = format!("v1/mining/pools/1m").clone();
    let get_mining_pools: &str = blocking(&binding).expect("returns current v1/mining/pools/1m");
    let get_mining_pools = api("mining_pools", "1m", true);
    wait("1");
    let binding = format!("v1/mining/pools/3m").clone();
    let get_mining_pools: &str = blocking(&binding).expect("returns current v1/mining/pools/3m");
    let get_mining_pools = api("mining_pools", "3m", true);
    wait("1");
    let binding = format!("v1/mining/pools/6m").clone();
    let get_mining_pools: &str = blocking(&binding).expect("returns current v1/mining/pools/6m");
    let get_mining_pools = api("mining_pools", "6m", true);
    wait("1");
    let binding = format!("v1/mining/pools/1y").clone();
    let get_mining_pools: &str = blocking(&binding).expect("returns current v1/mining/pools/1y");
    let get_mining_pools = api("mining_pools", "1y", true);
    wait("1");
    let binding = format!("v1/mining/pools/2y").clone();
    let get_mining_pools: &str = blocking(&binding).expect("returns current v1/mining/pools/2y");
    let get_mining_pools = api("mining_pools", "2y", true);
    wait("1");
    let binding = format!("v1/mining/pools/3y").clone();
    let get_mining_pools: &str = blocking(&binding).expect("returns current v1/mining/pools/3y");
    let get_mining_pools = api("mining_pools", "3y", true);
    wait("1");
}
#[test]
fn test_mining_pool() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  antpool
    let binding = format!("v1/mining/pool/antpool").clone();
    let get_mining_pool: &str = blocking(&binding).expect("returns current v1/mining/pool/:slug");
    let get_mining_pool = api("mining_pool", "antpool", true);
    wait("1");

    ###  ...

    ###  unknown
    let binding = format!("v1/mining/pool/unknown").clone();
    let get_mining_pool: &str = blocking(&binding).expect("returns current v1/mining/pool/:slug");
    let get_mining_pool = api("mining_pool", "unknown", true);
    wait("1");
}
#[test]
fn test_mining_hashrate_pools() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  timeperiod unspecified
    let binding = format!("v1/mining/hashrate/pools").clone();
    let mining_hashrate_pools: &str =
        blocking(&binding).expect("returns current v1/mining/hashrate/pools/[:timePeriod]");
    let get_mining_hashrate_pools = api("mining_hashrate_pools", "1m", true);
    wait("1");
      [1m, 3m, 6m, 1y, 2y, 3y]
    let binding = format!("v1/mining/hashrate/pools/1m").clone();
    let get_mining_hashrate_pools: &str =
        blocking(&binding).expect("returns current v1/mining/hashrate/pools/[:timePeriod]");
    let get_mining_hashrate_pools = api("mining_hashrate_pools", "1m", true);
    wait("1");
    let binding = format!("v1/mining/hashrate/pools/3m").clone();
    let get_mining_hashrate_pools: &str =
        blocking(&binding).expect("returns current v1/mining/hashrate/pools/[:timePeriod]");
    let get_mining_hashrate_pools = api("mining_hashrate_pools", "3m", true);
    wait("1");
    let binding = format!("v1/mining/hashrate/pools/6m").clone();
    let get_mining_hashrate_pools: &str =
        blocking(&binding).expect("returns current v1/mining/hashrate/pools/[:timePeriod]");
    let get_mining_hashrate_pools = api("mining_hashrate_pools", "6m", true);
    wait("1");
    let binding = format!("v1/mining/hashrate/pools/1y").clone();
    let get_mining_hashrate_pools: &str =
        blocking(&binding).expect("returns current v1/mining/hashrate/pools/[:timePeriod]");
    let get_mining_hashrate_pools = api("mining_hashrate_pools", "1y", true);
    wait("1");
    let binding = format!("v1/mining/hashrate/pools/2y").clone();
    let get_mining_hashrate_pools: &str =
        blocking(&binding).expect("returns current v1/mining/hashrate/pools/[:timePeriod]");
    let get_mining_hashrate_pools = api("mining_hashrate_pools", "2y", true);
    wait("1");
    let binding = format!("v1/mining/hashrate/pools/3y").clone();
    let get_mining_hashrate_pools: &str =
        blocking(&binding).expect("returns current v1/mining/hashrate/pools/[:timePeriod]");
    let get_mining_hashrate_pools = api("mining_hashrate_pools", "3y", true);
    wait("1");
}
#[test]
fn test_mining_pool_hashrate() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  antpool
    let binding = format!("v1/mining/pool/antpool/hashrate").clone();
    let get_mining_pool_hashrate: &str = blocking(&binding).expect("returns current v1/mining/pool/:slug/hashrate");
    let get_mining_pool_hashrate = api("mining_pool_hashrate", "antpool", true);
    wait("1");

    ###  ...

    ###  foundryusa
    let binding = format!("v1/mining/pool/foundryusa/hashrate").clone();
    let get_mining_pool_hashrate: &str = blocking(&binding).expect("returns current v1/mining/pool/:slug/hashrate");
    let get_mining_pool_hashrate = api("mining_pool_hashrate", "foundryusa", true);
    wait("1");
}
#[test]
fn test_mining_pool_blocks() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    use crate::args::mining_pool_blocks;
    ###  luxor
    let binding = format!("v1/mining/pool/luxor/blocks/730000").clone();
    let get_mining_pool_blocks: &str =
        blocking(&binding).expect("returns v1/mining/pool/:slug/blocks/[:blockHeight]");
    let get_mining_pool_blocks = mining_pool_blocks("luxor", "730000");
    wait("1");

    ###  ...

    ###  antpool
    let binding = format!("v1/mining/pool/antpool/blocks/730000").clone();
    let get_mining_pool_blocks: &str =
        blocking(&binding).expect("returns v1/mining/pool/:slug/blocks/[:blockHeight]");
    let get_mining_pool_blocks = mining_pool_blocks("antpool", "730000");
    wait("1");
}
#[test]
fn test_mining_hashrate() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  1m
    let binding = format!("v1/mining/hashrate/1m").clone();
    let get_mining_hashrate: &str = blocking(&binding).expect("returns v1/mining/hashrate/[:timePeriod]");
    let get_mining_hashrate = api("mining_hashrate", "1m", true);
    wait("1");
    ###  3m
    let binding = format!("v1/mining/hashrate/3m").clone();
    let get_mining_hashrate: &str = blocking(&binding).expect("returns v1/mining/hashrate/[:timePeriod]");
    let get_mining_hashrate = api("mining_hashrate", "3m", true);
    wait("1");
    ###  6m
    let binding = format!("v1/mining/hashrate/6m").clone();
    let get_mining_hashrate: &str = blocking(&binding).expect("returns v1/mining/hashrate/[:timePeriod]");
    let get_mining_hashrate = api("mining_hashrate", "6m", true);
    wait("1");
    ###  1y
    let binding = format!("v1/mining/hashrate/1y").clone();
    let get_mining_hashrate: &str = blocking(&binding).expect("returns v1/mining/hashrate/[:timePeriod]");
    let get_mining_hashrate = api("mining_hashrate", "1y", true);
    wait("1");
    ###  2y
    let binding = format!("v1/mining/hashrate/2y").clone();
    let get_mining_hashrate: &str = blocking(&binding).expect("returns v1/mining/hashrate/[:timePeriod]");
    let get_mining_hashrate = api("mining_hashrate", "2y", true);
    wait("1");
    ###  3y
    let binding = format!("v1/mining/hashrate/3y").clone();
    let get_mining_hashrate: &str = blocking(&binding).expect("returns v1/mining/hashrate/[:timePeriod]");
    let get_mining_hashrate = api("mining_hashrate", "3y", true);
    wait("1");
    ###  all
    let binding = format!("v1/mining/hashrate/all").clone();
    let get_mining_hashrate: &str = blocking(&binding).expect("returns v1/mining/hashrate/[:timePeriod]");
    let get_mining_hashrate = api("mining_hashrate", "all", true);
    wait("1");
}
#[test]
fn test_mining_difficulty_adjustments() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  1m
    let binding = format!("v1/mining/difficulty-adjustments/1m").clone();
    let get_mining_difficulty_adjustment: &str =
        blocking(&binding).expect("returns v1/mining/difficulty-adjustments/[:interval]");
    let get_mining_hashrate = api("mining_hashrate", "1m", true);
    wait("1");
    ###  3m
    let binding = format!("v1/mining/difficulty-adjustments/3m").clone();
    let get_mining_difficulty_adjustment: &str =
        blocking(&binding).expect("returns v1/mining/difficulty-adjustments/[:interval]");
    let get_mining_hashrate = api("mining_hashrate", "3m", true);
    wait("1");
    ###  6m
    let binding = format!("v1/mining/difficulty-adjustments/6m").clone();
    let get_mining_difficulty_adjustment: &str =
        blocking(&binding).expect("returns v1/mining/difficulty-adjustments/[:interval]");
    let get_mining_hashrate = api("mining_hashrate", "6m", true);
    wait("1");
    ###  1y
    let binding = format!("v1/mining/difficulty-adjustments/1y").clone();
    let get_mining_difficulty_adjustment: &str =
        blocking(&binding).expect("returns v1/mining/difficulty-adjustments/[:interval]");
    let get_mining_hashrate = api("mining_hashrate", "1y", true);
    wait("1");
    ###  2y
    let binding = format!("v1/mining/difficulty-adjustments/2y").clone();
    let get_mining_difficulty_adjustment: &str =
        blocking(&binding).expect("returns v1/mining/difficulty-adjustments/[:interval]");
    let get_mining_hashrate = api("mining_hashrate", "2y", true);
    wait("1");
    ###  3y
    let binding = format!("v1/mining/difficulty-adjustments/3y").clone();
    let get_mining_difficulty_adjustment: &str =
        blocking(&binding).expect("returns v1/mining/difficulty-adjustments/[:interval]");
    let get_mining_hashrate = api("mining_hashrate", "3y", true);
    wait("1");
    ###  all
    let binding = format!("v1/mining/difficulty-adjustments").clone();
    let get_mining_difficulty_adjustment: &str =
        blocking(&binding).expect("returns v1/mining/difficulty-adjustments/[:interval]");
    let get_mining_hashrate = api("mining_hashrate", "all", true);
    wait("1");
}
#[test]
fn test_mining_reward_stats() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  GET /api/v1/mining/reward-stats/:blockCount
    let blockCount = "100";
    let binding = format!("v1/mining/reward-stats/{blockCount}").clone();
    let mining_reward_stats: &str = blocking(&binding).expect("returns current v1/mining/reward-stats/:blockCount");
    let mining_reward_stats = api("mining_reward_stats", "100", true);
    wait("1");
}

###  ...

#[test]
fn test_mining_blocks_audit_score() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  GET /api/v1/mining/blocks/audit/score/:blockHash
    let blockHash = "000000000000000000032535698c5b0c48283b792cf86c1c6e36ff84464de785";
    let binding = format!("v1/mining/blocks/audit/score/{blockHash}").clone();
    let blocks_audit_score: &str =
        blocking(&binding).expect("returns current v1/mining/blocks/audit/score/:blockHash");
    let block_audit_score = api(
        "blocks_audit_score",
        "000000000000000000032535698c5b0c48283b792cf86c1c6e36ff84464de785",
        true,
    );
    wait("1");
}
#[test]
fn test_mining_blocks_audit_scores() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  GET /api/v1/mining/blocks/audit/scores/:startHeight
    let startHeight = "820000";
    let binding = format!("v1/mining/blocks/audit/scores/{startHeight}").clone();
    let blocks_audit_scores: &str =
        blocking(&binding).expect("returns current v1/mining/blocks/audit/scores/:startHeight");
    let blocks_audit_scores = api("blocks_audit_scores", "820000", true);
    wait("1");
}
#[test]
fn test_mining_block_audit_summary() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  GET /api/v1/block/:blockHash/audit-summary
    let blockHash = "00000000000000000000f218ceda7a5d9c289040b9c3f05ef9f7c2f4930e0123";
    let binding = format!("v1/block/{blockHash}/audit-summary").clone();
    let block_audit_summary: &str = blocking(&binding).expect("returns v1/block/{blockHash}/audit-summary");
    let block_audit_summary = api("block_audit_summary", "820000", true);
    wait("1");
}

###  Fees
#[test]
fn test_fees_mempool_blocks() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  GET /api/v1/fees/mempool-blocks
    let binding = format!("v1/fees/mempool-blocks").clone();
    let fees_mempool_blocks: &str = blocking(&binding).expect("returns v1/fees/mempool-blocks");
    let block_audit_summary = api("fees_mempool_blocks", &"", true);
    wait("1");
}
#[test]
fn test_fees_recommended() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  GET /api/v1/fees/recommended
    let binding = format!("v1/fees/recommended").clone();
    let fees_recommended: &str = blocking(&binding).expect("returns v1/fees/recommended");
    let block_audit_summary = api("fees_recommended", &"", true);
    wait("1");
}

###  Mempool
#[test]
fn test_mempool() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  GET /api/mempool
    let binding = format!("mempool").clone();
    let fees_recommended: &str = blocking(&binding).expect("returns mempool");
    let block_audit_summary = api("mempool", &"", true);
    wait("1");
}

###  Transactions
###  CPFP
###  CHILDREN_PAY_FOR_PARENT
#[test]
fn test_children_pay_for_parent() {
    let reachable = reachable();
    assert_eq!(reachable, true);
    ###  GET /api/v1/cpfp
    let txid = "e09d8afb19968715a4492205b8db5fe41da144b0c1e4f7a756c8bf9742d4f1f4";
    let binding = format!("v1/cpfp/{txid}").clone();
    ###  AS OF BLOCK_HEIGHT
    let children_pay_for_parent: &str = blocking(&binding).expect("returns v1/cpfp/:txid");
    let children_pay_for_parent = api(
        "children_pay_for_parent",
        "e09d8afb19968715a4492205b8db5fe41da144b0c1e4f7a756c8bf9742d4f1f4",
        true,
    );
    wait("1");
}

###  LIGHTNING TESTS
###  lighting_channels_from_node_pubkey
#[test]
fn test_lighting_channels_from_node_pubkey() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_channels_from_txid
#[test]
fn test_lighting_channels_from_txid() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_isp_nodes
#[test]
fn test_lighting_isp_nodes() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_network_status
#[test]
fn test_lighting_network_status() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_node_stats
#[test]
fn test_lighting_stats() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_node_stats_per_country
#[test]
fn test_lighting_stats_per_country() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_nodes_channels
#[test]
fn test_lighting_nodes_channels() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_nodes_in_country
#[test]
fn test_lighting_nodes_in_country() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_nodes_stats_per_isp
#[test]
fn test_lighting_nodes_stats_per_isp() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_top_nodes
#[test]
fn test_lighting_top_nodes() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_top_nodes_by_connectivity
#[test]
fn test_lighting_top_nodes_by_connectivity() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_top_nodes_by_liquidity
#[test]
fn test_lighting_top_nodes_by_liquidity() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}
###  lighting_top_oldests_nodes
#[test]
fn test_lighting_top_oldests_nodes() {
    let reachable = reachable();
    assert_eq!(reachable, true);
}

###  Accelerator (Public)

###  Accelerator (Authenticated)

#[test]
fn test_add() {
     assert_eq!(add(1, 2), 3);
    wait("1");
}

#[test]
fn test_bad_add() {
     This assert would fire and test will fail.
     Please note, that private functions can be tested too!
     assert_ne!(bad_add(1, 2), 3);
    wait("1");
}
use std::panic::{catch_unwind, AssertUnwindSafe};
#[test]
fn should_panic() {
    let msg = catch_unwind(AssertUnwindSafe(|| {
        panic!(" foo panic message");
    }));

    assert_ne!("foo panic message", *msg.unwrap_err().downcast_ref::<&str>().unwrap());
    wait("1");
}

}

Dependencies

~35–51MB
~824K SLoC