Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add previous and next links to inscription page #1193

Merged
merged 14 commits into from
Jan 11, 2023
30 changes: 30 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ macro_rules! define_table {

define_table! { HEIGHT_TO_BLOCK_HASH, u64, &BlockHashArray }
define_table! { INSCRIPTION_ID_TO_HEIGHT, &InscriptionIdArray, u64 }
define_table! { INSCRIPTION_ID_TO_INSCRIPTION_NUMBER, &InscriptionIdArray, u64}
define_table! { INSCRIPTION_ID_TO_SAT, &InscriptionIdArray, u64 }
define_table! { INSCRIPTION_ID_TO_SATPOINT, &InscriptionIdArray, &SatPointArray }
define_table! { INSCRIPTION_NUMBER_TO_INSCRIPTION_ID, u64, &InscriptionIdArray }
Expand Down Expand Up @@ -235,6 +236,7 @@ impl Index {

tx.open_table(HEIGHT_TO_BLOCK_HASH)?;
tx.open_table(INSCRIPTION_ID_TO_HEIGHT)?;
tx.open_table(INSCRIPTION_ID_TO_INSCRIPTION_NUMBER)?;
tx.open_table(INSCRIPTION_ID_TO_SAT)?;
tx.open_table(INSCRIPTION_ID_TO_SATPOINT)?;
tx.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?;
Expand Down Expand Up @@ -496,6 +498,34 @@ impl Index {
)
}

pub(crate) fn get_inscription_number_by_inscription_id(
&self,
id: InscriptionId,
) -> Result<Option<u64>> {
Ok(
self
.database
.begin_read()?
.open_table(INSCRIPTION_ID_TO_INSCRIPTION_NUMBER)?
.get(&id.as_inner())?
.map(|n| n.value()),
)
}

pub(crate) fn get_inscription_id_by_inscription_number(
&self,
n: u64,
) -> Result<Option<InscriptionId>> {
Ok(
self
.database
.begin_read()?
.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?
.get(&n)?
.map(|id| decode_inscription_id(*id.value())),
)
}

pub(crate) fn get_sat_by_inscription_id(
&self,
inscription_id: InscriptionId,
Expand Down
3 changes: 3 additions & 0 deletions src/index/updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ impl Updater {
}

let mut inscription_id_to_height = wtx.open_table(INSCRIPTION_ID_TO_HEIGHT)?;
let mut inscription_id_to_inscription_number =
wtx.open_table(INSCRIPTION_ID_TO_INSCRIPTION_NUMBER)?;
let mut inscription_id_to_sat = wtx.open_table(INSCRIPTION_ID_TO_SAT)?;
let mut inscription_id_to_satpoint = wtx.open_table(INSCRIPTION_ID_TO_SATPOINT)?;
let mut inscription_number_to_inscription_id =
Expand All @@ -291,6 +293,7 @@ impl Updater {
let mut inscription_updater = InscriptionUpdater::new(
self.height,
&mut inscription_id_to_height,
&mut inscription_id_to_inscription_number,
&mut inscription_id_to_satpoint,
index,
&mut inscription_id_to_sat,
Expand Down
6 changes: 6 additions & 0 deletions src/index/updater/inscription_updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub(super) struct InscriptionUpdater<'a, 'db, 'tx> {
flotsam: Vec<Flotsam>,
height: u64,
id_to_height: &'a mut Table<'db, 'tx, &'tx InscriptionIdArray, u64>,
id_to_number: &'a mut Table<'db, 'tx, &'tx InscriptionIdArray, u64>,
id_to_satpoint: &'a mut Table<'db, 'tx, &'tx InscriptionIdArray, &'tx SatPointArray>,
index: &'a Index,
inscription_id_to_sat: &'a mut Table<'db, 'tx, &'tx InscriptionIdArray, u64>,
Expand All @@ -32,6 +33,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
pub(super) fn new(
height: u64,
id_to_height: &'a mut Table<'db, 'tx, &'tx InscriptionIdArray, u64>,
id_to_number: &'a mut Table<'db, 'tx, &'tx InscriptionIdArray, u64>,
id_to_satpoint: &'a mut Table<'db, 'tx, &'tx InscriptionIdArray, &'tx SatPointArray>,
index: &'a Index,
inscription_id_to_sat: &'a mut Table<'db, 'tx, &'tx InscriptionIdArray, u64>,
Expand All @@ -53,6 +55,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
flotsam: Vec::new(),
height,
id_to_height,
id_to_number,
id_to_satpoint,
index,
inscription_id_to_sat,
Expand Down Expand Up @@ -203,6 +206,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
}
Origin::New => {
self.id_to_height.insert(&inscription_id, &self.height)?;
self
.id_to_number
.insert(&inscription_id, &self.next_number)?;
self
.number_to_id
.insert(&self.next_number, &inscription_id)?;
Expand Down
51 changes: 21 additions & 30 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,13 +635,32 @@ impl Server {
.nth(satpoint.outpoint.vout.try_into().unwrap())
.ok_or_not_found(|| format!("inscription {inscription_id} current transaction output"))?;

let number = index
.get_inscription_number_by_inscription_id(inscription_id)?
.ok_or_not_found(|| format!("inscription {inscription_id} number"))?;

let previous = if let Some(previous) = number.checked_sub(1) {
Some(
index
.get_inscription_id_by_inscription_number(previous)?
.ok_or_not_found(|| format!("inscription {previous}"))?,
)
} else {
None
};

let next = index.get_inscription_id_by_inscription_number(number + 1)?;

Ok(
InscriptionHtml {
chain,
genesis_height,
inscription,
inscription_id,
number,
next,
output,
previous,
sat,
satpoint,
}
Expand Down Expand Up @@ -1327,43 +1346,15 @@ mod tests {
test_server.assert_response_regex(
format!("/block/{block_hash}"),
StatusCode::OK,
".*<h1>Block 2</h1>
<dl>
<dt>hash</dt><dd class=monospace>[[:xdigit:]]{64}</dd>
<dt>target</dt><dd class=monospace>[[:xdigit:]]{64}</dd>
<dt>timestamp</dt><dd>0</dd>
<dt>size</dt><dd>202</dd>
<dt>weight</dt><dd>808</dd>
<dt>previous blockhash</dt><dd><a href=/block/659f9b67fbc0b5cba0ef6ebc0aea322e1c246e29e43210bd581f5f3bd36d17bf class=monospace>659f9b67fbc0b5cba0ef6ebc0aea322e1c246e29e43210bd581f5f3bd36d17bf</a></dd>
</dl>
<a href=/block/1>prev</a>
next
<h2>2 Transactions</h2>
<ul class=monospace>
<li><a href=/tx/[[:xdigit:]]{64}>[[:xdigit:]]{64}</a></li>
<li><a href=/tx/[[:xdigit:]]{64}>[[:xdigit:]]{64}</a></li>
</ul>.*",
".*<h1>Block 2</h1>.*",
);
}

#[test]
fn block_by_height() {
let test_server = TestServer::new();

test_server.assert_response_regex(
"/block/0",
StatusCode::OK,
".*<h1>Block 0</h1>
<dl>
<dt>hash</dt><dd class=monospace>[[:xdigit:]]{64}</dd>
<dt>target</dt><dd class=monospace>[[:xdigit:]]{64}</dd>
<dt>timestamp</dt><dd>1231006505</dd>
<dt>size</dt><dd>285</dd>
<dt>weight</dt><dd>1140</dd>
</dl>
prev
next.*",
);
test_server.assert_response_regex("/block/0", StatusCode::OK, ".*<h1>Block 0</h1>.*");
}

#[test]
Expand Down
122 changes: 24 additions & 98 deletions src/templates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,22 @@ pub(crate) trait PageContent: Display + 'static {
mod tests {
use super::*;

#[test]
fn page_mainnet() {
struct Foo;
struct Foo;

impl Display for Foo {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "<h1>Foo</h1>")
}
impl Display for Foo {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "<h1>Foo</h1>")
}
}

impl PageContent for Foo {
fn title(&self) -> String {
"Foo".to_string()
}
impl PageContent for Foo {
fn title(&self) -> String {
"Foo".to_string()
}
}

#[test]
fn page() {
assert_regex_match!(
Foo.page(Chain::Mainnet, true),
"<!doctype html>
Expand All @@ -90,6 +90,7 @@ mod tests {
<title>Foo</title>
<link href=/static/index.css rel=stylesheet>
<link href=/static/modern-normalize.css rel=stylesheet>
<script src=/static/index.js defer></script>
</head>
<body>
<header>
Expand All @@ -114,101 +115,26 @@ mod tests {
}

#[test]
fn page_no_sat_index() {
struct Foo;

impl Display for Foo {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "<h1>Foo</h1>")
}
}

impl PageContent for Foo {
fn title(&self) -> String {
"Foo".to_string()
}
}
fn page_mainnet() {
assert_regex_match!(
Foo.page(Chain::Mainnet, true),
r".*<nav>\s*<a href=/>Ordinals<sup>alpha</sup></a>.*"
);
}

#[test]
fn page_no_sat_index() {
assert_regex_match!(
Foo.page(Chain::Mainnet, false).to_string(),
"<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name=format-detection content='telephone=no'>
<meta name=viewport content='width=device-width,initial-scale=1.0'>
<title>Foo</title>
<link href=/static/index.css rel=stylesheet>
<link href=/static/modern-normalize.css rel=stylesheet>
</head>
<body>
<header>
<nav>
<a href=/>Ordinals<sup>alpha</sup></a>
.*
<a href=/clock>Clock</a>
<form action=/search method=get>
<input type=text .*>
<input type=submit value=Search>
</form>
</nav>
</header>
<main>
<h1>Foo</h1>
</main>
</body>
</html>
"
Foo.page(Chain::Mainnet, false),
r".*<nav>\s*<a href=/>Ordinals<sup>alpha</sup></a>.*<a href=/clock>Clock</a>\s*<form action=/search.*",
);
}

#[test]
fn page_signet() {
struct Foo;

impl Display for Foo {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "<h1>Foo</h1>")
}
}

impl PageContent for Foo {
fn title(&self) -> String {
"Foo".to_string()
}
}

assert_regex_match!(
Foo.page(Chain::Signet, true).to_string(),
"<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name=format-detection content='telephone=no'>
<meta name=viewport content='width=device-width,initial-scale=1.0'>
<title>Foo</title>
<link href=/static/index.css rel=stylesheet>
<link href=/static/modern-normalize.css rel=stylesheet>
</head>
<body>
<header>
<nav>
<a href=/>Ordinals<sup>signet</sup></a>
.*
<a href=/clock>Clock</a>
<a href=/rare.txt>rare.txt</a>
<form action=/search method=get>
<input type=text .*>
<input type=submit value=Search>
</form>
</nav>
</header>
<main>
<h1>Foo</h1>
</main>
</body>
</html>
"
Foo.page(Chain::Signet, true),
r".*<nav>\s*<a href=/>Ordinals<sup>signet</sup></a>.*"
);
}
}
Loading