extern crate tap_msg;
use chrono::{Duration, Utc};
use serde_json::json;
use std::str::FromStr;
use tap_caip::AssetId;
use tap_msg::message::tap_message_trait::TapMessageBody;
use tap_msg::message::{
Agent, Attachment, AuthorizationRequired, Connect, ConnectionConstraints, OutOfBand, Party,
Payment, PaymentBuilder, SimpleAttachmentData, TransactionLimits,
};
#[test]
fn test_payment_request_with_asset() {
let asset = "eip155:1/erc20:0xdac17f958d2ee523a2206206994597c13d831ec7"
.parse::<AssetId>()
.unwrap();
let merchant = Party::new("did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK");
let customer = Party::new("did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6");
let transaction_id = uuid::Uuid::new_v4().to_string();
let body = PaymentBuilder::default()
.transaction_id(transaction_id)
.asset(asset)
.amount("100000000".to_string())
.merchant(merchant.clone())
.customer(customer.clone())
.add_agent(Agent::new(
"did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6",
"customer_agent",
"did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6",
))
.build();
assert!(body.validate().is_ok());
let message = body
.to_didcomm_with_route(
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
["did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6"]
.iter()
.copied(),
)
.unwrap();
assert!(!message.id.is_empty());
assert_eq!(message.type_, "https://tap.rsvp/schema/1.0#Payment");
assert!(message.created_time.is_some());
assert_eq!(
message.from,
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK".to_string()
);
assert_eq!(
message.to,
vec!["did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6".to_string()]
);
}
#[test]
fn test_payment_request_with_currency() {
let merchant = Party::new("did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK");
let customer = Party::new("did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6");
let fiat_asset =
AssetId::from_str("fiat:USD").unwrap_or(AssetId::from_str("eip155:1/slip44:60").unwrap());
let body = PaymentBuilder::default()
.asset(fiat_asset.clone())
.currency_code("USD".to_string())
.amount("100.00".to_string())
.transaction_id(uuid::Uuid::new_v4().to_string())
.merchant(merchant.clone())
.customer(customer.clone())
.add_agent(Agent::new(
"did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6",
"customer_agent",
"did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6",
))
.build();
let mut body_with_supported_assets = body.clone();
body_with_supported_assets.metadata.insert(
"supported_assets".to_string(),
serde_json::to_value(vec![
"eip155:1/erc20:0xdac17f958d2ee523a2206206994597c13d831ec7".to_string(),
"bip122:000000000019d6689c085ae165831e93/slip44:0".to_string(),
])
.unwrap(),
);
assert!(body.validate().is_ok());
assert!(body_with_supported_assets.validate().is_ok());
let invalid_asset = AssetId::from_str("invalid:asset").unwrap_or(fiat_asset);
let invalid_body = PaymentBuilder::default()
.asset(invalid_asset)
.amount("".to_string()) .transaction_id(uuid::Uuid::new_v4().to_string())
.merchant(merchant.clone())
.customer(customer.clone())
.build();
assert!(invalid_body.validate().is_err());
}
#[test]
fn test_connect_message() {
let transaction_id = uuid::Uuid::new_v4().to_string();
let agent_id = "did:example:b2b-service".to_string();
let for_id = "did:example:business-customer".to_string();
let role = Some("ServiceAgent");
let transaction_limits = TransactionLimits {
per_transaction: Some("10000.00".to_string()),
per_day: Some("50000.00".to_string()),
per_week: None,
per_month: None,
per_year: None,
currency: Some("USD".to_string()),
};
let constraints = ConnectionConstraints {
purposes: Some(vec!["trading".to_string()]),
category_purposes: None,
limits: Some(transaction_limits),
allowed_beneficiaries: None,
allowed_settlement_addresses: None,
allowed_assets: None,
};
let mut body = Connect::new(&transaction_id, &agent_id, &for_id, role);
body.constraints = Some(constraints);
assert!(body.validate().is_ok());
let message = body
.to_didcomm_with_route(
"did:example:b2b-service",
["did:example:vasp"].iter().copied(),
)
.unwrap();
assert!(!message.id.is_empty());
assert_eq!(message.type_, "https://tap.rsvp/schema/1.0#Connect");
assert!(message.created_time.is_some());
assert_eq!(message.from, "did:example:b2b-service".to_string());
assert_eq!(message.to, vec!["did:example:vasp".to_string()]);
let mut invalid_body = body.clone();
invalid_body.for_ = Some("".to_string());
assert!(invalid_body.validate().is_err());
let minimal_body = Connect::new(
"test-transaction-id",
"did:example:b2b-service",
"did:example:business-customer",
None,
)
.with_constraints(ConnectionConstraints {
purposes: None,
category_purposes: None,
limits: None,
allowed_beneficiaries: None,
allowed_settlement_addresses: None,
allowed_assets: None,
});
assert!(minimal_body.validate().is_ok());
}
#[test]
fn test_authorization_required_message() {
let future_expiry = Utc::now() + Duration::days(1);
let expires_str = future_expiry.to_rfc3339();
let body = AuthorizationRequired::new(
"https://vasp.com/authorize?request=abc123".to_string(),
expires_str.clone(), );
assert!(body.validate().is_ok());
let message = body
.to_didcomm_with_route(
"did:example:vasp",
["did:example:b2b-service"].iter().copied(),
)
.unwrap();
assert!(!message.id.is_empty());
assert_eq!(
message.type_,
"https://tap.rsvp/schema/1.0#AuthorizationRequired"
);
assert!(message.created_time.is_some());
assert_eq!(message.from, "did:example:vasp".to_string());
assert_eq!(message.to, vec!["did:example:b2b-service".to_string()]);
let invalid_body = AuthorizationRequired::new("".to_string(), expires_str);
assert!(invalid_body.validate().is_err());
let invalid_expiry_body = AuthorizationRequired::new(
"https://vasp.com/authorize?request=abc123".to_string(),
"invalid-date-format".to_string(),
);
assert!(invalid_expiry_body.validate().is_err());
}
#[test]
fn test_out_of_band_message() {
let _attachment_data = SimpleAttachmentData {
base64: None,
json: Some(json!({
"key": "value"
})),
};
let _attachment = Attachment {
id: Some("123".to_string()),
media_type: Some("application/json".to_string()),
data: tap_msg::didcomm::AttachmentData::Json {
value: tap_msg::didcomm::JsonAttachmentData {
json: json!({
"key": "value"
}),
jws: None,
},
},
description: None,
filename: None,
format: None,
lastmod_time: None,
byte_count: None,
};
let body = OutOfBand::new(
"payment-request".to_string(),
"Request a payment".to_string(),
"https://example.com/service".to_string(),
);
let mut body_with_accept = body.clone();
body_with_accept.accept = Some(vec!["application/json".to_string()]);
body_with_accept.handshake_protocols =
Some(vec!["https://didcomm.org/connections/1.0".to_string()]);
assert!(body.validate().is_ok());
assert!(body_with_accept.validate().is_ok());
let message = body
.to_didcomm_with_route(
"did:example:sender",
["did:example:recipient"].iter().copied(),
)
.unwrap();
assert!(!message.id.is_empty());
assert_eq!(message.type_, "https://tap.rsvp/schema/1.0#OutOfBand");
assert!(message.created_time.is_some());
assert_eq!(message.from, "did:example:sender".to_string());
assert_eq!(message.to, vec!["did:example:recipient".to_string()]);
let _invalid_attachment = Attachment {
id: Some("".to_string()), media_type: Some("application/json".to_string()),
data: tap_msg::didcomm::AttachmentData::Json {
value: tap_msg::didcomm::JsonAttachmentData {
json: json!({}),
jws: None,
},
},
description: None,
filename: None,
format: None,
lastmod_time: None,
byte_count: None,
};
let invalid_body = OutOfBand::new(
"".to_string(), "Invalid test".to_string(),
"https://example.com/service".to_string(),
);
assert!(invalid_body.validate().is_err());
let _invalid_media_type_attachment = Attachment {
id: Some("123".to_string()),
media_type: Some("".to_string()), data: tap_msg::didcomm::AttachmentData::Json {
value: tap_msg::didcomm::JsonAttachmentData {
json: json!({}),
jws: None,
},
},
description: None,
filename: None,
format: None,
lastmod_time: None,
byte_count: None,
};
let invalid_media_type_body = OutOfBand::new(
"test".to_string(),
"Invalid media type test".to_string(),
"".to_string(), );
assert!(invalid_media_type_body.validate().is_err());
}
#[test]
fn test_invalid_out_of_band_message() {
let _invalid_attachment = Attachment {
id: Some("".to_string()),
media_type: Some("application/json".to_string()),
data: tap_msg::didcomm::AttachmentData::Json {
value: tap_msg::didcomm::JsonAttachmentData {
json: json!({}),
jws: None,
},
},
description: None,
filename: None,
format: None,
lastmod_time: None,
byte_count: None,
};
let invalid_body = OutOfBand::new(
"".to_string(), "Invalid test".to_string(),
"https://example.com/service".to_string(),
);
assert!(invalid_body.validate().is_err());
let _invalid_media_type_attachment = Attachment {
id: Some("attachment1".to_string()),
media_type: Some("".to_string()),
data: tap_msg::didcomm::AttachmentData::Json {
value: tap_msg::didcomm::JsonAttachmentData {
json: json!({}),
jws: None,
},
},
description: None,
filename: None,
format: None,
lastmod_time: None,
byte_count: None,
};
let invalid_media_type_body = OutOfBand::new(
"test".to_string(),
"Invalid media type test".to_string(),
"".to_string(), );
assert!(invalid_media_type_body.validate().is_err());
}
#[test]
fn test_payment_request_message() {
let asset = AssetId::from_str("eip155:1/slip44:60").unwrap();
let payment_request_body = PaymentBuilder::default()
.asset(asset)
.amount("1000000000000000000".to_string()) .transaction_id(uuid::Uuid::new_v4().to_string())
.merchant(Party::new("did:example:merchant"))
.customer(Party::new("did:example:customer"))
.add_agent(Agent::new(
"did:example:agent1",
"agent",
"did:example:agent1",
))
.build();
let message_result = payment_request_body.to_didcomm("did:example:sender");
assert!(message_result.is_ok());
let message = message_result.unwrap();
assert!(!message.id.is_empty()); assert_eq!(message.typ, "application/didcomm-plain+json"); assert!(!message.body.is_null());
let body_json = message.body;
let body: Payment = serde_json::from_value(body_json).unwrap();
assert_eq!(body.amount, "1000000000000000000"); }