Skip to content

Commit 2ac7ccd

Browse files
fix(ssv): send SSV node operator ID as numeric uint64 (#474)
Co-authored-by: Jason Vranek <jasonvranek@gmail.com>
1 parent 952eeec commit 2ac7ccd

1 file changed

Lines changed: 28 additions & 1 deletion

File tree

crates/common/src/interop/ssv/utils.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@ pub async fn request_ssv_pubkeys_from_ssv_node(
1717
http_timeout: Duration,
1818
) -> eyre::Result<SSVNodeResponse> {
1919
let client = reqwest::ClientBuilder::new().timeout(http_timeout).build()?;
20+
// The SSV node API expects operator IDs as numeric (uint64) values. Serializing
21+
// the U256 directly emits a JSON string, which the node rejects with a 400,
22+
// so narrow it to a u64 first.
23+
let operator_id = u64::try_from(node_operator_id)
24+
.map_err(|e| eyre::eyre!("SSV node operator ID does not fit in u64: {e}"))?;
2025
let body = json!({
21-
"operators": [node_operator_id]
26+
"operators": [operator_id]
2227
});
2328
let response = client.get(url).json(&body).send().await.map_err(|e| {
2429
if e.is_timeout() {
@@ -51,3 +56,25 @@ pub async fn request_ssv_pubkeys_from_public_api(
5156
serde_json::from_slice::<SSVPublicResponse>(&body_bytes)
5257
.wrap_err("failed to parse SSV response")
5358
}
59+
60+
#[cfg(test)]
61+
mod tests {
62+
use alloy::primitives::U256;
63+
use serde_json::json;
64+
65+
#[test]
66+
fn ssv_node_request_serializes_operator_as_number() {
67+
let node_operator_id = U256::from(100u64);
68+
69+
// Regression guard: serializing the U256 directly emits a (hex) JSON string,
70+
// which the SSV node rejects ("cannot unmarshal string into ...
71+
// uint64").
72+
let stringy = serde_json::to_string(&json!({ "operators": [node_operator_id] })).unwrap();
73+
assert_eq!(stringy, r#"{"operators":["0x64"]}"#);
74+
75+
// The fix narrows to u64 so the operator ID is emitted as a numeric value.
76+
let operator_id = u64::try_from(node_operator_id).unwrap();
77+
let numeric = serde_json::to_string(&json!({ "operators": [operator_id] })).unwrap();
78+
assert_eq!(numeric, r#"{"operators":[100]}"#);
79+
}
80+
}

0 commit comments

Comments
 (0)