Skip to content

Commit 6875774

Browse files
authored
Merge pull request #4180 from ProvableHQ/copilot/add-block-height-to-query-response
Add block height and block hash to transaction query responses via `?metadata=true`
2 parents 669dccd + b85a8e5 commit 6875774

1 file changed

Lines changed: 42 additions & 4 deletions

File tree

node/rest/src/routes.rs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ pub(crate) struct Commitments {
9191
commitments: Vec<String>,
9292
}
9393

94+
/// The return value for a transaction metadata query.
95+
#[skip_serializing_none]
96+
#[derive(Serialize)]
97+
pub(crate) struct TransactionWithMetadata<T: Serialize, N: Network> {
98+
transaction: T,
99+
block_hash: Option<N::BlockHash>,
100+
block_height: Option<u32>,
101+
}
102+
94103
/// The return value for a `sync_status` query.
95104
#[skip_serializing_none]
96105
#[derive(Copy, Clone, Serialize)]
@@ -292,25 +301,54 @@ impl<N: Network, C: ConsensusStorage<N>, R: Routing<N>> Rest<N, C, R> {
292301
}
293302

294303
/// GET /<network>/transaction/{transactionID}
304+
/// GET /<network>/transaction/{transactionID}?metadata={true}
295305
pub(crate) async fn get_transaction(
296306
State(rest): State<Self>,
297307
Path(tx_id): Path<N::TransactionID>,
308+
metadata: Query<Metadata>,
298309
) -> Result<ErasedJson, RestError> {
299310
// Ledger returns a generic anyhow::Error, so checking the message is the only way to parse it.
300-
Ok(ErasedJson::pretty(rest.ledger.get_transaction(tx_id).map_err(|err| {
311+
let transaction = rest.ledger.get_transaction(tx_id).map_err(|err| {
301312
if err.to_string().contains("Missing") { RestError::not_found(err) } else { RestError::from(err) }
302-
})?))
313+
})?;
314+
// Check if metadata is requested and return the transaction with metadata if so.
315+
if metadata.metadata.unwrap_or(false) {
316+
// Get the block hash and height for the transaction, if it exists.
317+
let block_hash = rest.ledger.find_block_hash(&tx_id).ok().flatten();
318+
let block_height = block_hash.and_then(|hash| rest.ledger.get_height(&hash).ok());
319+
Ok(ErasedJson::pretty(TransactionWithMetadata::<_, N> { transaction, block_hash, block_height }))
320+
} else {
321+
Ok(ErasedJson::pretty(transaction))
322+
}
303323
}
304324

305325
/// GET /<network>/transaction/confirmed/{transactionID}
326+
/// GET /<network>/transaction/confirmed/{transactionID}?metadata={true}
306327
pub(crate) async fn get_confirmed_transaction(
307328
State(rest): State<Self>,
308329
Path(tx_id): Path<N::TransactionID>,
330+
metadata: Query<Metadata>,
309331
) -> Result<ErasedJson, RestError> {
310332
// Ledger returns a generic anyhow::Error, so checking the message is the only way to parse it.
311-
Ok(ErasedJson::pretty(rest.ledger.get_confirmed_transaction(tx_id).map_err(|err| {
333+
let transaction = rest.ledger.get_confirmed_transaction(tx_id).map_err(|err| {
312334
if err.to_string().contains("Missing") { RestError::not_found(err) } else { RestError::from(err) }
313-
})?))
335+
})?;
336+
// Check if metadata is requested and return the transaction with metadata if so.
337+
if metadata.metadata.unwrap_or(false) {
338+
// Get the block hash and height for the confirmed transaction.
339+
let block_hash = rest
340+
.ledger
341+
.find_block_hash(&tx_id)?
342+
.ok_or_else(|| anyhow!("Block hash not found for transaction {tx_id}"))?;
343+
let block_height = rest.ledger.get_height(&block_hash)?;
344+
Ok(ErasedJson::pretty(TransactionWithMetadata::<_, N> {
345+
transaction,
346+
block_hash: Some(block_hash),
347+
block_height: Some(block_height),
348+
}))
349+
} else {
350+
Ok(ErasedJson::pretty(transaction))
351+
}
314352
}
315353

316354
/// GET /<network>/transaction/unconfirmed/{transactionID}

0 commit comments

Comments
 (0)