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

feat(rune): ordzaar custom rune api #8

Open
wants to merge 4 commits into
base: ordzaar-master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/ordzaar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ use super::*;

pub mod inscriptions;
pub mod ordinals;
pub mod runes;
96 changes: 96 additions & 0 deletions src/ordzaar/runes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use super::*;

// Custom Ordzaar Rune Response
// one of the reasons to create a custom response is to
// convert some of the bigint values into string
// and also to make the response consistent
// (prevent broken responses when bumping to the latest Ord version)

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct RuneOutpoint {
pub rune_spaced: String,
pub amount: String,
pub divisibility: u8,
pub symbol: Option<char>,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct RuneDetailMint {
pub deadline: Option<u32>,
pub end: Option<u32>,
pub limit: Option<String>,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct RuneDetail {
pub rune_id: RuneId,
pub rune: Rune,
pub rune_spaced: String,
pub burned: String,
pub divisibility: u8,
pub etching: Txid,
pub mint: Option<RuneDetailMint>,
pub mints: String,
pub number: String,
pub spacers: u32,
pub supply: String,
pub symbol: Option<char>,
pub timestamp: u32,
}

impl RuneOutpoint {
pub fn from_spaced_rune_pile(spaced_rune_piled: (SpacedRune, Pile)) -> Self {
Self {
rune_spaced: spaced_rune_piled.0.to_string(),
amount: spaced_rune_piled.1.amount.to_string(),
divisibility: spaced_rune_piled.1.divisibility,
symbol: spaced_rune_piled.1.symbol,
}
}
}

impl RuneDetail {
pub fn from_rune(rune_id: RuneId, entry: RuneEntry) -> Self {
let mut mint: Option<RuneDetailMint> = None;
if let Some(mint_value) = entry.mint {
mint = Some(RuneDetailMint {
deadline: mint_value.deadline,
end: mint_value.end,
limit: match mint_value.limit {
Some(value) => Some(value.to_string()),
None => None,
},
})
}

let rune_spaced = SpacedRune{
rune: entry.rune,
spacers: entry.spacers
};

Self {
rune_id,
rune: entry.rune,
rune_spaced: rune_spaced.to_string(),
burned: entry.burned.to_string(),
divisibility: entry.divisibility,
etching: entry.etching,
mint,
mints: entry.mints.to_string(),
number: entry.number.to_string(),
spacers: entry.spacers,
supply: entry.supply.to_string(),
symbol: entry.symbol,
timestamp: entry.timestamp,
}
}
}

pub fn str_coma_to_array(str_coma: &str) -> Vec<String> {
str_coma.split(',').map(|s| s.trim().to_string()).collect()
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct RuneOutputBulkQuery {
pub outpoints: String,
}
94 changes: 93 additions & 1 deletion src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,16 @@ impl Server {
.route("/status", get(Self::status))
.route("/tx/:txid", get(Self::transaction))
// ---- Ordzaar routes ----
// Deprecated: Ordzaar custom routes should use"ordzar" prefix/path
// to prevent duplication with the Ord server paths.
.route("/inscriptions", post(Self::ordzaar_inscriptions_from_ids))
.route("/ordinals/:outpoint", get(Self::ordzaar_ordinals_from_outpoint))

.route("/ordzaar/inscriptions", post(Self::ordzaar_inscriptions_from_ids))
.route("/ordzaar/ordinals/:outpoint", get(Self::ordzaar_ordinals_from_outpoint))
.route("/ordzaar/rune/:rune", get(Self::ordzaar_rune_detail))
.route("/ordzaar/rune/output/:outpoint", get(Self::ordzaar_rune_output))
.route("/ordzaar/rune/outputs/bulk", get(Self::ordzaar_rune_output_bulk))
// ---- Ordzaar routes ----
.layer(Extension(index))
.layer(Extension(server_config.clone()))
Expand Down Expand Up @@ -382,6 +390,87 @@ impl Server {
}
Ok(Json(inscriptions).into_response())
}

async fn ordzaar_rune_output(
Extension(index): Extension<Arc<Index>>,
Path(outpoint): Path<OutPoint>,
) -> ServerResult<Response> {
task::block_in_place(|| {
if !index.has_rune_index() {
return Err(ServerError::NotFound(
"this server has no rune index".to_string(),
));
}
let runes = index.get_rune_balances_for_outpoint(outpoint)?;

let response: Vec<ordzaar::runes::RuneOutpoint> = runes
.into_iter()
.map(|rune| ordzaar::runes::RuneOutpoint::from_spaced_rune_pile(rune))
.collect();

Ok(Json(response).into_response())
})
}

async fn ordzaar_rune_output_bulk(
Extension(index): Extension<Arc<Index>>,
Query(query): Query<ordzaar::runes::RuneOutputBulkQuery>,
) -> ServerResult<Response> {
task::block_in_place(|| {
if !index.has_rune_index() {
return Err(ServerError::NotFound(
"this server has no rune index".to_string(),
));
}

let mut results = HashMap::new();
for outpoint_str in ordzaar::runes::str_coma_to_array(&query.outpoints) {
let outpoint_result = OutPoint::from_str(&outpoint_str);
if !outpoint_result.is_ok() {
return Err(ServerError::BadRequest(format!(
"error parsing outpoint: {outpoint_str}"
)));
}
let runes = index.get_rune_balances_for_outpoint(outpoint_result.unwrap())?;

let response: Vec<ordzaar::runes::RuneOutpoint> = runes
.into_iter()
.map(|rune| ordzaar::runes::RuneOutpoint::from_spaced_rune_pile(rune))
.collect();

results.insert(outpoint_str, response);
}

Ok(Json(results).into_response())
})
}

async fn ordzaar_rune_detail(
Extension(index): Extension<Arc<Index>>,
Path(DeserializeFromStr(rune_query)): Path<DeserializeFromStr<query::Rune>>,
) -> ServerResult<Response> {
task::block_in_place(|| {
if !index.has_rune_index() {
return Err(ServerError::NotFound(
"this server has no rune index".to_string(),
));
}

let rune = match rune_query {
query::Rune::SpacedRune(spaced_rune) => spaced_rune.rune,
query::Rune::RuneId(rune_id) => index
.get_rune_by_id(rune_id)?
.ok_or_not_found(|| format!("rune {rune_id}"))?,
};

let (id, entry, _) = index
.rune(rune)?
.ok_or_not_found(|| format!("rune {rune}"))?;

Ok(Json(ordzaar::runes::RuneDetail::from_rune(id, entry)).into_response())
})
}

// ---- Ordzaar methods ----

fn spawn(
Expand Down Expand Up @@ -1549,7 +1638,10 @@ impl Server {
// ---- Ordzaar ----
inscription_sequence: info.entry.sequence_number,
delegate: info.inscription.delegate(),
content_encoding: info.inscription.content_encoding_str().map(|s| s.to_string()),
content_encoding: info
.inscription
.content_encoding_str()
.map(|s| s.to_string()),
// ---- Ordzaar ----
})
.into_response()
Expand Down
2 changes: 1 addition & 1 deletion src/subcommand/server/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl Display for Inscription {
}
}

pub(super) enum Rune {
pub enum Rune {
SpacedRune(SpacedRune),
RuneId(RuneId),
}
Expand Down