• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stacks-network / stacks-core / 25903914664-1

15 May 2026 06:28AM UTC coverage: 47.122% (-38.8%) from 85.959%
25903914664-1

Pull #7199

github

94e391
web-flow
Merge 109f2828c into 1c7b8e6ac
Pull Request #7199: Feat: L1 and L2 early unlocks, updating signer

103343 of 219309 relevant lines covered (47.12%)

12880462.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

16.13
/stackslib/src/net/api/getstackerdbmetadata.rs
1
// Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation
2
// Copyright (C) 2020-2023 Stacks Open Internet Foundation
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

17
use clarity::vm::representations::{CONTRACT_NAME_REGEX_STRING, STANDARD_PRINCIPAL_REGEX_STRING};
18
use clarity::vm::types::QualifiedContractIdentifier;
19
use libstackerdb::SlotMetadata;
20
use regex::{Captures, Regex};
21
use serde_json;
22
use stacks_common::types::net::PeerHost;
23

24
use crate::net::http::{
25
    parse_json, Error, HttpNotFound, HttpRequest, HttpRequestContents, HttpRequestPreamble,
26
    HttpResponse, HttpResponseContents, HttpResponsePayload, HttpResponsePreamble,
27
};
28
use crate::net::httpcore::{request, RPCRequestHandler, StacksHttpRequest, StacksHttpResponse};
29
use crate::net::{Error as NetError, StacksNodeState};
30

31
#[derive(Clone)]
32
pub struct RPCGetStackerDBMetadataRequestHandler {
33
    pub contract_identifier: Option<QualifiedContractIdentifier>,
34
}
35
impl RPCGetStackerDBMetadataRequestHandler {
36
    pub fn new() -> Self {
1,059,023✔
37
        Self {
1,059,023✔
38
            contract_identifier: None,
1,059,023✔
39
        }
1,059,023✔
40
    }
1,059,023✔
41
}
42

43
/// Decode the HTTP request
44
impl HttpRequest for RPCGetStackerDBMetadataRequestHandler {
45
    fn verb(&self) -> &'static str {
1,059,023✔
46
        "GET"
1,059,023✔
47
    }
1,059,023✔
48

49
    fn path_regex(&self) -> Regex {
2,118,046✔
50
        Regex::new(&format!(
2,118,046✔
51
            r#"^/v2/stackerdb/(?P<address>{})/(?P<contract>{})$"#,
2,118,046✔
52
            *STANDARD_PRINCIPAL_REGEX_STRING, *CONTRACT_NAME_REGEX_STRING
2,118,046✔
53
        ))
2,118,046✔
54
        .unwrap()
2,118,046✔
55
    }
2,118,046✔
56

57
    fn metrics_identifier(&self) -> &str {
×
58
        "/v2/stackerdb/:principal/:contract_name"
×
59
    }
×
60

61
    /// Try to decode this request.
62
    /// There's nothing to load here, so just make sure the request is well-formed.
63
    fn try_parse_request(
×
64
        &mut self,
×
65
        preamble: &HttpRequestPreamble,
×
66
        captures: &Captures,
×
67
        query: Option<&str>,
×
68
        _body: &[u8],
×
69
    ) -> Result<HttpRequestContents, Error> {
×
70
        if preamble.get_content_length() != 0 {
×
71
            return Err(Error::DecodeError(
×
72
                "Invalid Http request: expected 0-length body".to_string(),
×
73
            ));
×
74
        }
×
75

76
        let contract_identifier = request::get_contract_address(captures, "address", "contract")?;
×
77
        self.contract_identifier = Some(contract_identifier);
×
78

79
        Ok(HttpRequestContents::new().query_string(query))
×
80
    }
×
81
}
82

83
impl RPCRequestHandler for RPCGetStackerDBMetadataRequestHandler {
84
    /// Reset internal state
85
    fn restart(&mut self) {
×
86
        self.contract_identifier = None;
×
87
    }
×
88

89
    /// Make the response
90
    fn try_handle_request(
×
91
        &mut self,
×
92
        preamble: HttpRequestPreamble,
×
93
        _contents: HttpRequestContents,
×
94
        node: &mut StacksNodeState,
×
95
    ) -> Result<(HttpResponsePreamble, HttpResponseContents), NetError> {
×
96
        let contract_identifier = self
×
97
            .contract_identifier
×
98
            .take()
×
99
            .ok_or(NetError::SendError("`contract_identifier` not set".into()))?;
×
100

101
        let metadata_resp =
×
102
            node.with_node_state(|network, _sortdb, _chainstate, _mempool, _rpc_args| {
×
103
                network
×
104
                    .get_stackerdbs()
×
105
                    .get_db_slot_metadata(&contract_identifier)
×
106
                    .map_err(|_e| {
×
107
                        StacksHttpResponse::new_error(
×
108
                            &preamble,
×
109
                            &HttpNotFound::new("StackerDB contract not found".to_string()),
×
110
                        )
111
                    })
×
112
            });
×
113

114
        let metadata_resp = match metadata_resp {
×
115
            Ok(metadata) => metadata,
×
116
            Err(response) => {
×
117
                return response.try_into_contents().map_err(NetError::from);
×
118
            }
119
        };
120

121
        let preamble = HttpResponsePreamble::ok_json(&preamble);
×
122
        let body = HttpResponseContents::try_from_json(&metadata_resp)?;
×
123
        Ok((preamble, body))
×
124
    }
×
125
}
126

127
/// Decode the HTTP response
128
impl HttpResponse for RPCGetStackerDBMetadataRequestHandler {
129
    /// Decode this response from a byte stream.  This is called by the client to decode this
130
    /// message
131
    fn try_parse_response(
×
132
        &self,
×
133
        preamble: &HttpResponsePreamble,
×
134
        body: &[u8],
×
135
    ) -> Result<HttpResponsePayload, Error> {
×
136
        let metadata: Vec<SlotMetadata> = parse_json(preamble, body)?;
×
137
        Ok(HttpResponsePayload::try_from_json(metadata)?)
×
138
    }
×
139
}
140

141
impl StacksHttpRequest {
142
    pub fn new_get_stackerdb_metadata(
×
143
        host: PeerHost,
×
144
        stackerdb_contract_id: QualifiedContractIdentifier,
×
145
    ) -> StacksHttpRequest {
×
146
        StacksHttpRequest::new_for_peer(
×
147
            host,
×
148
            "GET".into(),
×
149
            format!(
×
150
                "/v2/stackerdb/{}/{}",
151
                &stackerdb_contract_id.issuer, &stackerdb_contract_id.name
×
152
            ),
153
            HttpRequestContents::new(),
×
154
        )
155
        .expect("FATAL: failed to construct request from infallible data")
×
156
    }
×
157
}
158

159
impl StacksHttpResponse {
160
    /// Decode an HTTP response into a block.
161
    /// If it fails, return Self::Error(..)
162
    pub fn decode_stackerdb_metadata(self) -> Result<Vec<SlotMetadata>, NetError> {
×
163
        let contents = self.get_http_payload_ok()?;
×
164
        let contents_json: serde_json::Value = contents.try_into()?;
×
165
        let resp: Vec<SlotMetadata> = serde_json::from_value(contents_json)
×
166
            .map_err(|_e| NetError::DeserializeError("Failed to load from JSON".to_string()))?;
×
167
        Ok(resp)
×
168
    }
×
169
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc