npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dignetwork/chia-query-wasm

v0.5.2

Published

coinset.org REST access for the browser and Node (the DIG Network chia-query wasm build)

Readme

chia-query

Rust crate for querying the Chia blockchain. Maintains a pool of decentralized peer connections as the primary data source and falls back to the coinset.org HTTP API when peers fail.

All hash parameters and return values use 0x-prefixed hex strings. All methods are async and return Result<T, ChiaQueryError>.

Installation

[dependencies]
chia-query = "0.1"
tokio = { version = "1", features = ["full"] }

Initialization

use chia_query::{ChiaQuery, ChiaQueryConfig, NetworkType};
use std::time::Duration;

// Default: mainnet, 5 peers, coinset.org fallback enabled
let client = ChiaQuery::new(ChiaQueryConfig::default()).await?;

// Custom configuration
let client = ChiaQuery::new(ChiaQueryConfig {
    network: NetworkType::Testnet11,
    max_peers: 3,
    coinset_base_url: "https://api.coinset.org".into(),
    coinset_fallback_enabled: true,
    cert_path: "/path/to/wallet_node.crt".into(),
    key_path: "/path/to/wallet_node.key".into(),
    peer_connect_timeout: Duration::from_secs(8),
    peer_request_timeout: Duration::from_secs(30),
    coinset_request_timeout: Duration::from_secs(30),
}).await?;

TLS certificates auto-generate if the files don't exist. Set TRUSTED_FULLNODE env var to an IP address to prioritize a specific peer. Localhost (127.0.0.1) is always tried before DNS discovery.

Types

Coin

pub struct Coin {
    pub parent_coin_info: String, // 0x-prefixed hex, 32 bytes
    pub puzzle_hash: String,      // 0x-prefixed hex, 32 bytes
    pub amount: u64,              // mojos
}

CoinRecord

pub struct CoinRecord {
    pub coin: Coin,
    pub confirmed_block_index: u32,
    pub spent_block_index: u32,    // 0 if unspent
    pub spent: bool,
    pub coinbase: bool,
    pub timestamp: u64,            // unix seconds
}

CoinSpend

pub struct CoinSpend {
    pub coin: Coin,
    pub puzzle_reveal: String, // 0x-prefixed hex, serialized CLVM
    pub solution: String,      // 0x-prefixed hex, serialized CLVM
}

SpendBundle

pub struct SpendBundle {
    pub coin_spends: Vec<CoinSpend>,
    pub aggregated_signature: String, // 0x-prefixed hex, 96 bytes BLS sig
}

BlockRecord

pub struct BlockRecord {
    pub header_hash: String,
    pub height: u32,
    pub weight: u64,
    pub prev_hash: String,
    pub total_iters: u64,
    pub signage_point_index: u8,
    pub farmer_puzzle_hash: String,
    pub pool_puzzle_hash: String,
    pub timestamp: Option<u64>,
    pub fees: Option<u64>,
    pub extra: serde_json::Value, // additional fields from API
}

Other types

  • FullBlock -- serde_json::Value (deeply nested block structure)
  • FeeEstimate -- estimates, target_times, current_fee_rate, mempool_size, etc.
  • NetworkInfo -- network_name, network_prefix, genesis_challenge
  • BlockchainState -- peak, sync state, difficulty, mempool stats
  • TxStatus -- status string, success bool
  • AdditionsAndRemovals -- additions: Vec<CoinRecord>, removals: Vec<CoinRecord>
  • Condition -- opcode: serde_json::Value (hex string), vars: Vec<String>
  • CoinSpendWithConditions -- coin_spend + parsed conditions
  • MempoolItem -- serde_json::Value

API Reference

Coin queries

get_coin_record_by_name

Look up a single coin by its ID.

let record = client.get_coin_record_by_name("0xabcd...").await?;
// record.coin.amount, record.spent, record.confirmed_block_index

get_coin_records_by_puzzle_hash

Find all coins matching a puzzle hash.

