diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 0fe115bec6..5a32d63216 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -185,18 +185,11 @@ impl Server { let router = Router::new() .route("/", get(Self::home)) - .route("/r/blockheight", get(Self::block_height)) - .route("/r/blockhash", get(Self::block_hash_json)) - .route( - "/r/blockhash/:height", - get(Self::block_hash_from_height_json), - ) - .route("/r/blocktime", get(Self::block_time)) .route("/block/:query", get(Self::block)) .route("/blockcount", get(Self::block_count)) - .route("/blockheight", get(Self::block_height)) .route("/blockhash", get(Self::block_hash)) .route("/blockhash/:height", get(Self::block_hash_from_height)) + .route("/blockheight", get(Self::block_height)) .route("/blocktime", get(Self::block_time)) .route("/bounties", get(Self::bounties)) .route("/clock", get(Self::clock)) @@ -207,6 +200,8 @@ impl Server { .route("/input/:block/:transaction/:input", get(Self::input)) .route("/inscription/:inscription_query", get(Self::inscription)) .route("/inscriptions", get(Self::inscriptions)) + .route("/inscriptions/:from", get(Self::inscriptions_from)) + .route("/inscriptions/:from/:n", get(Self::inscriptions_from_n)) .route( "/inscriptions/block/:height", get(Self::inscriptions_in_block), @@ -215,12 +210,18 @@ impl Server { "/inscriptions/block/:height/:page_index", get(Self::inscriptions_in_block_from_page), ) - .route("/inscriptions/:from", get(Self::inscriptions_from)) - .route("/inscriptions/:from/:n", get(Self::inscriptions_from_n)) .route("/install.sh", get(Self::install_script)) .route("/ordinal/:sat", get(Self::ordinal)) .route("/output/:output", get(Self::output)) .route("/preview/:inscription_id", get(Self::preview)) + .route("/r/blockhash", get(Self::block_hash_json)) + .route( + "/r/blockhash/:height", + get(Self::block_hash_from_height_json), + ) + .route("/r/blockheight", get(Self::block_height)) + .route("/r/blocktime", get(Self::block_time)) + .route("/r/metadata/:inscription_id", get(Self::metadata)) .route("/range/:start/:end", get(Self::range)) .route("/rare.txt", get(Self::rare_txt)) .route("/rune/:rune", get(Self::rune)) @@ -693,6 +694,19 @@ impl Server { ) } + async fn metadata( + Extension(index): Extension>, + Path(inscription_id): Path, + ) -> ServerResult> { + let metadata = index + .get_inscription_by_id(inscription_id)? + .ok_or_not_found(|| format!("inscription {inscription_id}"))? + .metadata + .ok_or_not_found(|| format!("inscription {inscription_id} metadata"))?; + + Ok(Json(hex::encode(metadata))) + } + async fn status(Extension(index): Extension>) -> (StatusCode, &'static str) { if index.is_unrecoverably_reorged() { ( diff --git a/tests/server.rs b/tests/server.rs index 5be237a62e..a8c44dfee4 100644 --- a/tests/server.rs +++ b/tests/server.rs @@ -1,4 +1,7 @@ -use {super::*, crate::command_builder::ToArgs, ord::subcommand::wallet::send::Output}; +use { + super::*, crate::command_builder::ToArgs, ciborium::value::Integer, + ord::subcommand::wallet::send::Output, +}; #[test] fn run() { @@ -190,6 +193,55 @@ fn inscription_content() { assert_eq!(response.bytes().unwrap(), "FOO"); } +#[test] +fn inscription_metadata() { + let metadata = r#"{"foo":"bar","baz":1}"#; + let mut encoded_metadata = Vec::new(); + let cbor_map = ciborium::value::Value::Map(vec![ + ( + ciborium::value::Value::Text("foo".into()), + ciborium::value::Value::Text("bar".into()), + ), + ( + ciborium::value::Value::Text("baz".into()), + ciborium::value::Value::Integer(Integer::from(1)), + ), + ]); + ciborium::ser::into_writer(&cbor_map, &mut encoded_metadata).unwrap(); + + let rpc_server = test_bitcoincore_rpc::spawn(); + create_wallet(&rpc_server); + + rpc_server.mine_blocks(1); + + let inscription_id = CommandBuilder::new( + "wallet inscribe --fee-rate 1 --json-metadata metadata.json --file foo.txt", + ) + .write("foo.txt", "FOO") + .write("metadata.json", metadata) + .rpc_server(&rpc_server) + .run_and_deserialize_output::() + .inscriptions + .get(0) + .unwrap() + .id; + + rpc_server.mine_blocks(1); + + let response = + TestServer::spawn_with_args(&rpc_server, &[]).request(format!("/r/metadata/{inscription_id}")); + + assert_eq!(response.status(), StatusCode::OK); + assert_eq!( + response.headers().get("content-type").unwrap(), + "application/json" + ); + assert_eq!( + response.text().unwrap(), + format!("\"{}\"", hex::encode(encoded_metadata)) + ); +} + #[test] fn inscriptions_page() { let rpc_server = test_bitcoincore_rpc::spawn();