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

Add sat at index content endpoint (/r/sat/:sat_number/at/:index/content) #4113

Merged
31 changes: 30 additions & 1 deletion docs/src/inscriptions/recursion.md
Original file line number Diff line number Diff line change
Expand Up @@ -3354,7 +3354,9 @@ curl -s -H "Accept: application/json" \

### Description

The inscription id at `<INDEX>` of all inscriptions on a sat. `<INDEX>` 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 `<INDEX>` of all inscriptions on a sat. `<INDEX>` 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

Expand All @@ -3370,6 +3372,33 @@ curl -s -H "Accept: application/json" \
```
</details>

<details>
<summary>
<code>GET</code>
<code><b>/r/sat/&lt;SAT_NUMBER&gt;/at/&lt;INDEX&gt;/content</b></code>
</summary>

### Description

The content of the inscription at `<INDEX>` on a sat. `<INDEX>` may be a
negative number to index from the back. `0` being the first and `-1` being the
most recent. Requires index with `--index-sats` flag.

### Example

Fetch the content of the most recently created inscription on sat 289488340427831.

```bash
curl -s -H "Accept: application/json" \
http://0.0.0.0:80/r/sat/289488340427831/at/-1/content
```

```
Hello, world!
```

</details>

<details>
<summary>
<code>GET</code>
Expand Down
103 changes: 100 additions & 3 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,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("/r/utxo/{outpoint}", get(Self::utxo_recursive))
.route("/rare.txt", get(Self::rare_txt))
.route("/rune/{rune}", get(Self::rune))
Expand Down Expand Up @@ -2287,9 +2291,7 @@ impl Server {
) -> ServerResult<Json<api::SatInscriptions>> {
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)?;
Expand All @@ -2315,6 +2317,33 @@ impl Server {
})
}

async fn sat_inscription_at_index_content(
index: Extension<Arc<Index>>,
settings: Extension<Arc<Settings>>,
server_config: Extension<Arc<ServerConfig>>,
Path((DeserializeFromStr(sat), inscription_index)): Path<(DeserializeFromStr<Sat>, isize)>,
accept_encoding: AcceptEncoding,
) -> ServerResult {
let inscription_id = task::block_in_place(|| {
if !index.has_sat_index() {
return Err(ServerError::NotFound("this server has no sat index".into()));
}

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(
Extension(mut destination): Extension<String>,
uri: Uri,
Expand Down Expand Up @@ -7601,4 +7630,72 @@ next
"output 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef:123 not found",
);
}

#[test]
fn sat_inscription_at_index_content_endpoint() {
let server = TestServer::builder()
.index_sats()
.chain(Chain::Regtest)
.build();

server.mine_blocks(1);

let first_txid = server.core.broadcast_tx(TransactionTemplate {
inputs: &[(
1,
0,
0,
inscription("text/plain;charset=utf-8", "foo").to_witness(),
)],
..default()
});

server.mine_blocks(1);

let first_inscription_id = InscriptionId {
txid: first_txid,
index: 0,
};

let first_inscription = server
.get_json::<api::InscriptionRecursive>(format!("/r/inscription/{first_inscription_id}"));

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", "bar").to_witness(),
)],
..default()
});

server.mine_blocks(1);

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(
"/r/sat/0/at/0/content",
StatusCode::NOT_FOUND,
"inscription on sat 0 not found",
);

let server = TestServer::new();

server.assert_response(
"/r/sat/0/at/0/content",
StatusCode::NOT_FOUND,
"this server has no sat index",
);
}
}
Loading