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

Feature add indexed recursive inscriptions endpoint #3936

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
31 changes: 31 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,37 @@ impl Index {
.transpose()
}

pub fn get_children_at_index_by_sequence_number(
&self,
sequence_number: u32,
index: isize,
) -> Result<Option<InscriptionId>> {
let rtx = self.database.begin_read()?;

let sequence_number_to_children = rtx.open_multimap_table(SEQUENCE_NUMBER_TO_CHILDREN)?;
let sequence_number_to_inscription_entry =
rtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?;
if index < 0 {
sequence_number_to_children
.get(sequence_number)?
.nth_back((index + 1).abs_diff(0))
} else {
sequence_number_to_children
.get(sequence_number)?
.nth(index.abs_diff(0))
}
.map(|result| {
result
.and_then(|sequence_number| {
let sequence_number = sequence_number.value();
sequence_number_to_inscription_entry
.get(sequence_number)
.map(|entry| InscriptionEntry::load(entry.unwrap().value()).id)
})
.map_err(|err| anyhow!(err.to_string()))
})
.transpose()
}
#[cfg(test)]
pub(crate) fn get_inscription_id_by_inscription_number(
&self,
Expand Down
99 changes: 99 additions & 0 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ impl Server {
"/r/children/:inscription_id/inscriptions",
get(Self::child_inscriptions_recursive),
)
.route(
"/r/children/:inscription_id/at/:index",
get(Self::child_inscription_at_index),
)
.route(
"/r/children/:inscription_id/inscriptions/:page",
get(Self::child_inscriptions_recursive_paginated),
Expand Down Expand Up @@ -2043,6 +2047,41 @@ impl Server {
})
}

async fn child_inscription_at_index(
Extension(index): Extension<Arc<Index>>,
Path((parent, inscription_index)): Path<(InscriptionId, isize)>,
) -> ServerResult {
task::block_in_place(|| {
let entry = index
.get_inscription_entry(parent)?
.ok_or_not_found(|| format!("inscription {parent}"))?;

let id = index
.get_children_at_index_by_sequence_number(entry.sequence_number, inscription_index)?
.ok_or_not_found(|| format!("child {inscription_index}"))?;

let satpoint = index
.get_inscription_satpoint_by_id(id)
.ok()
.flatten()
.unwrap();

Ok(
Json(api::ChildInscriptionRecursive {
charms: Charm::charms(entry.charms),
fee: entry.fee,
height: entry.height,
id,
number: entry.inscription_number,
output: satpoint.outpoint,
sat: entry.sat,
satpoint,
timestamp: timestamp(entry.timestamp.into()).timestamp(),
})
.into_response(),
)
})
}
async fn inscriptions(
Extension(server_config): Extension<Arc<ServerConfig>>,
Extension(index): Extension<Arc<Index>>,
Expand Down Expand Up @@ -6497,6 +6536,66 @@ next
assert_eq!(children_json.page, 1);
}

#[test]
fn children_recursive_indexed_endpoint() {
let server = TestServer::builder().chain(Chain::Regtest).build();
server.mine_blocks(1);

let parent_txid = server.core.broadcast_tx(TransactionTemplate {
inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())],
..default()
});

let parent_inscription_id = InscriptionId {
txid: parent_txid,
index: 0,
};

server.assert_response(
format!("/r/children/{parent_inscription_id}/at/-1"),
StatusCode::NOT_FOUND,
&format!("inscription {parent_inscription_id} not found"),
);

server.mine_blocks(1);

let mut builder = script::Builder::new();
for _ in 0..70 {
builder = Inscription {
content_type: Some("text/plain".into()),
body: Some("hello".into()),
parents: vec![parent_inscription_id.value()],
unrecognized_even_field: false,
..default()
}
.append_reveal_script_to_builder(builder);
}

let witness = Witness::from_slice(&[builder.into_bytes(), Vec::new()]);

let txid = server.core.broadcast_tx(TransactionTemplate {
inputs: &[(2, 0, 0, witness), (2, 1, 0, Default::default())],
..default()
});

server.mine_blocks(1);
let latest_child_inscription_id = InscriptionId { txid, index: 69 };
let child_json = server.get_json::<api::ChildInscriptionRecursive>(format!(
"/r/children/{parent_inscription_id}/at/-1"
));
assert_eq!(child_json.id, latest_child_inscription_id);
let zeroth_child_inscription_id = InscriptionId { txid, index: 0 };
let zeroth_child = server.get_json::<api::ChildInscriptionRecursive>(format!(
"/r/children/{parent_inscription_id}/at/0"
));
assert_eq!(zeroth_child.id, zeroth_child_inscription_id);
let first_child_inscription_id = InscriptionId { txid, index: 1 };
let first_child = server.get_json::<api::ChildInscriptionRecursive>(format!(
"/r/children/{parent_inscription_id}/at/1"
));
assert_eq!(first_child.id, first_child_inscription_id);
}

twosatsmaxi marked this conversation as resolved.
Show resolved Hide resolved
#[test]
fn parents_recursive_endpoint() {
let server = TestServer::builder().chain(Chain::Regtest).build();
Expand Down
Loading