tap_msg/message/update_party.rs
1//! Update Party message type for the Transaction Authorization Protocol.
2//!
3//! This module defines the UpdateParty message type, which is used to update
4//! party information in an existing transaction.
5
6use crate::error::{Error, Result};
7use crate::message::agent::TapParticipant;
8use crate::message::Party;
9use crate::TapMessage;
10use serde::{Deserialize, Serialize};
11
12/// UpdateParty message body (TAIP-6).
13///
14/// This message type allows agents to update party information in a transaction.
15/// It enables a participant to modify their details or role within an existing transfer without
16/// creating a new transaction. This is particularly useful for situations where participant
17/// information changes during the lifecycle of a transaction.
18///
19/// # TAIP-6 Specification
20/// The UpdateParty message follows the TAIP-6 specification for updating party information
21/// in a TAP transaction. It includes JSON-LD compatibility with an optional @context field.
22///
23/// # Example
24/// ```
25/// use tap_msg::message::update_party::UpdateParty;
26/// use tap_msg::message::Party;
27/// use std::collections::HashMap;
28///
29/// // Create a party with updated information
30/// let updated_party = Party::new("did:key:z6MkpDYxrwJw5WoD1o4YVfthJJgZfxrECpW6Da6QCWagRHLx")
31/// .with_country("de");
32///
33/// // Create an UpdateParty message
34/// let update_party = UpdateParty::new(
35/// "transfer-123",
36/// "originator",
37/// updated_party
38/// );
39///
40/// ```
41#[derive(Debug, Clone, Serialize, Deserialize, TapMessage)]
42#[tap(message_type = "https://tap.rsvp/schema/1.0#UpdateParty")]
43pub struct UpdateParty {
44 /// ID of the transaction this update relates to.
45 #[tap(thread_id)]
46 pub transaction_id: String,
47
48 /// Type of party being updated (e.g., 'originator', 'beneficiary').
49 #[serde(rename = "partyType")]
50 pub party_type: String,
51
52 /// Updated party information.
53 #[tap(participant)]
54 pub party: Party,
55
56 /// Optional context for the update.
57 #[serde(rename = "@context", skip_serializing_if = "Option::is_none")]
58 pub context: Option<String>,
59}
60
61impl UpdateParty {
62 /// Creates a new UpdateParty message body.
63 pub fn new(transaction_id: &str, party_type: &str, party: Party) -> Self {
64 Self {
65 transaction_id: transaction_id.to_string(),
66 party_type: party_type.to_string(),
67 party,
68 context: None,
69 }
70 }
71
72 /// Custom validation for UpdateParty messages
73 pub fn validate_update_party(&self) -> Result<()> {
74 if self.transaction_id.is_empty() {
75 return Err(Error::Validation(
76 "transaction_id cannot be empty".to_string(),
77 ));
78 }
79
80 if self.party_type.is_empty() {
81 return Err(Error::Validation("partyType cannot be empty".to_string()));
82 }
83
84 if self.party.id().is_empty() {
85 return Err(Error::Validation("party.id cannot be empty".to_string()));
86 }
87
88 Ok(())
89 }
90}
91
92impl UpdateParty {
93 /// Implementation of the validate method for the TapMessageBody trait
94 /// This delegates to the custom validation method
95 pub fn validate(&self) -> Result<()> {
96 self.validate_update_party()
97 }
98}