extern crate tap_msg;
use std::collections::HashMap;
use std::str::FromStr;
use tap_caip::AssetId;
use tap_msg::message::tap_message_trait::Authorizable;
use tap_msg::message::tap_message_trait::TapMessageBody;
use tap_msg::message::{Agent, Party, Payment, PaymentBuilder, Transfer, UpdateParty};
#[test]
fn test_create_message() {
let asset = "eip155:1/erc20:0xdac17f958d2ee523a2206206994597c13d831ec7"
.parse::<AssetId>()
.unwrap();
let originator = Party::new("did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK");
let beneficiary = Party::new("did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6");
let body = Transfer {
transaction_id: Some(uuid::Uuid::new_v4().to_string()),
asset,
originator: Some(originator.clone()),
beneficiary: Some(beneficiary.clone()),
amount: "100000000".to_string(),
agents: vec![
Agent::new(
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"originator_agent",
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
),
Agent::new(
"did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6",
"beneficiary_agent",
"did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6",
),
],
settlement_id: None,
expiry: None,
transaction_value: None,
connection_id: None,
metadata: HashMap::new(),
memo: None,
};
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#Transfer");
assert!(message.created_time.is_some());
assert_eq!(
message.from,
"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
);
assert_eq!(
message.to,
vec!["did:key:z6MkmRsjkKHNrBiVz5mhiqhJVYf9E9mxg3MVGqgqMkRwCJd6".to_string()]
);
}
#[cfg(test)]
mod payment_tests {
use super::*;
trait PaymentExt {
fn merchant(&self) -> &Party;
fn customer(&self) -> Option<&Party>;
}
impl PaymentExt for Payment {
fn merchant(&self) -> &Party {
&self.merchant
}
fn customer(&self) -> Option<&Party> {
self.customer.as_ref()
}
}
fn create_valid_payment() -> Payment {
let merchant_did = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH";
let customer_did = "did:key:z6MkhTBLxt9a7sWX77zn1GnzYam743kc9HvzA9qnKXqpVmXC";
let asset_id_str = "eip155:1/slip44:60";
let merchant = Party::new(merchant_did);
let customer = Party::new(customer_did);
PaymentBuilder::default()
.transaction_id("pay_123".to_string())
.merchant(merchant.clone())
.customer(customer.clone())
.asset(AssetId::from_str(asset_id_str).unwrap())
.amount("100.50".to_string())
.build()
}
#[test]
fn test_build_valid_payment() {
let payment = create_valid_payment();
assert_eq!(payment.transaction_id, Some("pay_123".to_string()));
assert_eq!(payment.amount.parse::<f64>().unwrap(), 100.50);
}
#[test]
fn test_payment_validation_failures() {
let merchant_did = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH";
let customer_did = "did:key:z6MkhTBLxt9a7sWX77zn1GnzYam743kc9HvzA9qnKXqpVmXC";
let asset_id_str = "eip155:1/slip44:60";
let res = PaymentBuilder::default()
.merchant(Party::new(merchant_did))
.customer(Party::new(customer_did))
.asset(AssetId::from_str(asset_id_str).unwrap())
.amount("100".to_string())
.build();
assert!(res.transaction_id.is_none());
let res = PaymentBuilder::default()
.transaction_id("pay_000".to_string())
.merchant(Party::new(merchant_did))
.customer(Party::new(customer_did))
.asset(AssetId::from_str(asset_id_str).unwrap())
.amount("0.00".to_string())
.build();
assert_eq!(res.amount, "0.00".to_string());
}
#[test]
fn test_payment_to_didcomm() {
let payment = create_valid_payment();
let merchant_did = &payment.merchant().id;
let customer_did = &payment.customer().unwrap().id;
let message_from_merchant = payment.to_didcomm(merchant_did).unwrap();
assert_eq!(
message_from_merchant.type_,
<Payment as TapMessageBody>::message_type()
);
assert_eq!(message_from_merchant.from, merchant_did.to_string());
assert!(!message_from_merchant.to.is_empty());
assert_eq!(message_from_merchant.to.len(), 1); assert!(message_from_merchant.to.contains(customer_did));
assert!(!message_from_merchant.to.contains(merchant_did));
let body: Payment = serde_json::from_value(message_from_merchant.body).unwrap();
assert_eq!(body.amount, payment.amount);
assert_eq!(body.asset, payment.asset);
assert_eq!(body.merchant.id, payment.merchant.id);
}
#[test]
fn test_payment_authorizable_trait() {
let payment = create_valid_payment();
let transaction_id = payment.transaction_id.clone();
let _authorize_message = payment.authorize("did:example:creator", None, None);
let reject_code = "E001".to_string();
let reject_reason = "Insufficient funds".to_string();
let reject = tap_msg::message::Reject {
transaction_id: payment.transaction_id.clone().unwrap(),
reason: Some(format!("{}: {}", reject_code, reject_reason)),
};
assert_eq!(reject.reason, Some("E001: Insufficient funds".to_string()));
let settle = tap_msg::message::Settle {
transaction_id: payment.transaction_id.clone().unwrap(),
settlement_id: Some("tx-abc".to_string()),
amount: Some("100.0".to_string()),
};
assert_eq!(settle.settlement_id, Some("tx-abc".to_string()));
assert_eq!(settle.amount, Some("100.0".to_string()));
let updated_participant =
Party::new("did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH");
let update_party = UpdateParty {
transaction_id: transaction_id.clone().unwrap(),
party_type: "beneficiary".to_string(),
party: updated_participant.clone(),
context: None,
};
assert_eq!(update_party.transaction_id, transaction_id.unwrap());
}
}