Skip to content

Commit

Permalink
Merge pull request #3365 from ProvableHQ/feat/get_mapping_values
Browse files Browse the repository at this point in the history
[Feature] Add REST endpoint to get all items in a mapping
  • Loading branch information
zosorock authored Oct 22, 2024
2 parents d190415 + 0388e68 commit dae2509
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 5 deletions.
1 change: 1 addition & 0 deletions node/rest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ impl<N: Network, C: ConsensusStorage<N>, R: Routing<N>> Rest<N, C, R> {

// All the endpoints before the call to `route_layer` are protected with JWT auth.
.route(&format!("/{network}/node/address"), get(Self::get_node_address))
.route(&format!("/{network}/program/:id/mapping/:name"), get(Self::get_mapping_values))
.route_layer(middleware::from_fn(auth_middleware))

// GET ../block/..
Expand Down
46 changes: 41 additions & 5 deletions node/rest/src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ pub(crate) struct BlockRange {
end: u32,
}

/// The `get_mapping_value` query object.
#[derive(Deserialize, Serialize)]
/// The query object for `get_mapping_value` and `get_mapping_values`.
#[derive(Copy, Clone, Deserialize, Serialize)]
pub(crate) struct Metadata {
metadata: bool,
metadata: Option<bool>,
all: Option<bool>,
}

impl<N: Network, C: ConsensusStorage<N>, R: Routing<N>> Rest<N, C, R> {
Expand Down Expand Up @@ -195,13 +196,13 @@ impl<N: Network, C: ConsensusStorage<N>, R: Routing<N>> Rest<N, C, R> {
pub(crate) async fn get_mapping_value(
State(rest): State<Self>,
Path((id, name, key)): Path<(ProgramID<N>, Identifier<N>, Plaintext<N>)>,
metadata: Option<Query<Metadata>>,
metadata: Query<Metadata>,
) -> Result<ErasedJson, RestError> {
// Retrieve the mapping value.
let mapping_value = rest.ledger.vm().finalize_store().get_value_confirmed(id, name, &key)?;

// Check if metadata is requested and return the value with metadata if so.
if metadata.map(|q| q.metadata).unwrap_or(false) {
if metadata.metadata.unwrap_or(false) {
return Ok(ErasedJson::pretty(json!({
"data": mapping_value,
"height": rest.ledger.latest_height(),
Expand All @@ -212,6 +213,41 @@ impl<N: Network, C: ConsensusStorage<N>, R: Routing<N>> Rest<N, C, R> {
Ok(ErasedJson::pretty(mapping_value))
}

// GET /<network>/program/{programID}/mapping/{mappingName}?all={true}&metadata={true}
pub(crate) async fn get_mapping_values(
State(rest): State<Self>,
Path((id, name)): Path<(ProgramID<N>, Identifier<N>)>,
metadata: Query<Metadata>,
) -> Result<ErasedJson, RestError> {
// Return an error if the `all` query parameter is not set to `true`.
if metadata.all != Some(true) {
return Err(RestError("Invalid query parameter. At this time, 'all=true' must be included".to_string()));
}

// Retrieve the latest height.
let height = rest.ledger.latest_height();

// Retrieve all the mapping values from the mapping.
match tokio::task::spawn_blocking(move || rest.ledger.vm().finalize_store().get_mapping_confirmed(id, name))
.await
{
Ok(Ok(mapping_values)) => {
// Check if metadata is requested and return the mapping with metadata if so.
if metadata.metadata.unwrap_or(false) {
return Ok(ErasedJson::pretty(json!({
"data": mapping_values,
"height": height,
})));
}

// Return the full mapping without metadata.
Ok(ErasedJson::pretty(mapping_values))
}
Ok(Err(err)) => Err(RestError(format!("Unable to read mapping - {err}"))),
Err(err) => Err(RestError(format!("Unable to read mapping - {err}"))),
}
}

// GET /<network>/statePath/{commitment}
pub(crate) async fn get_state_path_for_commitment(
State(rest): State<Self>,
Expand Down

0 comments on commit dae2509

Please sign in to comment.