Skip to main content

dig_node_control_interface/
params.rs

1//! Typed request params for the control methods, each bound to its method + result via
2//! [`ControlCall`](crate::traits::ControlCall).
3//!
4//! One params type per method (even where two methods share the same field shape, e.g. the four
5//! `{ store }` methods) so the compile-time method↔params↔result binding is exact: a caller passes
6//! `PinParams { store }` and the type system yields a [`PinResult`](crate::results::PinResult).
7//! Field names are the exact wire names dig-node reads.
8
9use serde::{Deserialize, Serialize};
10
11use crate::method::ControlMethod;
12use crate::results;
13use crate::traits::ControlCall;
14
15/// Bind a params type to its wire method + typed result.
16macro_rules! control_call {
17    ($ty:ty => $method:expr, $out:ty) => {
18        impl ControlCall for $ty {
19            const METHOD: ControlMethod = $method;
20            type Output = $out;
21        }
22    };
23}
24
25/// Define a no-param call: an empty params struct (serializes to `{}`) bound to its method + result.
26macro_rules! no_params {
27    ($(#[$doc:meta])* $name:ident => $method:expr, $out:ty) => {
28        $(#[$doc])*
29        #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
30        pub struct $name {}
31        control_call!($name => $method, $out);
32    };
33}
34
35no_params!(
36    /// `control.status` params (none).
37    StatusParams => ControlMethod::Status, results::StatusResult
38);
39no_params!(
40    /// `control.config.get` params (none).
41    ConfigGetParams => ControlMethod::ConfigGet, results::ConfigResult
42);
43no_params!(
44    /// `control.cache.get` params (none).
45    CacheGetParams => ControlMethod::CacheGet, results::CacheView
46);
47no_params!(
48    /// `control.cache.clear` params (none).
49    CacheClearParams => ControlMethod::CacheClear, results::CacheClearResult
50);
51no_params!(
52    /// `control.hostedStores.list` params (none).
53    HostedStoresListParams => ControlMethod::HostedStoresList, results::HostedStoresListResult
54);
55no_params!(
56    /// `control.sync.status` params (none).
57    SyncStatusParams => ControlMethod::SyncStatus, results::SyncStatusResult
58);
59no_params!(
60    /// `control.updater.status` params (none). Result is the proxied beacon status.
61    UpdaterStatusParams => ControlMethod::UpdaterStatus, serde_json::Value
62);
63no_params!(
64    /// `control.updater.resume` params (none).
65    UpdaterResumeParams => ControlMethod::UpdaterResume, serde_json::Value
66);
67no_params!(
68    /// `control.updater.checkNow` params (none).
69    UpdaterCheckNowParams => ControlMethod::UpdaterCheckNow, serde_json::Value
70);
71no_params!(
72    /// `control.pairing.list` params (none). Result is the pending + issued-token list.
73    PairingListParams => ControlMethod::PairingList, serde_json::Value
74);
75no_params!(
76    /// `control.peerStatus` params (none). Result is the peer-pool snapshot.
77    PeerStatusParams => ControlMethod::PeerStatus, serde_json::Value
78);
79no_params!(
80    /// `control.listSubscriptions` params (none).
81    ListSubscriptionsParams => ControlMethod::ListSubscriptions, results::ListSubscriptionsResult
82);
83
84/// `control.config.setUpstream` params.
85#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
86pub struct SetUpstreamParams {
87    /// The upstream DIG RPC URL to persist (blank clears the override).
88    pub upstream: String,
89}
90control_call!(SetUpstreamParams => ControlMethod::ConfigSetUpstream, results::SetUpstreamResult);
91
92/// `control.log.setLevel` params.
93#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
94pub struct SetLevelParams {
95    /// An `EnvFilter` directive, e.g. `"debug"` or `"info,dig_node_core=debug"`.
96    pub filter: String,
97}
98control_call!(SetLevelParams => ControlMethod::LogSetLevel, results::SetLevelResult);
99
100/// `control.cache.setCap` params.
101#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
102pub struct SetCapParams {
103    /// The cache size cap in bytes (floored at 64 MiB by the node).
104    pub cap_bytes: u64,
105}
106control_call!(SetCapParams => ControlMethod::CacheSetCap, results::SetCapResult);
107
108/// `control.hostedStores.pin` params.
109#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
110pub struct PinParams {
111    /// A store reference: `storeId` or `storeId:rootHash`.
112    pub store: String,
113}
114control_call!(PinParams => ControlMethod::HostedStoresPin, results::PinResult);
115
116/// `control.hostedStores.unpin` params.
117#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
118pub struct UnpinParams {
119    /// A store reference: `storeId` or `storeId:rootHash`.
120    pub store: String,
121}
122control_call!(UnpinParams => ControlMethod::HostedStoresUnpin, results::UnpinResult);
123
124/// `control.hostedStores.status` params.
125#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
126pub struct HostedStoreStatusParams {
127    /// A store reference: `storeId` or `storeId:rootHash`.
128    pub store: String,
129}
130control_call!(HostedStoreStatusParams => ControlMethod::HostedStoresStatus, results::HostedStoreStatusResult);
131
132/// `control.sync.trigger` params.
133#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
134pub struct SyncTriggerParams {
135    /// A capsule reference: `storeId:rootHash` (a concrete root is required).
136    pub store: String,
137}
138control_call!(SyncTriggerParams => ControlMethod::SyncTrigger, results::SyncTriggerResult);
139
140/// `control.updater.setChannel` params.
141#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
142pub struct SetChannelParams {
143    /// The update channel (`"nightly"` | `"stable"`; the beacon CLI is the sole validator).
144    pub channel: String,
145}
146control_call!(SetChannelParams => ControlMethod::UpdaterSetChannel, serde_json::Value);
147
148/// `control.updater.pause` params.
149#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
150pub struct PauseParams {
151    /// The unix-seconds time to pause until; omit to pause indefinitely.
152    #[serde(skip_serializing_if = "Option::is_none", default)]
153    pub until: Option<u64>,
154}
155control_call!(PauseParams => ControlMethod::UpdaterPause, serde_json::Value);
156
157/// `control.pairing.approve` params.
158#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
159pub struct ApproveParams {
160    /// The pending pairing's id (from `pairing.request`).
161    pub pairing_id: String,
162}
163control_call!(ApproveParams => ControlMethod::PairingApprove, results::PairingApproveResult);
164
165/// `control.pairing.revoke` params.
166#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
167pub struct RevokeParams {
168    /// The short id of the paired token to revoke.
169    pub token_id: String,
170}
171control_call!(RevokeParams => ControlMethod::PairingRevoke, results::PairingRevokeResult);
172
173/// `control.peers.connect` params.
174#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
175pub struct PeersConnectParams {
176    /// A peer address to dial, or an already-connected peer_id to resolve.
177    pub peer: String,
178}
179control_call!(PeersConnectParams => ControlMethod::PeersConnect, results::PeersConnectResult);
180
181/// `control.peers.disconnect` params.
182#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
183pub struct PeersDisconnectParams {
184    /// The peer_id to drop.
185    pub peer: String,
186}
187control_call!(PeersDisconnectParams => ControlMethod::PeersDisconnect, results::PeersDisconnectResult);
188
189/// `control.subscribe` params.
190#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
191pub struct SubscribeParams {
192    /// The store id to subscribe to.
193    pub store_id: String,
194}
195control_call!(SubscribeParams => ControlMethod::Subscribe, results::SubscribeResult);
196
197/// `control.unsubscribe` params.
198#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
199pub struct UnsubscribeParams {
200    /// The store id to stop watching.
201    pub store_id: String,
202}
203control_call!(UnsubscribeParams => ControlMethod::Unsubscribe, results::UnsubscribeResult);
204
205/// `pairing.request` params (OPEN — no token).
206#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
207pub struct RequestParams {
208    /// A human-readable name for the requesting client (shown to the operator).
209    pub client_name: String,
210}
211control_call!(RequestParams => ControlMethod::PairingRequest, results::PairingRequestResult);
212
213/// `pairing.poll` params (OPEN — no token).
214#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
215pub struct PollParams {
216    /// The pairing id to poll.
217    pub pairing_id: String,
218}
219control_call!(PollParams => ControlMethod::PairingPoll, results::PairingPollResult);
220
221#[cfg(test)]
222mod tests {
223    use super::*;
224    use crate::traits::build_request;
225    use serde_json::json;
226
227    #[test]
228    fn no_param_call_serializes_params_to_empty_object() {
229        let req = build_request(1.into(), &StatusParams {});
230        assert_eq!(req.method, "control.status");
231        assert_eq!(req.params, json!({}));
232    }
233
234    #[test]
235    fn data_param_call_carries_its_fields() {
236        let req = build_request(2.into(), &SetCapParams { cap_bytes: 128 });
237        assert_eq!(req.method, "control.cache.setCap");
238        assert_eq!(req.params, json!({ "cap_bytes": 128 }));
239    }
240
241    #[test]
242    fn pause_omits_until_when_indefinite() {
243        assert_eq!(
244            serde_json::to_value(PauseParams { until: None }).unwrap(),
245            json!({})
246        );
247        assert_eq!(
248            serde_json::to_value(PauseParams { until: Some(99) }).unwrap(),
249            json!({ "until": 99 })
250        );
251    }
252
253    #[test]
254    fn method_binding_matches_the_catalog_name() {
255        assert_eq!(
256            SetUpstreamParams::METHOD.name(),
257            "control.config.setUpstream"
258        );
259        assert_eq!(RequestParams::METHOD.name(), "pairing.request");
260        assert_eq!(PollParams::METHOD.name(), "pairing.poll");
261    }
262}