Skip to content

Commit

Permalink
Add /input page (ordinals#639)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey committed Oct 11, 2022
1 parent 2580024 commit a7aa13f
Show file tree
Hide file tree
Showing 24 changed files with 256 additions and 103 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ derive_more = "0.99.17"
dirs = "4.0.0"
env_logger = "0.9.0"
futures = "0.3.21"
hex = "0.4.3"
html-escaper = "0.2.0"
http = "0.2.6"
lazy_static = "1.4.0"
Expand Down
6 changes: 3 additions & 3 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ impl Index {

let mut errors = 0;
let block = loop {
match self.block_at_height(height) {
match self.block(height) {
Err(err) => {
if cfg!(test) {
return Err(err);
Expand Down Expand Up @@ -490,7 +490,7 @@ impl Index {
Ok(())
}

fn block_at_height(&self, height: u64) -> Result<Option<Block>> {
pub(crate) fn block(&self, height: u64) -> Result<Option<Block>> {
Ok(
self
.client
Expand Down Expand Up @@ -625,7 +625,7 @@ impl Index {
pub(crate) fn blocktime(&self, height: Height) -> Result<Blocktime> {
let height = height.n();

match self.block_at_height(height)? {
match self.block(height)? {
Some(block) => Ok(Blocktime::Confirmed(block.header.time.into())),
None => {
let tx = self.database.begin_read()?;
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ use {
anyhow::{anyhow, bail, Context, Error},
bitcoin::{
blockdata::constants::COIN_VALUE,
consensus::{Decodable, Encodable},
consensus::{self, Decodable, Encodable},
hash_types::BlockHash,
hashes::{sha256, Hash},
Address, Block, Network, OutPoint, Transaction, TxOut, Txid,
Address, Block, Network, OutPoint, Sequence, Transaction, TxIn, TxOut, Txid,
},
bitcoincore_rpc::RpcApi,
chrono::{DateTime, NaiveDateTime, Utc},
Expand Down
80 changes: 60 additions & 20 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ use super::*;

use {
self::{
deserialize_ordinal_from_str::DeserializeOrdinalFromStr,
deserialize_from_str::DeserializeFromStr,
templates::{
block::BlockHtml, clock::ClockSvg, home::HomeHtml, ordinal::OrdinalHtml, output::OutputHtml,
range::RangeHtml, rare::RareTxt, rune::RuneHtml, transaction::TransactionHtml, Content,
PageHtml,
BlockHtml, ClockSvg, Content, HomeHtml, InputHtml, OrdinalHtml, OutputHtml, PageHtml,
RangeHtml, RareTxt, RuneHtml, TransactionHtml,
},
},
axum::{
Expand All @@ -27,12 +26,11 @@ use {
AcmeConfig,
},
serde::{de, Deserializer},
std::cmp::Ordering,
std::str,
std::{cmp::Ordering, str},
tokio_stream::StreamExt,
};

mod deserialize_ordinal_from_str;
mod deserialize_from_str;
mod templates;

enum ServerError {
Expand Down Expand Up @@ -145,6 +143,7 @@ impl Server {
.route("/faq", get(Self::faq))
.route("/favicon.ico", get(Self::favicon))
.route("/height", get(Self::height))
.route("/input/:block/:transaction/:input", get(Self::input))
.route("/ordinal/:ordinal", get(Self::ordinal))
.route("/output/:output", get(Self::output))
.route("/range/:start/:end", get(Self::range))
Expand Down Expand Up @@ -287,7 +286,7 @@ impl Server {

async fn ordinal(
Extension(index): Extension<Arc<Index>>,
Path(DeserializeOrdinalFromStr(ordinal)): Path<DeserializeOrdinalFromStr>,
Path(DeserializeFromStr(ordinal)): Path<DeserializeFromStr<Ordinal>>,
) -> ServerResult<PageHtml> {
Ok(
OrdinalHtml {
Expand Down Expand Up @@ -331,9 +330,9 @@ impl Server {
}

async fn range(
Path((DeserializeOrdinalFromStr(start), DeserializeOrdinalFromStr(end))): Path<(
DeserializeOrdinalFromStr,
DeserializeOrdinalFromStr,
Path((DeserializeFromStr(start), DeserializeFromStr(end))): Path<(
DeserializeFromStr<Ordinal>,
DeserializeFromStr<Ordinal>,
)>,
) -> ServerResult<PageHtml> {
match start.cmp(&end) {
Expand Down Expand Up @@ -538,6 +537,29 @@ impl Server {
)
}

async fn input(
Extension(index): Extension<Arc<Index>>,
Path(path): Path<(u64, usize, usize)>,
) -> Result<PageHtml, ServerError> {
let not_found =
|| ServerError::NotFound(format!("Input /{}/{}/{} unknown", path.0, path.1, path.2));

let block = index
.block(path.0)
.map_err(ServerError::Internal)?
.ok_or_else(not_found)?;

let transaction = block.txdata.into_iter().nth(path.1).ok_or_else(not_found)?;

let input = transaction
.input
.into_iter()
.nth(path.2)
.ok_or_else(not_found)?;

Ok(InputHtml { path, input }.page())
}

async fn faq() -> Redirect {
Redirect::to("https://docs.ordinals.com/faq/")
}
Expand Down Expand Up @@ -1038,10 +1060,10 @@ mod tests {
test_server.assert_response_regex(
"/output/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0",
StatusCode::OK,
".*<title>Output 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0</title>.*<h1>Output 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0</h1>
".*<title>Output 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0</title>.*<h1>Output <span class=monospace>4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b:0</span></h1>
<dl>
<dt>value</dt><dd>5000000000</dd>
<dt>script pubkey</dt><dd>OP_PUSHBYTES_65 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG</dd>
<dt>script pubkey</dt><dd class=data>OP_PUSHBYTES_65 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG</dd>
</dl>
<h2>1 Ordinal Range</h2>
<ul class=monospace>
Expand Down Expand Up @@ -1086,7 +1108,7 @@ mod tests {
<dt>block</dt><dd>1</dd>
</dl>
<h2>Latest Blocks</h2>
<ol start=1 reversed class='blocks monospace'>
<ol start=1 reversed class=blocks>
<li><a href=/block/[[:xdigit:]]{64}>[[:xdigit:]]{64}</a></li>
<li><a href=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/block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f>000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f</a></li>
</ol>.*",
Expand All @@ -1102,7 +1124,7 @@ mod tests {
test_server.assert_response_regex(
"/",
StatusCode::OK,
".*<ol start=101 reversed class='blocks monospace'>\n( <li><a href=/block/[[:xdigit:]]{64}>[[:xdigit:]]{64}</a></li>\n){100}</ol>.*"
".*<ol start=101 reversed class=blocks>\n( <li><a href=/block/[[:xdigit:]]{64}>[[:xdigit:]]{64}</a></li>\n){100}</ol>.*"
);
}

Expand Down Expand Up @@ -1173,13 +1195,13 @@ mod tests {
test_server.assert_response_regex(
&format!("/block/{block_hash}"),
StatusCode::OK,
".*<h1>Block [[:xdigit:]]{64}</h1>
".*<h1>Block <span class=monospace>[[:xdigit:]]{64}</span></h1>
<dl>
<dt>height</dt><dd>2</dd>
<dt>timestamp</dt><dd>0</dd>
<dt>size</dt><dd>203</dd>
<dt>weight</dt><dd>812</dd>
<dt>prev blockhash</dt><dd><a href=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/block/659f9b67fbc0b5cba0ef6ebc0aea322e1c246e29e43210bd581f5f3bd36d17bf>659f9b67fbc0b5cba0ef6ebc0aea322e1c246e29e43210bd581f5f3bd36d17bf</a></dd>
<dt>prev blockhash</dt><dd><a href=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/block/659f9b67fbc0b5cba0ef6ebc0aea322e1c246e29e43210bd581f5f3bd36d17bf class=monospace>659f9b67fbc0b5cba0ef6ebc0aea322e1c246e29e43210bd581f5f3bd36d17bf</a></dd>
</dl>
<h2>2 Transactions</h2>
<ul class=monospace>
Expand All @@ -1200,16 +1222,16 @@ mod tests {
&format!("/tx/{txid}"),
StatusCode::OK,
&format!(
".*<title>Transaction {txid}</title>.*<h1>Transaction {txid}</h1>
".*<title>Transaction {txid}</title>.*<h1>Transaction <span class=monospace>{txid}</span></h1>
<h2>1 Output</h2>
<ul class=monospace>
<li>
<a href=/output/9068a11b8769174363376b606af9a4b8b29dd7b13d013f4b0cbbd457db3c3ce5:0>
<a href=/output/9068a11b8769174363376b606af9a4b8b29dd7b13d013f4b0cbbd457db3c3ce5:0 class=monospace>
9068a11b8769174363376b606af9a4b8b29dd7b13d013f4b0cbbd457db3c3ce5:0
</a>
<dl>
<dt>value</dt><dd>5000000000</dd>
<dt>script pubkey</dt><dd></dd>
<dt>script pubkey</dt><dd class=data></dd>
</dl>
</li>
</ul>.*"
Expand Down Expand Up @@ -1242,6 +1264,24 @@ mod tests {
);
}

#[test]
fn input() {
TestServer::new().assert_response_regex(
"/input/0/0/0",
StatusCode::OK,
".*<title>Input /0/0/0</title>.*<h1>Input /0/0/0</h1>.*<dt>text</dt><dd>.*The Times 03/Jan/2009 Chancellor on brink of second bailout for banks</dd>.*",
);
}

#[test]
fn input_missing() {
TestServer::new().assert_response(
"/input/1/1/1",
StatusCode::NOT_FOUND,
"Input /1/1/1 unknown",
);
}

#[test]
fn rune_not_found() {
TestServer::new().assert_response(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use super::*;

pub(crate) struct DeserializeOrdinalFromStr(pub(crate) Ordinal);
pub(crate) struct DeserializeFromStr<T: FromStr>(pub(crate) T);

impl<'de> Deserialize<'de> for DeserializeOrdinalFromStr {
impl<'de, T: FromStr> Deserialize<'de> for DeserializeFromStr<T>
where
T::Err: Display,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
Expand Down
25 changes: 16 additions & 9 deletions src/subcommand/server/templates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@ use {
html_escaper::{Escape, Trusted},
};

pub(crate) mod block;
pub(crate) mod clock;
pub(crate) mod home;
pub(crate) mod ordinal;
pub(crate) mod output;
pub(crate) mod range;
pub(crate) mod rare;
pub(crate) mod rune;
pub(crate) mod transaction;
pub(crate) use {
block::BlockHtml, clock::ClockSvg, home::HomeHtml, input::InputHtml, ordinal::OrdinalHtml,
output::OutputHtml, range::RangeHtml, rare::RareTxt, rune::RuneHtml,
transaction::TransactionHtml,
};

mod block;
mod clock;
mod home;
mod input;
mod ordinal;
mod output;
mod range;
mod rare;
mod rune;
mod transaction;

#[derive(Boilerplate)]
pub(crate) struct PageHtml {
Expand Down
8 changes: 4 additions & 4 deletions src/subcommand/server/templates/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,23 @@ impl Content for BlockHtml {

#[cfg(test)]
mod tests {
use {super::*, pretty_assertions::assert_eq, unindent::Unindent};
use super::*;

#[test]
fn block_html() {
assert_eq!(
pretty_assert_eq!(
BlockHtml::new(bitcoin::blockdata::constants::genesis_block(
Network::Bitcoin
), Height(0))
.to_string(),
"
<h1>Block 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f</h1>
<h1>Block <span class=monospace>000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f</span></h1>
<dl>
<dt>height</dt><dd>0</dd>
<dt>timestamp</dt><dd>1231006505</dd>
<dt>size</dt><dd>285</dd>
<dt>weight</dt><dd>1140</dd>
<dt>prev blockhash</dt><dd><a href=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/block/0000000000000000000000000000000000000000000000000000000000000000>0000000000000000000000000000000000000000000000000000000000000000</a></dd>
<dt>prev blockhash</dt><dd><a href=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/block/0000000000000000000000000000000000000000000000000000000000000000 class=monospace>0000000000000000000000000000000000000000000000000000000000000000</a></dd>
</dl>
<h2>1 Transaction</h2>
<ul class=monospace>
Expand Down
Loading

0 comments on commit a7aa13f

Please sign in to comment.