From 8d5bb1ef20678b7520dda6928d89e9df9acd6c08 Mon Sep 17 00:00:00 2001 From: Astral Arkitekt Date: Thu, 28 Nov 2024 18:49:52 -0600 Subject: [PATCH 1/6] Added /r/sat//r/sat/:sat_number/at/:index/content --- docs/src/inscriptions/recursion.md | 25 +++++++ src/subcommand/server.rs | 105 +++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/docs/src/inscriptions/recursion.md b/docs/src/inscriptions/recursion.md index abb151bc9c..4c8fae72f7 100644 --- a/docs/src/inscriptions/recursion.md +++ b/docs/src/inscriptions/recursion.md @@ -3389,3 +3389,28 @@ plain-text responses. See [examples](examples.md#recursion) for on-chain examples of inscriptions that feature this functionality. + +
+ + GET + /r/sat/<SAT_NUMBER>/at/<INDEX>/content + + +### Description + +The content of the inscription at `` of all inscriptions on a sat. `` may be a negative number to index from the back. `0` being the first and `-1` being the most recent for example. Requires index with `--index-sats` flag. + +### Example + +Fetch the most recently created inscription content from the queried satoshi + +```bash +curl -s -H "Accept: application/json" \ + http://0.0.0.0:80/r/sat/289488340427831/at/-1/content +``` + +Returns the appropriate mime-type and content of the last inscription created on the queried satoshi. +``` +alwaysbebuilding.bitmap +``` +
diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 38e501f4ed..68684a5699 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -272,6 +272,10 @@ impl Server { "/r/sat/:sat_number/at/:index", get(Self::sat_inscription_at_index), ) + .route( + "/r/sat/:sat_number/at/:index/content", + get(Self::sat_inscription_at_index_content), + ) .route("/rare.txt", get(Self::rare_txt)) .route("/rune/:rune", get(Self::rune)) .route("/runes", get(Self::runes)) @@ -2266,6 +2270,35 @@ impl Server { }) } + async fn sat_inscription_at_index_content( + Extension(index): Extension>, + Extension(server_config): Extension>, + Path((DeserializeFromStr(sat), inscription_index)): Path<(DeserializeFromStr, isize)>, + accept_encoding: AcceptEncoding, + ) -> ServerResult { + task::block_in_place(|| { + if !index.has_sat_index() { + return Err(ServerError::NotFound( + "this server has no sat index".to_string(), + )); + } + + let inscription_id = index.get_inscription_id_by_sat_indexed(sat, inscription_index)?; + + if let Some(id) = inscription_id { + if let Some(inscription) = index.get_inscription_by_id(id)? { + return Ok( + Self::content_response(inscription, accept_encoding, &server_config)? + .ok_or_not_found(|| format!("inscription {id} content"))? + .into_response(), + ); + } + } + + Err(ServerError::NotFound("inscription not found".to_string())) + }) + } + async fn redirect_http_to_https( Extension(mut destination): Extension, uri: Uri, @@ -7420,4 +7453,76 @@ next "output 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef:123 not found", ); } + + #[test] + fn sat_inscription_at_index_content_endpoint() { + let server = TestServer::builder() + .index_sats() + .chain(Chain::Regtest) // Add chain + .build(); + + server.mine_blocks(1); + + // Create first inscription + let first_txid = server.core.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, inscription("text/plain;charset=utf-8", "hello").to_witness())], + ..default() + }); + + server.mine_blocks(1); + + // Get first inscription info... + let first_inscription_id = InscriptionId { txid: first_txid, index: 0 }; + println!("First inscription ID: {}", first_inscription_id); + let first_inscription = server + .get_json::(format!("/r/inscription/{first_inscription_id}")); + println!("First inscription: {:?}", first_inscription); + let sat = first_inscription.sat.expect("inscription should have a sat number"); + println!("Sat number: {}", sat); + println!("Satpoint: {:?}", first_inscription.satpoint); + + // Reinscribe on the same sat by using the output containing first inscription + let second_txid = server.core.broadcast_tx(TransactionTemplate { + inputs: &[( + 2, + 1, + first_inscription.satpoint.outpoint.vout.try_into().unwrap(), + inscription("text/plain;charset=utf-8", "alwaysbebuilding.bitmap 👷🏗️🟧🌌").to_witness(), + )], + ..default() + }); + + server.mine_blocks(1); + println!("Second inscription txid: {}", second_txid); + + // Test fetching the content - should get the most recent inscription + server.assert_response( + format!("/r/sat/{}/at/-1/content", sat), + StatusCode::OK, + "alwaysbebuilding.bitmap 👷🏗️🟧🌌", + ); + + // Test fetching the first inscription + server.assert_response( + format!("/r/sat/{}/at/0/content", sat), + StatusCode::OK, + "hello", + ); + + // Test error when sat index is disabled + let server = TestServer::new(); + server.assert_response( + format!("/r/sat/{}/at/-1/content", sat), + StatusCode::NOT_FOUND, + "this server has no sat index" + ); + + // Test error for non-existent inscription + let server = TestServer::builder().index_sats().build(); + server.assert_response( + format!("/r/sat/{}/at/999/content", sat), + StatusCode::NOT_FOUND, + "inscription not found" + ); + } } From 972a866928fd0ef78e068e467b634fde6fe41b92 Mon Sep 17 00:00:00 2001 From: Astral Arkitekt Date: Thu, 28 Nov 2024 19:05:36 -0600 Subject: [PATCH 2/6] Moved the details in doc to proper section of recursion.md --- docs/src/inscriptions/recursion.md | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/src/inscriptions/recursion.md b/docs/src/inscriptions/recursion.md index 4c8fae72f7..e30c77cfdf 100644 --- a/docs/src/inscriptions/recursion.md +++ b/docs/src/inscriptions/recursion.md @@ -3370,26 +3370,6 @@ curl -s -H "Accept: application/json" \ ``` -  -  - -Note: `` only allows the actual number of a sat no other sat -notations like degree, percentile or decimal. We may expand to allow those in -the future. - -Responses from most of the above recursive endpoints are JSON. For backwards -compatibility, some endpoints are supported which only return -plain-text responses. - -- `/blockheight`: latest block height. -- `/blockhash`: latest block hash. -- `/blockhash/`: block hash at given block height. -- `/blocktime`: UNIX time stamp of latest block. - - -See -[examples](examples.md#recursion) for on-chain examples of inscriptions that feature this functionality. -
GET @@ -3414,3 +3394,23 @@ Returns the appropriate mime-type and content of the last inscription created on alwaysbebuilding.bitmap ```
+ +  +  + +Note: `` only allows the actual number of a sat no other sat +notations like degree, percentile or decimal. We may expand to allow those in +the future. + +Responses from most of the above recursive endpoints are JSON. For backwards +compatibility, some endpoints are supported which only return +plain-text responses. + +- `/blockheight`: latest block height. +- `/blockhash`: latest block hash. +- `/blockhash/`: block hash at given block height. +- `/blocktime`: UNIX time stamp of latest block. + + +See +[examples](examples.md#recursion) for on-chain examples of inscriptions that feature this functionality. From 3fb94b4d492a573c89ca7f6c65e5e87a4888356a Mon Sep 17 00:00:00 2001 From: Astral Arkitekt Date: Thu, 28 Nov 2024 19:07:19 -0600 Subject: [PATCH 3/6] Moved the details in doc to proper section of recursion.md --- docs/src/inscriptions/recursion.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/inscriptions/recursion.md b/docs/src/inscriptions/recursion.md index e30c77cfdf..83c6e5cf02 100644 --- a/docs/src/inscriptions/recursion.md +++ b/docs/src/inscriptions/recursion.md @@ -3391,7 +3391,7 @@ curl -s -H "Accept: application/json" \ Returns the appropriate mime-type and content of the last inscription created on the queried satoshi. ``` -alwaysbebuilding.bitmap +alwaysbebuilding.bitmap 👷🏗️🟧🌌 ``` From fef31fb61a3b1c9769600069fb06500eba3e8a22 Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Fri, 24 Jan 2025 13:46:20 -0800 Subject: [PATCH 4/6] Use Self::content --- src/subcommand/server.rs | 114 ++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 61 deletions(-) diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 68684a5699..b03d4819b3 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -2242,9 +2242,7 @@ impl Server { ) -> ServerResult> { task::block_in_place(|| { if !index.has_sat_index() { - return Err(ServerError::NotFound( - "this server has no sat index".to_string(), - )); + return Err(ServerError::NotFound("this server has no sat index".into())); } let (ids, more) = index.get_inscription_ids_by_sat_paginated(Sat(sat), 100, page)?; @@ -2271,32 +2269,30 @@ impl Server { } async fn sat_inscription_at_index_content( - Extension(index): Extension>, - Extension(server_config): Extension>, + index: Extension>, + settings: Extension>, + server_config: Extension>, Path((DeserializeFromStr(sat), inscription_index)): Path<(DeserializeFromStr, isize)>, accept_encoding: AcceptEncoding, ) -> ServerResult { - task::block_in_place(|| { + let inscription_id = task::block_in_place(|| { if !index.has_sat_index() { - return Err(ServerError::NotFound( - "this server has no sat index".to_string(), - )); - } - - let inscription_id = index.get_inscription_id_by_sat_indexed(sat, inscription_index)?; - - if let Some(id) = inscription_id { - if let Some(inscription) = index.get_inscription_by_id(id)? { - return Ok( - Self::content_response(inscription, accept_encoding, &server_config)? - .ok_or_not_found(|| format!("inscription {id} content"))? - .into_response(), - ); - } + return Err(ServerError::NotFound("this server has no sat index".into())); } - Err(ServerError::NotFound("inscription not found".to_string())) - }) + index + .get_inscription_id_by_sat_indexed(sat, inscription_index)? + .ok_or_not_found(|| format!("inscription on sat {sat}")) + })?; + + Self::content( + index, + settings, + server_config, + Path(inscription_id), + accept_encoding, + ) + .await } async fn redirect_http_to_https( @@ -7458,71 +7454,67 @@ next fn sat_inscription_at_index_content_endpoint() { let server = TestServer::builder() .index_sats() - .chain(Chain::Regtest) // Add chain + .chain(Chain::Regtest) .build(); server.mine_blocks(1); - // Create first inscription let first_txid = server.core.broadcast_tx(TransactionTemplate { - inputs: &[(1, 0, 0, inscription("text/plain;charset=utf-8", "hello").to_witness())], + inputs: &[( + 1, + 0, + 0, + inscription("text/plain;charset=utf-8", "foo").to_witness(), + )], ..default() }); server.mine_blocks(1); - // Get first inscription info... - let first_inscription_id = InscriptionId { txid: first_txid, index: 0 }; - println!("First inscription ID: {}", first_inscription_id); + let first_inscription_id = InscriptionId { + txid: first_txid, + index: 0, + }; + let first_inscription = server .get_json::(format!("/r/inscription/{first_inscription_id}")); - println!("First inscription: {:?}", first_inscription); - let sat = first_inscription.sat.expect("inscription should have a sat number"); - println!("Sat number: {}", sat); - println!("Satpoint: {:?}", first_inscription.satpoint); - // Reinscribe on the same sat by using the output containing first inscription - let second_txid = server.core.broadcast_tx(TransactionTemplate { + let sat = first_inscription.sat.unwrap(); + + server.assert_response(format!("/r/sat/{sat}/at/0/content"), StatusCode::OK, "foo"); + + server.assert_response(format!("/r/sat/{sat}/at/-1/content"), StatusCode::OK, "foo"); + + server.core.broadcast_tx(TransactionTemplate { inputs: &[( 2, 1, first_inscription.satpoint.outpoint.vout.try_into().unwrap(), - inscription("text/plain;charset=utf-8", "alwaysbebuilding.bitmap 👷🏗️🟧🌌").to_witness(), + inscription("text/plain;charset=utf-8", "bar").to_witness(), )], ..default() }); server.mine_blocks(1); - println!("Second inscription txid: {}", second_txid); - // Test fetching the content - should get the most recent inscription + server.assert_response(format!("/r/sat/{sat}/at/0/content"), StatusCode::OK, "foo"); + + server.assert_response(format!("/r/sat/{sat}/at/1/content"), StatusCode::OK, "bar"); + + server.assert_response(format!("/r/sat/{sat}/at/-1/content"), StatusCode::OK, "bar"); + server.assert_response( - format!("/r/sat/{}/at/-1/content", sat), - StatusCode::OK, - "alwaysbebuilding.bitmap 👷🏗️🟧🌌", + format!("/r/sat/0/at/999/content"), + StatusCode::NOT_FOUND, + "inscription on sat 0 not found", ); - // Test fetching the first inscription + let server = TestServer::new(); + server.assert_response( - format!("/r/sat/{}/at/0/content", sat), - StatusCode::OK, - "hello", + format!("/r/sat/{sat}/at/-1/content"), + StatusCode::NOT_FOUND, + "this server has no sat index", ); - - // Test error when sat index is disabled - let server = TestServer::new(); - server.assert_response( - format!("/r/sat/{}/at/-1/content", sat), - StatusCode::NOT_FOUND, - "this server has no sat index" - ); - - // Test error for non-existent inscription - let server = TestServer::builder().index_sats().build(); - server.assert_response( - format!("/r/sat/{}/at/999/content", sat), - StatusCode::NOT_FOUND, - "inscription not found" - ); } } From ffed29310bcf8387798e82023ca3656ba113de3b Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Fri, 24 Jan 2025 14:01:39 -0800 Subject: [PATCH 5/6] Modify --- docs/src/inscriptions/recursion.md | 4 +++- src/subcommand/server.rs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/src/inscriptions/recursion.md b/docs/src/inscriptions/recursion.md index 1e010d3073..7821476864 100644 --- a/docs/src/inscriptions/recursion.md +++ b/docs/src/inscriptions/recursion.md @@ -3354,7 +3354,9 @@ curl -s -H "Accept: application/json" \ ### Description -The inscription id at `` of all inscriptions on a sat. `` may be a negative number to index from the back. `0` being the first and `-1` being the most recent for example. Requires index with `--index-sats` flag. +The inscription id at `` of all inscriptions on a sat. `` may be +a negative number to index from the back. `0` being the first and `-1` being +the most recent for example. Requires index with `--index-sats` flag. ### Example diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 716a96c385..ee97eabe32 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -7685,7 +7685,7 @@ next server.assert_response(format!("/r/sat/{sat}/at/-1/content"), StatusCode::OK, "bar"); server.assert_response( - format!("/r/sat/0/at/999/content"), + "/r/sat/0/at/0/content", StatusCode::NOT_FOUND, "inscription on sat 0 not found", ); @@ -7693,7 +7693,7 @@ next let server = TestServer::new(); server.assert_response( - format!("/r/sat/{sat}/at/-1/content"), + "/r/sat/0/at/0/content", StatusCode::NOT_FOUND, "this server has no sat index", ); From eaef18249552a5bfdf0e337bac3a339fa600cdc4 Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Fri, 24 Jan 2025 14:08:21 -0800 Subject: [PATCH 6/6] Use new notation --- src/subcommand/server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index ee97eabe32..1d410f336f 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -275,7 +275,7 @@ impl Server { get(Self::sat_inscription_at_index), ) .route( - "/r/sat/:sat_number/at/:index/content", + "/r/sat/{sat_number}/at/{index}/content", get(Self::sat_inscription_at_index_content), ) .route("/r/utxo/{outpoint}", get(Self::utxo_recursive))