1pub mod matching;
16pub mod services;
17
18use serde::{Deserialize, Serialize};
19
20#[cfg(feature = "client")]
21use crate::client::VtaClient;
22#[cfg(feature = "client")]
23use crate::error::VtaError;
24#[cfg(feature = "client")]
25use crate::protocols::protocol_management;
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29#[must_use]
30pub struct EnableDidcommRequest {
31 pub mediator_did: String,
32 #[serde(default)]
35 pub force: bool,
36 #[serde(default, skip_serializing_if = "Option::is_none")]
38 pub handshake_timeout_secs: Option<u64>,
39}
40
41impl EnableDidcommRequest {
42 pub fn new(mediator_did: impl Into<String>) -> Self {
43 Self {
44 mediator_did: mediator_did.into(),
45 force: false,
46 handshake_timeout_secs: None,
47 }
48 }
49
50 pub fn force(mut self, force: bool) -> Self {
51 self.force = force;
52 self
53 }
54
55 pub fn handshake_timeout_secs(mut self, secs: u64) -> Self {
56 self.handshake_timeout_secs = Some(secs);
57 self
58 }
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct EnableDidcommResponse {
63 pub new_version_id: String,
64 pub mediator_did: String,
65 pub mediator_endpoint: String,
66 #[serde(default, skip_serializing_if = "String::is_empty")]
72 pub vta_did: String,
73 #[serde(default)]
78 pub serverless: bool,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
83#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
84pub struct DidcommStatusResponse {
85 pub enabled: bool,
86 #[serde(default, skip_serializing_if = "Option::is_none")]
87 pub mediator_did: Option<String>,
88 #[serde(default, skip_serializing_if = "Option::is_none")]
89 pub websocket_status: Option<String>,
90}
91
92#[derive(Debug, Clone, Deserialize)]
95pub struct EnableDidcommConflictBody {
96 pub error: String,
97 #[serde(default)]
98 pub mediator_did: Option<String>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct DisableDidcommRequest {
104 pub drain_ttl_secs: u64,
107}
108
109impl DisableDidcommRequest {
110 pub fn new(drain_ttl_secs: u64) -> Self {
111 Self { drain_ttl_secs }
112 }
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct DisableDidcommResponse {
117 pub new_version_id: String,
118 pub prior_mediator_did: String,
119 #[serde(default, skip_serializing_if = "Option::is_none")]
122 pub drains_until: Option<String>,
123 #[serde(default, skip_serializing_if = "String::is_empty")]
125 pub vta_did: String,
126 #[serde(default)]
129 pub serverless: bool,
130}
131
132#[cfg(feature = "client")]
133impl VtaClient {
134 pub async fn enable_didcomm(
151 &self,
152 req: EnableDidcommRequest,
153 ) -> Result<EnableDidcommResponse, VtaError> {
154 match &self.transport {
155 crate::client::Transport::Rest {
156 client,
157 base_url,
158 auth,
159 } => {
160 Self::ensure_token_valid(client, base_url, auth).await?;
161 let token = auth.lock().await.token.clone();
162 let req = client
163 .post(format!("{base_url}/services/didcomm/enable"))
164 .json(&req);
165 let resp = Self::with_auth_token(req, &token).send().await?;
166 Self::handle_response(resp).await
167 }
168 #[cfg(feature = "session")]
169 crate::client::Transport::DIDComm { .. } => Err(VtaError::UnsupportedTransport(
170 "enable_didcomm is REST-only".into(),
171 )),
172 }
173 }
174
175 pub async fn didcomm_status(&self) -> Result<DidcommStatusResponse, VtaError> {
178 match &self.transport {
179 crate::client::Transport::Rest {
180 client,
181 base_url,
182 auth,
183 } => {
184 crate::client::VtaClient::ensure_token_valid(client, base_url, auth).await?;
185 let token = auth.lock().await.token.clone();
186 let req = client.get(format!("{base_url}/services/didcomm"));
187 let resp = crate::client::VtaClient::with_auth_token(req, &token)
188 .send()
189 .await?;
190 crate::client::VtaClient::handle_response(resp).await
191 }
192 #[cfg(feature = "session")]
193 crate::client::Transport::DIDComm { .. } => Err(VtaError::UnsupportedTransport(
194 "didcomm status is REST-only in the SDK".into(),
195 )),
196 }
197 }
198
199 pub async fn disable_didcomm(
205 &self,
206 req: DisableDidcommRequest,
207 ) -> Result<DisableDidcommResponse, VtaError> {
208 self.rpc(
209 protocol_management::DISABLE_DIDCOMM,
210 serde_json::to_value(&req)?,
211 protocol_management::DISABLE_DIDCOMM_RESULT,
212 30,
213 |c, url| c.post(format!("{url}/services/didcomm/disable")).json(&req),
214 )
215 .await
216 }
217
218 pub async fn update_didcomm(
227 &self,
228 req: UpdateDidcommRequest,
229 ) -> Result<UpdateDidcommResponse, VtaError> {
230 self.rpc(
231 protocol_management::UPDATE_DIDCOMM,
232 serde_json::to_value(&req)?,
233 protocol_management::UPDATE_DIDCOMM_RESULT,
234 120,
235 |c, url| c.post(format!("{url}/services/didcomm/update")).json(&req),
236 )
237 .await
238 }
239
240 pub async fn enable_rest(
246 &self,
247 req: services::EnableRestRequest,
248 ) -> Result<services::ServiceMutationResponse, VtaError> {
249 self.rpc(
250 protocol_management::ENABLE_REST,
251 serde_json::to_value(&req)?,
252 protocol_management::ENABLE_REST_RESULT,
253 30,
254 |c, url| c.post(format!("{url}/services/rest/enable")).json(&req),
255 )
256 .await
257 }
258
259 pub async fn update_rest(
261 &self,
262 req: services::UpdateRestRequest,
263 ) -> Result<services::ServiceMutationResponse, VtaError> {
264 self.rpc(
265 protocol_management::UPDATE_REST,
266 serde_json::to_value(&req)?,
267 protocol_management::UPDATE_REST_RESULT,
268 30,
269 |c, url| c.post(format!("{url}/services/rest/update")).json(&req),
270 )
271 .await
272 }
273
274 pub async fn disable_rest(
277 &self,
278 req: services::DisableRestRequest,
279 ) -> Result<services::ServiceMutationResponse, VtaError> {
280 self.rpc(
281 protocol_management::DISABLE_REST,
282 serde_json::to_value(&req)?,
283 protocol_management::DISABLE_REST_RESULT,
284 30,
285 |c, url| c.post(format!("{url}/services/rest/disable")).json(&req),
286 )
287 .await
288 }
289
290 pub async fn rollback_rest(
296 &self,
297 req: services::RollbackRestRequest,
298 ) -> Result<services::RollbackResponse, VtaError> {
299 self.rpc(
300 protocol_management::ROLLBACK_REST,
301 serde_json::to_value(&req)?,
302 protocol_management::ROLLBACK_REST_RESULT,
303 60,
304 |c, url| c.post(format!("{url}/services/rest/rollback")).json(&req),
305 )
306 .await
307 }
308
309 pub async fn enable_tsp(
322 &self,
323 req: services::EnableTspRequest,
324 ) -> Result<services::ServiceMutationResponse, VtaError> {
325 self.rpc(
326 protocol_management::ENABLE_TSP,
327 serde_json::to_value(&req)?,
328 protocol_management::ENABLE_TSP_RESULT,
329 30,
330 |c, url| c.post(format!("{url}/services/tsp/enable")).json(&req),
331 )
332 .await
333 }
334
335 pub async fn update_tsp(
337 &self,
338 req: services::UpdateTspRequest,
339 ) -> Result<services::ServiceMutationResponse, VtaError> {
340 self.rpc(
341 protocol_management::UPDATE_TSP,
342 serde_json::to_value(&req)?,
343 protocol_management::UPDATE_TSP_RESULT,
344 30,
345 |c, url| c.post(format!("{url}/services/tsp/update")).json(&req),
346 )
347 .await
348 }
349
350 pub async fn disable_tsp(
354 &self,
355 req: services::DisableTspRequest,
356 ) -> Result<services::ServiceMutationResponse, VtaError> {
357 self.rpc(
358 protocol_management::DISABLE_TSP,
359 serde_json::to_value(&req)?,
360 protocol_management::DISABLE_TSP_RESULT,
361 30,
362 |c, url| c.post(format!("{url}/services/tsp/disable")).json(&req),
363 )
364 .await
365 }
366
367 pub async fn rollback_tsp(
370 &self,
371 req: services::RollbackTspRequest,
372 ) -> Result<services::RollbackResponse, VtaError> {
373 self.rpc(
374 protocol_management::ROLLBACK_TSP,
375 serde_json::to_value(&req)?,
376 protocol_management::ROLLBACK_TSP_RESULT,
377 60,
378 |c, url| c.post(format!("{url}/services/tsp/rollback")).json(&req),
379 )
380 .await
381 }
382
383 pub async fn enable_webauthn(
388 &self,
389 req: services::EnableWebauthnRequest,
390 ) -> Result<services::ServiceMutationResponse, VtaError> {
391 self.rpc(
392 protocol_management::ENABLE_WEBAUTHN,
393 serde_json::to_value(&req)?,
394 protocol_management::ENABLE_WEBAUTHN_RESULT,
395 30,
396 |c, url| c.post(format!("{url}/services/webauthn/enable")).json(&req),
397 )
398 .await
399 }
400
401 pub async fn update_webauthn(
403 &self,
404 req: services::UpdateWebauthnRequest,
405 ) -> Result<services::ServiceMutationResponse, VtaError> {
406 self.rpc(
407 protocol_management::UPDATE_WEBAUTHN,
408 serde_json::to_value(&req)?,
409 protocol_management::UPDATE_WEBAUTHN_RESULT,
410 30,
411 |c, url| c.post(format!("{url}/services/webauthn/update")).json(&req),
412 )
413 .await
414 }
415
416 pub async fn disable_webauthn(
421 &self,
422 req: services::DisableWebauthnRequest,
423 ) -> Result<services::ServiceMutationResponse, VtaError> {
424 self.rpc(
428 protocol_management::DISABLE_WEBAUTHN,
429 serde_json::to_value(&req)?,
430 protocol_management::DISABLE_WEBAUTHN_RESULT,
431 300,
432 |c, url| {
433 c.post(format!("{url}/services/webauthn/disable"))
434 .json(&req)
435 },
436 )
437 .await
438 }
439
440 pub async fn rollback_webauthn(
443 &self,
444 req: services::RollbackWebauthnRequest,
445 ) -> Result<services::RollbackResponse, VtaError> {
446 self.rpc(
447 protocol_management::ROLLBACK_WEBAUTHN,
448 serde_json::to_value(&req)?,
449 protocol_management::ROLLBACK_WEBAUTHN_RESULT,
450 300,
451 |c, url| {
452 c.post(format!("{url}/services/webauthn/rollback"))
453 .json(&req)
454 },
455 )
456 .await
457 }
458
459 pub async fn rollback_didcomm(
463 &self,
464 req: services::RollbackDidcommRequest,
465 ) -> Result<services::RollbackResponse, VtaError> {
466 self.rpc(
467 protocol_management::ROLLBACK_DIDCOMM,
468 serde_json::to_value(&req)?,
469 protocol_management::ROLLBACK_DIDCOMM_RESULT,
470 120,
471 |c, url| {
472 c.post(format!("{url}/services/didcomm/rollback"))
473 .json(&req)
474 },
475 )
476 .await
477 }
478
479 pub async fn list_services(&self) -> Result<services::ServicesListResponse, VtaError> {
485 self.rpc(
486 protocol_management::LIST_SERVICES,
487 serde_json::Value::Null,
488 protocol_management::LIST_SERVICES_RESULT,
489 30,
490 |c, url| c.get(format!("{url}/services")),
491 )
492 .await
493 }
494
495 pub async fn list_drain(&self) -> Result<services::DrainListResponse, VtaError> {
497 self.rpc(
498 protocol_management::LIST_DRAIN,
499 serde_json::Value::Null,
500 protocol_management::LIST_DRAIN_RESULT,
501 30,
502 |c, url| c.get(format!("{url}/services/didcomm/drain")),
503 )
504 .await
505 }
506}
507
508#[derive(Debug, Clone, Serialize, Deserialize)]
510#[must_use]
511pub struct UpdateDidcommRequest {
512 pub new_mediator_did: String,
513 pub drain_ttl_secs: u64,
514 #[serde(default)]
515 pub force: bool,
516 #[serde(default, skip_serializing_if = "Option::is_none")]
517 pub handshake_timeout_secs: Option<u64>,
518 #[serde(default)]
520 pub rollback: bool,
521}
522
523impl UpdateDidcommRequest {
524 pub fn new(new_mediator_did: impl Into<String>, drain_ttl_secs: u64) -> Self {
525 Self {
526 new_mediator_did: new_mediator_did.into(),
527 drain_ttl_secs,
528 force: false,
529 handshake_timeout_secs: None,
530 rollback: false,
531 }
532 }
533
534 pub fn force(mut self, force: bool) -> Self {
535 self.force = force;
536 self
537 }
538
539 pub fn rollback(mut self, rollback: bool) -> Self {
540 self.rollback = rollback;
541 self
542 }
543
544 pub fn handshake_timeout_secs(mut self, secs: u64) -> Self {
545 self.handshake_timeout_secs = Some(secs);
546 self
547 }
548}
549
550#[derive(Debug, Clone, Serialize, Deserialize)]
551pub struct UpdateDidcommResponse {
552 pub new_version_id: String,
553 pub prior_mediator_did: String,
554 pub active_mediator_did: String,
555 pub active_mediator_endpoint: String,
556 pub drains_until: String,
557 #[serde(default, skip_serializing_if = "String::is_empty")]
559 pub vta_did: String,
560 #[serde(default)]
563 pub serverless: bool,
564}
565
566#[derive(Debug, Clone, Serialize, Deserialize)]
568pub struct DrainCancelRequest {
569 pub mediator_did: String,
570}
571
572#[derive(Debug, Clone, Serialize, Deserialize)]
573pub struct DrainCancelResponse {
574 pub mediator_did: String,
575}
576
577#[derive(Debug, Clone, Serialize, Deserialize)]
578pub struct MediatorStats {
579 pub mediator_did: String,
580 pub inbound_count: u64,
581 pub first_seen: String,
582 pub last_seen: String,
583}
584
585#[derive(Debug, Clone, Serialize, Deserialize)]
586pub struct SenderLastSeen {
587 pub sender_did: String,
588 pub last_seen_mediator: String,
589 pub last_seen_at: String,
590}
591
592#[derive(Debug, Clone, Serialize, Deserialize)]
593pub struct MediatorReport {
594 #[serde(default)]
595 pub since: Option<String>,
596 pub until: String,
597 pub mediators: Vec<MediatorStats>,
598 pub senders: Vec<SenderLastSeen>,
599}
600
601#[cfg(feature = "client")]
602impl VtaClient {
603 pub async fn drain_cancel(
608 &self,
609 req: DrainCancelRequest,
610 ) -> Result<DrainCancelResponse, VtaError> {
611 self.rpc(
612 protocol_management::DRAIN_CANCEL,
613 serde_json::to_value(&req)?,
614 protocol_management::DRAIN_CANCEL_RESULT,
615 30,
616 |c, url| c.post(format!("{url}/mediators/drain/cancel")).json(&req),
617 )
618 .await
619 }
620
621 pub async fn mediator_report(
627 &self,
628 since: Option<&str>,
629 until: Option<&str>,
630 ) -> Result<MediatorReport, VtaError> {
631 let since_owned = since.map(str::to_string);
632 let until_owned = until.map(str::to_string);
633 let qs = build_report_query(since_owned.as_deref(), until_owned.as_deref());
634 self.rpc(
635 protocol_management::MEDIATOR_REPORT,
636 serde_json::json!({
637 "since": since_owned,
638 "until": until_owned,
639 }),
640 protocol_management::MEDIATOR_REPORT_RESULT,
641 30,
642 move |c, url| {
643 let url = if qs.is_empty() {
644 format!("{url}/mediators/report")
645 } else {
646 format!("{url}/mediators/report?{qs}")
647 };
648 c.get(url)
649 },
650 )
651 .await
652 }
653}
654
655#[cfg(feature = "client")]
656fn build_report_query(since: Option<&str>, until: Option<&str>) -> String {
657 let mut parts: Vec<String> = Vec::new();
658 if let Some(s) = since {
659 parts.push(format!("since={}", url_encode(s)));
660 }
661 if let Some(u) = until {
662 parts.push(format!("until={}", url_encode(u)));
663 }
664 parts.join("&")
665}
666
667#[cfg(feature = "client")]
668fn url_encode(s: &str) -> String {
669 s.chars()
674 .flat_map(|c| match c {
675 ':' => "%3A".chars().collect::<Vec<_>>(),
676 '+' => "%2B".chars().collect::<Vec<_>>(),
677 _ => vec![c],
678 })
679 .collect()
680}