diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index e5c6ce7ac6..efd566806d 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -3,7 +3,7 @@ use super::*; use { self::{ deserialize_ordinal_from_str::DeserializeOrdinalFromStr, - templates::{ordinal::OrdinalHtml, root::RootHtml, Content}, + templates::{block::BlockHtml, ordinal::OrdinalHtml, root::RootHtml, Content}, tls_acceptor::TlsAcceptor, }, clap::ArgGroup, @@ -250,22 +250,7 @@ impl Server { index: extract::Extension<Arc<Index>>, ) -> impl IntoResponse { match index.block_with_hash(hash) { - Ok(Some(block)) => ( - StatusCode::OK, - Html(format!( - "<ul>\n{}</ul>", - block - .txdata - .iter() - .enumerate() - .map(|(i, tx)| format!( - " <li>{i} - <a href='/tx/{}'>{}</a></li>\n", - tx.txid(), - tx.txid() - )) - .collect::<String>() - )), - ), + Ok(Some(block)) => BlockHtml::new(block).page().into_response(), Ok(None) => ( StatusCode::NOT_FOUND, Html( @@ -274,7 +259,8 @@ impl Server { .unwrap_or_default() .to_string(), ), - ), + ) + .into_response(), Err(error) => { eprintln!("Error serving request for block with hash {hash}: {error}"); ( @@ -286,6 +272,7 @@ impl Server { .to_string(), ), ) + .into_response() } } } diff --git a/src/subcommand/server/templates.rs b/src/subcommand/server/templates.rs index 1be0d72d26..553b9b54df 100644 --- a/src/subcommand/server/templates.rs +++ b/src/subcommand/server/templates.rs @@ -1,5 +1,6 @@ use {super::*, boilerplate::Display}; +pub(crate) mod block; pub(crate) mod ordinal; pub(crate) mod root; diff --git a/src/subcommand/server/templates/block.rs b/src/subcommand/server/templates/block.rs new file mode 100644 index 0000000000..1545775ad9 --- /dev/null +++ b/src/subcommand/server/templates/block.rs @@ -0,0 +1,51 @@ +use super::*; + +#[derive(Display)] +pub(crate) struct BlockHtml { + hash: BlockHash, + txids: Vec<Txid>, +} + +impl BlockHtml { + pub(crate) fn new(block: Block) -> Self { + Self { + hash: block.header.block_hash(), + txids: block.txdata.iter().map(Transaction::txid).collect(), + } + } +} + +impl Content for BlockHtml { + fn title(&self) -> String { + format!("Block {}", self.hash) + } + + fn page(self) -> PageHtml { + PageHtml { + content: Box::new(self), + } + } +} + +#[cfg(test)] +mod tests { + use {super::*, pretty_assertions::assert_eq, unindent::Unindent}; + + #[test] + fn block_html() { + assert_eq!( + BlockHtml::new(bitcoin::blockdata::constants::genesis_block( + Network::Bitcoin + )) + .to_string(), + " + <h1>Block 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f</h1> + <h2>Transactions</h2> + <ul> + <li><a href=/tx/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b>4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b</a></li> + </ul> + " + .unindent() + ); + } +} diff --git a/templates/block.html b/templates/block.html new file mode 100644 index 0000000000..55116e7788 --- /dev/null +++ b/templates/block.html @@ -0,0 +1,7 @@ +<h1>Block {{ self.hash }}</h1> +<h2>Transactions</h2> +<ul> +%% for txid in &self.txids { + <li><a href=/tx/{{txid}}>{{txid}}</a></li> +%% } +</ul> diff --git a/tests/server.rs b/tests/server.rs index c83d911ce6..1abaae0d9e 100644 --- a/tests/server.rs +++ b/tests/server.rs @@ -150,7 +150,7 @@ fn root() { } #[test] -fn transactions() { +fn block() { let mut state = State::new(); state.blocks(101); @@ -168,9 +168,11 @@ fn transactions() { state.request_regex( &format!("block/{}", blocks[0]), 200, - ".*<ul> - <li>0 - <a href='/tx/[[:xdigit:]]{64}'>[[:xdigit:]]{64}</a></li> - <li>1 - <a href='/tx/[[:xdigit:]]{64}'>[[:xdigit:]]{64}</a></li> + ".*<h1>Block [[:xdigit:]]{64}</h1> +<h2>Transactions</h2> +<ul> + <li><a href=/tx/[[:xdigit:]]{64}>[[:xdigit:]]{64}</a></li> + <li><a href=/tx/[[:xdigit:]]{64}>[[:xdigit:]]{64}</a></li> </ul>.*", ); }