use std::collections::HashMap;
use std::str::FromStr;
use tap_caip::AssetId;
use tap_msg::didcomm::PlainMessage;
use tap_msg::error::{Error, Result};
use tap_msg::message::tap_message_trait::{TapMessage, TapMessageBody};
use tap_msg::message::{
AddAgents, Agent, Authorize, ConfirmRelationship, Party, RemoveAgent, ReplaceAgent, Transfer,
};
use uuid::Uuid;
#[test]
fn test_create_reply() -> Result<()> {
let _alice_did = "did:example:alice";
let _bob_did = "did:example:bob";
let _charlie_did = "did:example:charlie";
let transfer = Transfer {
transaction_id: Some(uuid::Uuid::new_v4().to_string()),
asset: AssetId::from_str("eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
.unwrap(),
originator: Some(Party::new(_alice_did)),
beneficiary: Some(Party::new(_bob_did)),
amount: "10.00".to_string(),
agents: vec![],
settlement_id: None,
expiry: None,
transaction_value: None,
connection_id: None,
metadata: HashMap::new(),
memo: None,
};
let mut transfer_message = transfer.to_didcomm(_alice_did)?;
transfer_message.to = vec![_bob_did.to_string()];
let authorize = Authorize {
transaction_id: transfer_message.id.clone(), settlement_address: None,
expiry: None,
};
let reply_via_message = TapMessage::create_reply(&transfer_message, &authorize, _bob_did)?;
println!("Transfer message ID: {}", transfer_message.id);
println!("Transfer message thid: {:?}", transfer_message.thid);
println!("Reply message thid: {:?}", reply_via_message.thid);
assert_eq!(reply_via_message.from, _bob_did.to_string());
assert!(reply_via_message.to.contains(&_alice_did.to_string()));
assert!(!reply_via_message.to.contains(&_bob_did.to_string()));
assert_eq!(reply_via_message.thid, Some(transfer_message.id.clone()));
Ok(())
}
#[test]
fn test_add_agents() -> Result<()> {
let transfer_id = "test-transfer-123";
let _alice_did = "did:example:alice";
let _bob_did = "did:example:bob";
let charlie_did = "did:example:charlie";
let add_agents = AddAgents {
transaction_id: transfer_id.to_string(),
agents: vec![Agent::new(charlie_did, "observer", charlie_did)],
};
TapMessageBody::validate(&add_agents)?;
let mut message = add_agents.to_didcomm(_alice_did)?;
message.to = vec![_bob_did.to_string(), charlie_did.to_string()];
let message_with_thread = PlainMessage {
thid: Some(transfer_id.to_string()),
attachments: message.attachments.clone(),
..message
};
assert_eq!(message_with_thread.from, _alice_did.to_string());
assert!(message_with_thread.to.contains(&_bob_did.to_string()));
assert!(message_with_thread.to.contains(&charlie_did.to_string()));
assert_eq!(message_with_thread.thid, Some(transfer_id.to_string()));
let extracted_add_agents = AddAgents::from_didcomm(&message_with_thread)?;
assert_eq!(extracted_add_agents.transaction_id, transfer_id);
assert_eq!(extracted_add_agents.agents.len(), 1);
assert_eq!(extracted_add_agents.agents[0].id, charlie_did);
Ok(())
}
#[test]
fn test_replace_agent() -> Result<()> {
let transfer_id = "test-transfer-123";
let _alice_did = "did:example:alice";
let _bob_did = "did:example:bob";
let charlie_did = "did:example:charlie";
let replace_agent = ReplaceAgent {
transaction_id: transfer_id.to_string(),
original: _bob_did.to_string(),
replacement: Agent::new(charlie_did, "beneficiary", charlie_did),
};
TapMessageBody::validate(&replace_agent)?;
let mut message = replace_agent.to_didcomm(_alice_did)?;
message.to = vec![_bob_did.to_string(), charlie_did.to_string()];
let message_with_thread = PlainMessage {
thid: Some(transfer_id.to_string()),
attachments: message.attachments.clone(),
..message
};
assert_eq!(message_with_thread.from, _alice_did.to_string());
assert!(message_with_thread.to.contains(&_bob_did.to_string()));
assert!(message_with_thread.to.contains(&charlie_did.to_string()));
assert_eq!(message_with_thread.thid, Some(transfer_id.to_string()));
let extracted_replace_agent = ReplaceAgent::from_didcomm(&message_with_thread)?;
assert_eq!(extracted_replace_agent.transaction_id, transfer_id);
assert_eq!(extracted_replace_agent.original, _bob_did);
assert_eq!(extracted_replace_agent.replacement.id, charlie_did);
Ok(())
}
#[test]
fn test_remove_agent() -> Result<()> {
let transfer_id = "test-transfer-123";
let _alice_did = "did:example:alice";
let _bob_did = "did:example:bob";
let remove_agent = RemoveAgent {
transaction_id: transfer_id.to_string(),
agent: _bob_did.to_string(),
};
TapMessageBody::validate(&remove_agent)?;
let mut message = remove_agent.to_didcomm(_alice_did)?;
message.to = vec![_bob_did.to_string()];
let message_with_thread = PlainMessage {
thid: Some(transfer_id.to_string()),
attachments: message.attachments.clone(),
..message
};
assert_eq!(message_with_thread.from, _alice_did.to_string());
assert!(message_with_thread.to.contains(&_bob_did.to_string()));
assert_eq!(message_with_thread.thid, Some(transfer_id.to_string()));
let extracted_remove_agent = RemoveAgent::from_didcomm(&message_with_thread)?;
assert_eq!(extracted_remove_agent.transaction_id, transfer_id);
assert_eq!(extracted_remove_agent.agent, _bob_did);
Ok(())
}
#[test]
fn test_confirm_relationship() -> Result<()> {
let transfer_id = "test-transfer-123";
let _alice_did = "did:example:alice";
let _bob_did = "did:example:bob";
let _org_did = "did:example:organization";
let confirm_relationship = ConfirmRelationship {
transaction_id: transfer_id.to_string(),
agent_id: _bob_did.to_string(),
for_entity: _org_did.to_string(),
role: Some("custodian".to_string()),
};
use tap_msg::message::tap_message_trait::TapMessageBody;
TapMessageBody::validate(&confirm_relationship)?;
let mut message = confirm_relationship.to_didcomm(_alice_did)?;
message.to = vec![_bob_did.to_string()];
let message_with_thread = PlainMessage {
thid: Some(transfer_id.to_string()),
attachments: message.attachments.clone(),
..message
};
assert_eq!(message_with_thread.from, _alice_did.to_string());
assert!(message_with_thread.to.contains(&_bob_did.to_string()));
assert_eq!(message_with_thread.thid, Some(transfer_id.to_string()));
let extracted_confirm = ConfirmRelationship::from_didcomm(&message_with_thread)?;
assert_eq!(extracted_confirm.transaction_id, transfer_id);
assert_eq!(extracted_confirm.agent_id, _bob_did);
assert_eq!(extracted_confirm.for_entity, _org_did);
assert_eq!(extracted_confirm.role, Some("custodian".to_string()));
let transfer = Transfer {
transaction_id: Some(uuid::Uuid::new_v4().to_string()),
asset: AssetId::from_str("eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
.unwrap(),
originator: Some(Party::new(_alice_did)),
beneficiary: Some(Party::new(_bob_did)),
amount: "10.00".to_string(),
agents: vec![],
settlement_id: None,
expiry: None,
transaction_value: None,
connection_id: None,
metadata: HashMap::new(),
memo: Some("Test memo".to_string()),
};
let transfer_message = transfer.to_didcomm(_alice_did)?;
let mut metadata = HashMap::new();
metadata.insert(
"context".to_string(),
serde_json::Value::String("test".to_string()),
);
let transfer_body_json = transfer_message.body;
if transfer_body_json.is_null() {
return Err(Error::SerializationError(
"Missing transfer body".to_string(),
));
}
let _transfer_body: Transfer = serde_json::from_value(transfer_body_json.clone())?;
let confirm_relationship = ConfirmRelationship {
transaction_id: transfer_id.to_string(),
agent_id: _bob_did.to_string(),
for_entity: _org_did.to_string(),
role: Some("custodian".to_string()),
};
let confirm_message = confirm_relationship.to_didcomm(_alice_did)?;
assert_eq!(confirm_message.from, _alice_did.to_string());
assert!(confirm_message.to.is_empty());
assert_eq!(confirm_message.thid, Some(transfer_id.to_string()));
assert_eq!(confirm_message.body["for"].as_str().unwrap(), _org_did);
assert_eq!(confirm_message.body["role"].as_str().unwrap(), "custodian");
Ok(())
}
#[test]
fn test_get_all_participants() -> Result<()> {
let _alice_did = "did:example:alice";
let _bob_did = "did:example:bob";
let charlie_did = "did:example:charlie";
let message = PlainMessage {
id: Uuid::new_v4().to_string(),
typ: "application/didcomm-plain+json".to_string(),
type_: "https://tap.rsvp/schema/1.0#Transfer".to_string(),
body: serde_json::json!({}),
from: _alice_did.to_string(),
to: vec![_bob_did.to_string(), charlie_did.to_string()],
thid: None,
pthid: None,
extra_headers: HashMap::new(),
created_time: Some(1645556488),
expires_time: None,
from_prior: None,
attachments: None,
};
let mut participants = vec![message.from.clone()];
participants.extend(message.to.clone());
assert_eq!(participants.len(), 3);
assert!(participants.contains(&_alice_did.to_string()));
assert!(participants.contains(&_bob_did.to_string()));
assert!(participants.contains(&charlie_did.to_string()));
Ok(())
}
#[test]
fn test_add_agents_missing_transfer_id() {
let _tx_id = "".to_string();
let agents = vec![Agent::new(
"did:key:z6Mkk7yqnGF3YwTrLpqrW6PGsKci7dNqh1CjnvMbzrMerSeL",
"sender_agent",
"did:key:z6Mkk7yqnGF3YwTrLpqrW6PGsKci7dNqh1CjnvMbzrMerSeL",
)];
let add_agents = AddAgents {
transaction_id: _tx_id,
agents,
};
assert!(TapMessageBody::validate(&add_agents).is_err());
}
#[test]
fn test_add_agents_empty() {
let transfer_id = "test-transfer-123";
let _alice_did = "did:example:alice";
let _bob_did = "did:example:bob";
let add_agents = AddAgents {
transaction_id: transfer_id.to_string(),
agents: vec![],
};
let err = TapMessageBody::validate(&add_agents).unwrap_err();
match err {
Error::Validation(s) => assert!(s.contains("At least one agent")),
_ => panic!("Expected Validation error"),
}
}