let records = client.get_coin_records_by_puzzle_hash(
    "0xabcd...",       // puzzle_hash
    Some(1000000),     // start_height (optional)
    Some(2000000),     // end_height (optional)
    false,             // include_spent_coins
).await?;

get_coin_records_by_puzzle_hashes

Same as above but batched for multiple puzzle hashes.

let hashes = vec!["0xaaa...".into(), "0xbbb...".into()];
let records = client.get_coin_records_by_puzzle_hashes(
    &hashes, None, None, true,
).await?;

get_coin_records_by_names

Look up multiple coins by their IDs.

let names = vec!["0xaaa...".into(), "0xbbb...".into()];
let records = client.get_coin_records_by_names(
    &names, None, None, true,
).await?;

get_coin_records_by_parent_ids

Find child coins of given parent coin IDs.

let parents = vec!["0xaaa...".into()];
let records = client.get_coin_records_by_parent_ids(
    &parents, None, None, true,
).await?;

get_coin_records_by_hint / get_coin_records_by_hints

Find coins by hint (used in CAT and NFT protocols).

let records = client.get_coin_records_by_hint(
    "0xabcd...", None, None, false,
).await?;

get_memos_by_coin_name

Get memos associated with a coin. Returns serde_json::Value.

let memos = client.get_memos_by_coin_name("0xabcd...").await?;

Puzzle and solution

get_puzzle_and_solution

Get the puzzle reveal and solution for a spent coin. Height is optional -- if omitted, the spent height is auto-resolved from the peer.

let spend = client.get_puzzle_and_solution(
    "0xabcd...", // coin_id
    Some(500000), // height (optional)
).await?;
// spend.puzzle_reveal, spend.solution

get_puzzle_and_solution_with_conditions

Same as above but also runs the puzzle against the solution to extract parsed CLVM conditions.

let result = client.get_puzzle_and_solution_with_conditions(
    "0xabcd...", Some(500000),
).await?;
for cond in &result.conditions {
    // cond.opcode = "0x33" (CREATE_COIN), cond.vars = ["0x..puzzle_hash", "0x..amount"]
}

Transaction broadcast

push_tx

Broadcast a spend bundle to the network.

let status = client.push_tx(&SpendBundle {
    coin_spends: vec![CoinSpend {
        coin: Coin {
            parent_coin_info: "0x...".into(),
            puzzle_hash: "0x...".into(),
            amount: 1000000000000,
        },
        puzzle_reveal: "0xff...".into(),
        solution: "0xff...".into(),
    }],
    aggregated_signature: "0xc0...".into(),
}).await?;
// status.status = "SUCCESS" | "PENDING" | "FAILED"
// status.success = true/false

Block queries

get_block / get_block_by_height

Get a full block. Returns serde_json::Value.

let block = client.get_block("0x...header_hash").await?;
let block = client.get_block_by_height(1000000).await?;
// block["reward_chain_block"]["height"].as_u64()

get_block_record / get_block_record_by_height

Get a block record (lighter than full block).

let record = client.get_block_record_by_height(1000000).await?;
// record.height, record.weight, record.timestamp, record.farmer_puzzle_hash

get_block_records

Get a range of block records. Range is [start, end).

let records = client.get_block_records(1000000, 1000010).await?;

get_blocks

Get a range of full blocks. Range is [start, end).

let blocks = client.get_blocks(
    1000000,  // start
    1000005,  // end
    false,    // exclude_header_hash
    false,    // exclude_reorged
).await?;

get_additions_and_removals

Get all coins created (additions) and spent (removals) in a block.

let ar = client.get_additions_and_removals("0x...header_hash").await?;
// ar.additions: Vec<CoinRecord> -- coins created
// ar.removals: Vec<CoinRecord> -- coins spent

get_block_spends

Get all coin spends in a block with puzzle_reveal and solution.

let spends = client.get_block_spends("0x...header_hash").await?;
for spend in &spends {
    // spend.coin, spend.puzzle_reveal, spend.solution
}

get_block_spends_with_conditions

Same as above but also extracts parsed CLVM conditions per spend.

