Skip to main content

deribit_http/model/
api_key.rs

1//! API key management models and types
2
3use serde::{Deserialize, Serialize};
4use serde_with::skip_serializing_none;
5
6/// API key information returned by API key management endpoints.
7///
8/// Contains all details about an API key including credentials,
9/// permissions, and configuration.
10#[skip_serializing_none]
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct ApiKeyInfo {
13    /// Unique identifier for the API key
14    pub id: u64,
15    /// Client identifier used for authentication
16    pub client_id: String,
17    /// Client secret or MD5 fingerprint of public key used for authentication
18    pub client_secret: String,
19    /// API key name that can be displayed in transaction log
20    pub name: String,
21    /// Describes maximal access for tokens generated with this key.
22    ///
23    /// Possible values include combinations of:
24    /// - `trade:[read, read_write, none]`
25    /// - `wallet:[read, read_write, none]`
26    /// - `account:[read, read_write, none]`
27    /// - `block_trade:[read, read_write, none]`
28    /// - `block_rfq:[read, read_write, none]`
29    pub max_scope: String,
30    /// Whether the API key is enabled and can be used for authentication
31    pub enabled: bool,
32    /// Whether this API key is the default (deprecated, will be removed)
33    pub default: bool,
34    /// Timestamp when the key was created or last modified, in milliseconds since Unix epoch
35    pub timestamp: u64,
36    /// List of enabled advanced on-key features.
37    ///
38    /// Available options:
39    /// - `restricted_block_trades`: Limit block_trade read scope to trades made with this key
40    /// - `block_trade_approval`: Block trades require additional user approval
41    #[serde(default)]
42    pub enabled_features: Vec<String>,
43    /// List of IP addresses whitelisted for this key
44    #[serde(default)]
45    pub ip_whitelist: Option<Vec<String>>,
46    /// PEM encoded public key (Ed25519/RSA) used for asymmetric signatures
47    pub public_key: Option<String>,
48}
49
50/// Request parameters for creating a new API key.
51///
52/// # Example
53///
54/// ```rust
55/// use deribit_http::model::CreateApiKeyRequest;
56///
57/// let request = CreateApiKeyRequest {
58///     max_scope: "account:read trade:read_write".to_string(),
59///     name: Some("my_trading_key".to_string()),
60///     ..Default::default()
61/// };
62/// ```
63#[derive(Debug, Clone, Default)]
64pub struct CreateApiKeyRequest {
65    /// Describes maximal access for tokens generated with this key.
66    ///
67    /// Required. Possible values include combinations of:
68    /// - `trade:[read, read_write, none]`
69    /// - `wallet:[read, read_write, none]`
70    /// - `account:[read, read_write, none]`
71    /// - `block_trade:[read, read_write, none]`
72    pub max_scope: String,
73    /// Name of key (only letters, numbers and underscores; max 16 characters)
74    pub name: Option<String>,
75    /// ED25519 or RSA PEM encoded public key for asymmetric API key authentication
76    pub public_key: Option<String>,
77    /// List of enabled advanced on-key features.
78    ///
79    /// Available options:
80    /// - `restricted_block_trades`
81    /// - `block_trade_approval`
82    pub enabled_features: Option<Vec<String>>,
83}
84
85/// Request parameters for editing an existing API key.
86///
87/// At least one optional parameter must be provided along with the required fields.
88///
89/// # Example
90///
91/// ```rust
92/// use deribit_http::model::EditApiKeyRequest;
93///
94/// let request = EditApiKeyRequest {
95///     id: 123,
96///     max_scope: "account:read_write trade:read_write".to_string(),
97///     name: Some("updated_key_name".to_string()),
98///     ..Default::default()
99/// };
100/// ```
101#[derive(Debug, Clone, Default)]
102pub struct EditApiKeyRequest {
103    /// ID of the API key to edit
104    pub id: u64,
105    /// Describes maximal access for tokens generated with this key.
106    ///
107    /// Required. Possible values include combinations of:
108    /// - `trade:[read, read_write, none]`
109    /// - `wallet:[read, read_write, none]`
110    /// - `account:[read, read_write, none]`
111    /// - `block_trade:[read, read_write, none]`
112    pub max_scope: String,
113    /// Name of key (only letters, numbers and underscores; max 16 characters)
114    pub name: Option<String>,
115    /// Enable or disable the API key
116    pub enabled: Option<bool>,
117    /// List of enabled advanced on-key features
118    pub enabled_features: Option<Vec<String>>,
119    /// List of IP addresses to whitelist for this key
120    pub ip_whitelist: Option<Vec<String>>,
121}
122
123#[cfg(test)]
124mod tests {
125    use super::*;
126
127    #[test]
128    fn test_api_key_info_deserialization() {
129        let json = r#"{
130            "timestamp": 1560238048714,
131            "max_scope": "account:read block_trade:read_write trade:read wallet:none",
132            "id": 5,
133            "enabled": true,
134            "enabled_features": [],
135            "default": false,
136            "public_key": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAM7FWhKquNqLmTOV4hfYT5r3AjrYiORTT6Tn5HIfFNV8=\n-----END PUBLIC KEY-----",
137            "client_secret": "9c:6d:c9:02:fd:9f:75:6e:14:bb:71:c5:74:95:86:c8",
138            "client_id": "wcVoQGam",
139            "name": ""
140        }"#;
141
142        let info: ApiKeyInfo = serde_json::from_str(json).expect("Failed to deserialize");
143        assert_eq!(info.id, 5);
144        assert_eq!(info.client_id, "wcVoQGam");
145        assert!(info.enabled);
146        assert!(!info.default);
147        assert!(info.public_key.is_some());
148    }
149
150    #[test]
151    fn test_api_key_info_list_deserialization() {
152        let json = r#"[
153            {
154                "timestamp": 1560236001108,
155                "max_scope": "account:read block_trade:read trade:read_write wallet:read",
156                "id": 1,
157                "enabled": false,
158                "default": false,
159                "client_secret": "SjM57m1T2CfXZ4vZ76X1APjqRlJdtzHI8IwVXoQnfoM",
160                "client_id": "TiA4AyLPq3",
161                "name": "",
162                "enabled_features": []
163            },
164            {
165                "timestamp": 1560236287708,
166                "max_scope": "account:read_write block_trade:read_write trade:read_write wallet:read_write",
167                "id": 2,
168                "enabled": true,
169                "default": true,
170                "client_secret": "mwNOvbUVyQczytQ5IVM8CbzmgqNJ81WvLKfu6MXcJPs",
171                "client_id": "aD-KFx-H",
172                "name": "",
173                "enabled_features": []
174            }
175        ]"#;
176
177        let keys: Vec<ApiKeyInfo> = serde_json::from_str(json).expect("Failed to deserialize");
178        assert_eq!(keys.len(), 2);
179        assert_eq!(keys[0].id, 1);
180        assert!(!keys[0].enabled);
181        assert_eq!(keys[1].id, 2);
182        assert!(keys[1].enabled);
183    }
184
185    #[test]
186    fn test_create_api_key_request_default() {
187        let request = CreateApiKeyRequest::default();
188        assert!(request.max_scope.is_empty());
189        assert!(request.name.is_none());
190        assert!(request.public_key.is_none());
191        assert!(request.enabled_features.is_none());
192    }
193
194    #[test]
195    fn test_edit_api_key_request_default() {
196        let request = EditApiKeyRequest::default();
197        assert_eq!(request.id, 0);
198        assert!(request.max_scope.is_empty());
199        assert!(request.name.is_none());
200        assert!(request.enabled.is_none());
201    }
202}