From 769bdbbd65e55dc7c70bbdfe33afec43aa8feb1a Mon Sep 17 00:00:00 2001 From: joundy Date: Fri, 1 Mar 2024 13:47:26 +0700 Subject: [PATCH] feat(ordzaar): methods and apis (#4) --- src/lib.rs | 1 + src/ordzaar/inscriptions.rs | 42 ++++++++++++++++ src/ordzaar/mod.rs | 4 ++ src/ordzaar/ordinals.rs | 92 ++++++++++++++++++++++++++++++++++++ src/subcommand/server.rs | 58 ++++++++++++++++++++++- src/templates/inscription.rs | 4 ++ 6 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 src/ordzaar/inscriptions.rs create mode 100644 src/ordzaar/mod.rs create mode 100644 src/ordzaar/ordinals.rs diff --git a/src/lib.rs b/src/lib.rs index 9102594701..fb49868858 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -128,6 +128,7 @@ mod index; mod inscriptions; mod object; mod options; +mod ordzaar; mod outgoing; pub mod rarity; mod representation; diff --git a/src/ordzaar/inscriptions.rs b/src/ordzaar/inscriptions.rs new file mode 100644 index 0000000000..b16326f2ba --- /dev/null +++ b/src/ordzaar/inscriptions.rs @@ -0,0 +1,42 @@ +use super::*; + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct InscriptionData { + pub inscription_id: InscriptionId, + pub number: i32, + pub sequence: u32, + pub genesis_height: u32, + pub genesis_fee: u64, + pub sat: Option, + pub satpoint: SatPoint, + pub timestamp: i64, +} + +impl InscriptionData { + pub fn new( + genesis_fee: u64, + genesis_height: u32, + inscription_id: InscriptionId, + number: i32, + sequence: u32, + sat: Option, + satpoint: SatPoint, + timestamp: DateTime, + ) -> Self { + Self { + inscription_id, + number, + sequence, + genesis_height, + genesis_fee, + sat, + satpoint, + timestamp: timestamp.timestamp(), + } + } +} + +#[derive(Deserialize)] +pub struct InscriptionIds { + pub ids: Vec, +} diff --git a/src/ordzaar/mod.rs b/src/ordzaar/mod.rs new file mode 100644 index 0000000000..7c01e31dcb --- /dev/null +++ b/src/ordzaar/mod.rs @@ -0,0 +1,4 @@ +use super::*; + +pub mod inscriptions; +pub mod ordinals; diff --git a/src/ordzaar/ordinals.rs b/src/ordzaar/ordinals.rs new file mode 100644 index 0000000000..363b8acd15 --- /dev/null +++ b/src/ordzaar/ordinals.rs @@ -0,0 +1,92 @@ +use super::*; + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct OrdinalJson { + pub number: u64, + pub decimal: String, + pub degree: String, + pub name: String, + pub height: u32, + pub cycle: u32, + pub epoch: u32, + pub period: u32, + pub offset: u64, + pub rarity: Rarity, + pub output: OutPoint, + pub start: u64, + pub end: u64, + pub size: u64, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct Output { + pub output: OutPoint, + pub start: u64, + pub end: u64, + pub size: u64, + pub offset: u64, + pub rarity: Rarity, + pub name: String, +} + +pub fn get_ordinals(index: &Index, outpoint: OutPoint) -> Result> { + match index.list(outpoint)? { + Some(crate::index::List::Unspent(ranges)) => { + let mut ordinals = Vec::new(); + for Output { + output, + start, + end, + size, + offset, + rarity, + name, + } in list(outpoint, ranges) + { + let sat = Sat(start); + ordinals.push(OrdinalJson { + number: sat.n(), + decimal: sat.decimal().to_string(), + degree: sat.degree().to_string(), + name, + height: sat.height().0, + cycle: sat.cycle(), + epoch: sat.epoch().0, + period: sat.period(), + offset, + rarity, + output, + start, + end, + size, + }); + } + Ok(ordinals) + } + Some(crate::index::List::Spent) => Ok(Vec::new()), + None => Ok(Vec::new()), + } +} + +fn list(outpoint: OutPoint, ranges: Vec<(u64, u64)>) -> Vec { + let mut offset = 0; + ranges + .into_iter() + .map(|(start, end)| { + let size = end - start; + let output = Output { + output: outpoint, + start, + end, + size, + offset, + name: Sat(start).name(), + rarity: Sat(start).rarity(), + }; + + offset += size; + + output + }) + .collect() +} diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index a9806f4181..888275bbcd 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -7,6 +7,8 @@ use { }, super::*, crate::{ + ordzaar::inscriptions::{InscriptionData, InscriptionIds}, + ordzaar::ordinals::get_ordinals, server_config::ServerConfig, templates::{ BlockHtml, BlockJson, BlocksHtml, ChildrenHtml, ChildrenJson, ClockSvg, CollectionsHtml, @@ -24,7 +26,7 @@ use { headers::UserAgent, http::{header, HeaderMap, HeaderValue, StatusCode, Uri}, response::{IntoResponse, Redirect, Response}, - routing::get, + routing::{get, post}, Router, TypedHeader, }, axum_server::Handle, @@ -274,6 +276,10 @@ impl Server { .route("/static/*path", get(Self::static_asset)) .route("/status", get(Self::status)) .route("/tx/:txid", get(Self::transaction)) + // ---- Ordzaar routes ---- + .route("/inscriptions", post(Self::ordzaar_inscriptions_from_ids)) + .route("/ordinals/:outpoint", get(Self::ordzaar_ordinals_from_outpoint)) + // ---- Ordzaar routes ---- .layer(Extension(index)) .layer(Extension(server_config.clone())) .layer(Extension(config)) @@ -338,6 +344,52 @@ impl Server { }) } + // ---- Ordzaar methods ---- + async fn ordzaar_ordinals_from_outpoint( + Extension(index): Extension>, + Path(outpoint): Path, + ) -> ServerResult { + index + .get_transaction(outpoint.txid)? + .ok_or_not_found(|| format!("output {outpoint}"))? + .output + .into_iter() + .nth(outpoint.vout as usize) + .ok_or_not_found(|| format!("output {outpoint}"))?; + Ok(Json(get_ordinals(&index, outpoint)?).into_response()) + } + + async fn ordzaar_inscriptions_from_ids( + Extension(index): Extension>, + Json(payload): Json, + ) -> ServerResult { + let mut inscriptions: Vec = Vec::new(); + for id in payload.ids { + let entry = match index.get_inscription_entry(id)? { + Some(entry) => entry, + None => continue, + }; + + let satpoint = match index.get_inscription_satpoint_by_id(id)? { + Some(satpoint) => satpoint, + None => continue, + }; + + inscriptions.push(InscriptionData::new( + entry.fee, + entry.height, + id, + entry.inscription_number, + entry.sequence_number, + entry.sat, + satpoint, + timestamp(entry.timestamp), + )); + } + Ok(Json(inscriptions).into_response()) + } + // ---- Ordzaar methods ---- + fn spawn( &self, router: Router, @@ -1315,6 +1367,10 @@ impl Server { previous: info.previous, next: info.next, rune: info.rune, + + // ---- Ordzaar ---- + inscription_sequence: info.entry.sequence_number, + // ---- Ordzaar ---- }) .into_response() } else { diff --git a/src/templates/inscription.rs b/src/templates/inscription.rs index 2470424a35..c4f412d99e 100644 --- a/src/templates/inscription.rs +++ b/src/templates/inscription.rs @@ -39,6 +39,10 @@ pub struct InscriptionJson { pub sat: Option, pub satpoint: SatPoint, pub timestamp: i64, + + // ---- Ordzaar ---- + pub inscription_sequence: u32 + // ---- Ordzaar ---- } impl PageContent for InscriptionHtml {