let spends = client.get_block_spends_with_conditions("0x...header_hash").await?;
for s in &spends {
    // s.coin_spend.puzzle_reveal, s.conditions
}

get_block_count_metrics

let metrics = client.get_block_count_metrics().await?;
// metrics.compact_blocks, metrics.uncompact_blocks, metrics.hint_count

get_unfinished_block_headers

let headers = client.get_unfinished_block_headers().await?;

Fee estimation

get_fee_estimate

Estimate fees for target confirmation times (in seconds).

let estimate = client.get_fee_estimate(
    None,                       // spend_bundle (optional)
    Some(&[60, 120, 300]),      // target_times in seconds
    None,                       // spend_count (optional)
).await?;
// estimate.estimates = [0.0, 0.0, 0.0] -- fee rate per target time
// estimate.current_fee_rate, estimate.mempool_size

Network and state

get_network_info

let info = client.get_network_info().await?;
// info.network_name = "mainnet"
// info.network_prefix = "xch"
// info.genesis_challenge = "0xccd5bb71..."

get_aggsig_additional_data

let data = client.get_aggsig_additional_data().await?;
// "0xccd5bb71..." (same as genesis_challenge on mainnet)

get_blockchain_state

let state = client.get_blockchain_state().await?;
// state.peak.unwrap().height
// state.sync.unwrap().synced
// state.difficulty, state.mempool_size

get_network_space

let space = client.get_network_space(
    "0x...newer_header_hash",
    "0x...older_header_hash",
).await?;

Mempool

get_all_mempool_items

let items = client.get_all_mempool_items().await?;
// HashMap<String, serde_json::Value> keyed by transaction ID

get_all_mempool_tx_ids

let tx_ids = client.get_all_mempool_tx_ids().await?;

get_mempool_item_by_tx_id

let item = client.get_mempool_item_by_tx_id("0x...").await?;

get_mempool_items_by_coin_name

let items = client.get_mempool_items_by_coin_name("0x...", Some(true)).await?;

Convenience

wait_for_confirmation

Poll until a coin is confirmed on-chain.

use std::time::Duration;

let record = client.wait_for_confirmation(
    "0xabcd...",                   // coin_id
    Duration::from_secs(5),        // poll interval
    Duration::from_secs(300),      // timeout
).await?;
// Returns CoinRecord once confirmed_block_index > 0
// Errors with timeout if not confirmed within the deadline

Routing behavior

Every request tries decentralized peers first (two attempts on different peers), then falls back to coinset.org. Peer connections are maintained in a pool of up to max_peers (default 5). Failed peers are ejected and replaced in the background.

| Source | Endpoints | |---|---| | Peer first, coinset fallback | All coin queries, puzzle_and_solution, fee_estimate, push_tx, block_record_by_height, block_records, additions_and_removals, block_spends, blocks | | Constants (no network call) | get_network_info, get_aggsig_additional_data | | Coinset only | get_block_count_metrics, get_block_record (by hash), get_unfinished_block_headers, get_memos_by_coin_name, get_network_space, all mempool endpoints |

Error handling

use chia_query::ChiaQueryError;

match client.get_coin_record_by_name("0x...").await {
    Ok(record) => { /* use record */ }
    Err(ChiaQueryError::PeerRejection(msg)) => { /* peer rejected */ }
    Err(ChiaQueryError::PeerConnection(msg)) => { /* connection/timeout */ }
    Err(ChiaQueryError::CoinsetApiError(msg)) => { /* coinset returned error */ }
    Err(ChiaQueryError::CoinsetHttp(e)) => { /* HTTP transport error */ }
    Err(ChiaQueryError::AllSourcesFailed { .. }) => { /* both peer and coinset failed */ }
    Err(ChiaQueryError::InvalidRequest(msg)) => { /* bad input */ }
    Err(ChiaQueryError::TlsError(msg)) => { /* certificate issue */ }
    Err(ChiaQueryError::PeerDiscoveryFailed) => { /* no peers found */ }
    Err(ChiaQueryError::UnsupportedWithoutCoinset(ep)) => { /* coinset disabled, endpoint needs it */ }
}

License

MIT