diff --git a/docs/src/inscriptions/recursion.md b/docs/src/inscriptions/recursion.md
index 3944413c54..37f8e80e2e 100644
--- a/docs/src/inscriptions/recursion.md
+++ b/docs/src/inscriptions/recursion.md
@@ -33,10 +33,10 @@ Recursion has a number of interesting use-cases:
## Endpoints
-
+
GET
/content/<INSCRIPTION_ID>
-
+
### Description
The content of the inscription with ``
@@ -50,67 +50,67 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/blockhash
-
+
### Description
-Latest block hash in text.
+Latest block hash.
### Example
```bash
curl -s \
http://0.0.0.0:80/r/blockhash
```
-```text
+```json
"00000000000000000002891b440944e0ce40b37b6ccaa138c280e9edfc319d5d"
```
-
+
GET
/r/blockhash/<HEIGHT>
-
+
### Description
-Block hash at given block height in text.
+Block hash at given block height as JSON string.
### Example
```bash
curl -s \
http://0.0.0.0:80/r/blockhash/840000
```
-```text
+```json
"0000000000000000000320283a032748cef8227873ff4872689bf23f1cda83a5"
```
-
+
GET
/r/blockheight
-
+
### Description
-Latest block height in text.
+Latest block height.
### Example
```bash
curl -s \
http://0.0.0.0:80/r/blockheight
```
-```text
+```json
866393
```
-
+
GET
/r/blockinfo/<QUERY>
-
+
### Description
Block info. `` may be a block height or block hash.
@@ -207,29 +207,29 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/blocktime
-
+
### Description
-UNIX time stamp of latest block in text.
+UNIX time stamp of latest block.
### Example
```bash
curl -s \
http://0.0.0.0:80/r/blocktime
```
-```text
+```json
1729362253
```
-
+
GET
/r/children/<INSCRIPTION_ID>
-
+
### Description
The first 100 child inscription ids.
@@ -350,10 +350,10 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/children/<INSCRIPTION_ID>/<PAGE>
-
+
### Description
The set of 100 child inscription ids on ``.
@@ -474,10 +474,10 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/children/<INSCRIPTION_ID>/inscriptions
-
+
### Description
Details of the first 100 child inscriptions.
@@ -1796,10 +1796,10 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/children/<INSCRIPTION_ID>/inscriptions/<PAGE>
-
+
### Description
Details of the set of 100 child inscriptions on <PAGE>.
@@ -3119,10 +3119,22 @@ curl -s -H "Accept: application/json" \
-
+
+ GET
+ /r/undelegated-content/<INSCRIPTION_ID>
+
+
+### Description
+Undelegated content of an inscription.
+
+
+
+
+
+
GET
/r/inscription/<INSCRIPTION_ID>
-
+
### Description
Information about an inscription.
@@ -3155,10 +3167,10 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/metadata/<INSCRIPTION_ID>
-
+
### Description
JSON string containing the hex-encoded CBOR metadata.
@@ -3174,10 +3186,10 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/parents/<INSCRIPTION_ID>
-
+
### Description
The first 100 parent inscription ids.
@@ -3199,10 +3211,10 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/parents/<INSCRIPTION_ID>/<PAGE>
-
+
### Description
The set of 100 parent inscription ids on ``.
@@ -3222,10 +3234,10 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/sat/<SAT_NUMBER>
-
+
### Description
The first 100 inscription ids on a sat. Requires index with `--index-sats` flag.
@@ -3250,10 +3262,10 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/sat/<SAT_NUMBER>/<PAGE>
-
+
### Description
The set of 100 inscription ids on ``. Requires index with `--index-sats` flag.
@@ -3285,10 +3297,10 @@ curl -s -H "Accept: application/json" \
-
+
GET
/r/sat/<SAT_NUMBER>/at/<INDEX>
-
+
### 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.
diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs
index 8cc7763f57..d711bd7761 100644
--- a/src/subcommand/server.rs
+++ b/src/subcommand/server.rs
@@ -236,6 +236,10 @@ impl Server {
"/r/children/:inscription_id/inscriptions/:page",
get(Self::child_inscriptions_recursive_paginated),
)
+ .route(
+ "/r/undelegated-content/:inscription_id",
+ get(Self::undelegated_content),
+ )
.route("/r/metadata/:inscription_id", get(Self::metadata))
.route("/r/parents/:inscription_id", get(Self::parents_recursive))
.route(
@@ -1467,6 +1471,30 @@ impl Server {
})
}
+ async fn undelegated_content(
+ Extension(index): Extension>,
+ Extension(settings): Extension>,
+ Extension(server_config): Extension>,
+ Path(inscription_id): Path,
+ accept_encoding: AcceptEncoding,
+ ) -> ServerResult {
+ task::block_in_place(|| {
+ if settings.is_hidden(inscription_id) {
+ return Ok(PreviewUnknownHtml.into_response());
+ }
+
+ let inscription = index
+ .get_inscription_by_id(inscription_id)?
+ .ok_or_not_found(|| format!("inscription {inscription_id}"))?;
+
+ Ok(
+ Self::content_response(inscription, accept_encoding, &server_config)?
+ .ok_or_not_found(|| format!("inscription {inscription_id} content"))?
+ .into_response(),
+ )
+ })
+ }
+
fn content_response(
inscription: Inscription,
accept_encoding: AcceptEncoding,
@@ -6576,6 +6604,81 @@ next
);
}
+ #[test]
+ fn undelegated_content() {
+ let server = TestServer::builder().chain(Chain::Regtest).build();
+
+ server.mine_blocks(1);
+
+ let delegate = Inscription {
+ content_type: Some("text/plain".into()),
+ body: Some("foo".into()),
+ ..default()
+ };
+
+ let delegate_txid = server.core.broadcast_tx(TransactionTemplate {
+ inputs: &[(1, 0, 0, delegate.to_witness())],
+ ..default()
+ });
+
+ let delegate_id = InscriptionId {
+ txid: delegate_txid,
+ index: 0,
+ };
+
+ server.mine_blocks(1);
+
+ let inscription = Inscription {
+ content_type: Some("text/plain".into()),
+ body: Some("bar".into()),
+ delegate: Some(delegate_id.value()),
+ ..default()
+ };
+
+ let txid = server.core.broadcast_tx(TransactionTemplate {
+ inputs: &[(2, 0, 0, inscription.to_witness())],
+ ..default()
+ });
+
+ server.mine_blocks(1);
+
+ let id = InscriptionId { txid, index: 0 };
+
+ server.assert_response(
+ format!("/r/undelegated-content/{id}"),
+ StatusCode::OK,
+ "bar",
+ );
+
+ server.assert_response(format!("/content/{id}"), StatusCode::OK, "foo");
+
+ // Test normal inscription without delegate
+ let normal_inscription = Inscription {
+ content_type: Some("text/plain".into()),
+ body: Some("baz".into()),
+ ..default()
+ };
+
+ let normal_txid = server.core.broadcast_tx(TransactionTemplate {
+ inputs: &[(3, 0, 0, normal_inscription.to_witness())],
+ ..default()
+ });
+
+ server.mine_blocks(1);
+
+ let normal_id = InscriptionId {
+ txid: normal_txid,
+ index: 0,
+ };
+
+ server.assert_response(
+ format!("/r/undelegated-content/{normal_id}"),
+ StatusCode::OK,
+ "baz",
+ );
+ server.assert_response(format!("/content/{normal_id}"), StatusCode::OK, "baz");
+ }
+
#[test]
fn content_proxy() {
let server = TestServer::builder().chain(Chain::Regtest).build();