Skip to content

Commit

Permalink
JSON API for /inscription, /inscriptions and /output (#2323)
Browse files Browse the repository at this point in the history
  • Loading branch information
veryordinally authored Aug 14, 2023
1 parent f3a5182 commit 40e4807
Show file tree
Hide file tree
Showing 15 changed files with 667 additions and 86 deletions.
10 changes: 10 additions & 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 @@ -35,6 +35,7 @@ html-escaper = "0.2.0"
http = "0.2.6"
hyper = { version = "0.14.24", features = ["http1", "client"] }
indicatif = "0.17.1"
itertools = "0.11.0"
lazy_static = "1.4.0"
log = "0.4.14"
mime = "0.3.16"
Expand Down
2 changes: 1 addition & 1 deletion src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use {super::*, clap::ValueEnum};

#[derive(Default, ValueEnum, Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub(crate) enum Chain {
pub enum Chain {
#[default]
#[clap(alias("main"))]
Mainnet,
Expand Down
60 changes: 46 additions & 14 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use {
bitcoincore_rpc::{json::GetBlockHeaderResult, Client},
chrono::SubsecRound,
indicatif::{ProgressBar, ProgressStyle},
itertools::Itertools,
log::log_enabled,
redb::{
Database, MultimapTable, MultimapTableDefinition, ReadableMultimapTable, ReadableTable, Table,
Expand Down Expand Up @@ -57,7 +58,7 @@ define_table! { STATISTIC_TO_COUNT, u64, u64 }
define_table! { WRITE_TRANSACTION_STARTING_BLOCK_COUNT_TO_TIMESTAMP, u64, u128 }

#[derive(Debug, PartialEq)]
pub(crate) enum List {
pub enum List {
Spent,
Unspent(Vec<(u64, u64)>),
}
Expand Down Expand Up @@ -877,19 +878,23 @@ impl Index {
&self,
n: usize,
from: Option<i64>,
) -> Result<(Vec<InscriptionId>, Option<i64>, Option<i64>)> {
) -> Result<(Vec<InscriptionId>, Option<i64>, Option<i64>, i64, i64)> {
let rtx = self.database.begin_read()?;

let inscription_number_to_inscription_id =
rtx.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?;

let latest = match inscription_number_to_inscription_id.iter()?.next_back() {
let highest = match inscription_number_to_inscription_id.iter()?.next_back() {
Some(Ok((number, _id))) => number.value(),
Some(Err(_)) => return Ok(Default::default()),
None => return Ok(Default::default()),
Some(Err(_)) | None => return Ok(Default::default()),
};

let from = from.unwrap_or(latest);
let lowest = match inscription_number_to_inscription_id.iter()?.next() {
Some(Ok((number, _id))) => number.value(),
Some(Err(_)) | None => return Ok(Default::default()),
};

let from = from.unwrap_or(highest);

let prev = if let Some(prev) = from.checked_sub(n.try_into()?) {
inscription_number_to_inscription_id
Expand All @@ -899,12 +904,12 @@ impl Index {
None
};

let next = if from < latest {
let next = if from < highest {
Some(
from
.checked_add(n.try_into()?)
.unwrap_or(latest)
.min(latest),
.unwrap_or(highest)
.min(highest),
)
} else {
None
Expand All @@ -917,7 +922,32 @@ impl Index {
.flat_map(|result| result.map(|(_number, id)| Entry::load(*id.value())))
.collect();

Ok((inscriptions, prev, next))
Ok((inscriptions, prev, next, lowest, highest))
}

pub(crate) fn get_inscriptions_in_block(&self, block_height: u64) -> Result<Vec<InscriptionId>> {
// This is a naive approach and will require optimization, but we don't have an index by block
let block_inscriptions = self
.database
.begin_read()?
.open_table(INSCRIPTION_ID_TO_INSCRIPTION_ENTRY)?
.iter()?
.filter_map(|result| match result {
Ok((key, entry_value)) => {
let entry = InscriptionEntry::load(entry_value.value());
if entry.height == block_height {
Some((InscriptionId::load(*key.value()), entry.number))
} else {
None
}
}
Err(_) => None,
})
.sorted_by_key(|&(_id, number)| number)
.map(|(id, _)| id)
.collect();

Ok(block_inscriptions)
}

pub(crate) fn get_feed_inscriptions(&self, n: usize) -> Result<Vec<(i64, InscriptionId)>> {
Expand Down Expand Up @@ -2447,7 +2477,7 @@ mod tests {

context.mine_blocks(1);

let (inscriptions, prev, next) = context
let (inscriptions, prev, next, _, _) = context
.index
.get_latest_inscriptions_with_prev_and_next(100, None)
.unwrap();
Expand Down Expand Up @@ -2476,23 +2506,25 @@ mod tests {

ids.reverse();

let (inscriptions, prev, next) = context
let (inscriptions, prev, next, lowest, highest) = context
.index
.get_latest_inscriptions_with_prev_and_next(100, None)
.unwrap();
assert_eq!(inscriptions, &ids[..100]);
assert_eq!(prev, Some(2));
assert_eq!(next, None);
assert_eq!(highest, 102);
assert_eq!(lowest, 0);

let (inscriptions, prev, next) = context
let (inscriptions, prev, next, _lowest, _highest) = context
.index
.get_latest_inscriptions_with_prev_and_next(100, Some(101))
.unwrap();
assert_eq!(inscriptions, &ids[1..101]);
assert_eq!(prev, Some(1));
assert_eq!(next, Some(102));

let (inscriptions, prev, next) = context
let (inscriptions, prev, next, _lowest, _highest) = context
.index
.get_latest_inscriptions_with_prev_and_next(100, Some(0))
.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion src/inscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub(crate) enum Curse {
}

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Inscription {
pub struct Inscription {
body: Option<Vec<u8>>,
content_type: Option<Vec<u8>>,
}
Expand Down
4 changes: 2 additions & 2 deletions src/inscription_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use super::*;

#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)]
pub struct InscriptionId {
pub(crate) txid: Txid,
pub(crate) index: u32,
pub txid: Txid,
pub index: u32,
}

impl<'de> Deserialize<'de> for InscriptionId {
Expand Down
Loading

0 comments on commit 40e4807

Please sign in to comment.