1use crate::agent_key_manager::{AgentKeyManager, AgentKeyManagerBuilder};
2use crate::config::AgentConfig;
3#[cfg(all(not(target_arch = "wasm32"), test))]
4use crate::did::SyncDIDResolver; use crate::error::{Error, Result};
6use crate::key_manager::KeyManager; #[cfg(not(target_arch = "wasm32"))]
8use crate::message::SecurityMode;
9#[cfg(not(target_arch = "wasm32"))]
10use crate::message_packing::{PackOptions, Packable, UnpackOptions, Unpackable};
11use async_trait::async_trait;
12#[cfg(feature = "native")]
13use reqwest::Client;
14use serde::de::DeserializeOwned;
15use serde_json::Value;
16use std::sync::Arc;
17#[cfg(feature = "native")]
18use std::time::Duration;
19use tap_msg::didcomm::PlainMessage;
20use tap_msg::TapMessageBody;
21
22#[derive(Debug, Clone)]
24pub struct DeliveryResult {
25 pub did: String,
27 pub endpoint: String,
29 pub status: Option<u16>,
31 pub error: Option<String>,
33}
34
35#[cfg(not(target_arch = "wasm32"))]
37#[async_trait]
38#[cfg(not(target_arch = "wasm32"))]
39pub trait Agent {
40 fn get_agent_did(&self) -> &str;
42
43 async fn get_service_endpoint(&self, to: &str) -> Result<Option<String>>;
45
46 async fn send_message<
48 T: TapMessageBody + serde::Serialize + Send + Sync + std::fmt::Debug + 'static,
49 >(
50 &self,
51 message: &T,
52 to: Vec<&str>,
53 deliver: bool,
54 ) -> Result<(String, Vec<DeliveryResult>)>;
55
56 async fn receive_message<T: TapMessageBody + DeserializeOwned + Send>(
58 &self,
59 packed_message: &str,
60 ) -> Result<T>;
61}
62
63#[cfg(target_arch = "wasm32")]
65pub trait WasmAgent {
66 fn get_agent_did(&self) -> &str;
68
69 fn pack_message<T: TapMessageBody + serde::Serialize>(&self, message: &T) -> Result<String>;
71
72 fn unpack_message<T: TapMessageBody + DeserializeOwned>(
74 &self,
75 packed_message: &str,
76 ) -> Result<T>;
77}
78
79#[derive(Debug, Clone)]
81pub struct TapAgent {
82 pub config: AgentConfig,
84 key_manager: Arc<AgentKeyManager>,
86 #[cfg(all(not(target_arch = "wasm32"), test))]
88 resolver: Option<Arc<dyn SyncDIDResolver>>,
89 #[cfg(all(feature = "native", not(target_arch = "wasm32")))]
91 http_client: Option<Client>,
92}
93
94impl TapAgent {
95 pub fn new(config: AgentConfig, key_manager: Arc<AgentKeyManager>) -> Self {
97 #[cfg(all(feature = "native", not(target_arch = "wasm32")))]
98 {
99 let timeout = Duration::from_secs(config.timeout_seconds.unwrap_or(30));
100 let client = Client::builder().timeout(timeout).build().ok();
101
102 #[cfg(test)]
103 let agent = TapAgent {
104 config,
105 key_manager,
106 resolver: None,
107 http_client: client,
108 };
109
110 #[cfg(not(test))]
111 let agent = TapAgent {
112 config,
113 key_manager,
114 http_client: client,
115 };
116
117 agent
118 }
119
120 #[cfg(not(all(feature = "native", not(target_arch = "wasm32"))))]
121 {
122 #[cfg(all(not(target_arch = "wasm32"), test))]
123 let agent = TapAgent {
124 config,
125 key_manager,
126 resolver: None,
127 };
128
129 #[cfg(all(not(target_arch = "wasm32"), not(test)))]
130 let agent = TapAgent {
131 config,
132 key_manager,
133 };
134
135 #[cfg(target_arch = "wasm32")]
136 let agent = TapAgent {
137 config,
138 key_manager,
139 };
140
141 agent
142 }
143 }
144
145 #[cfg(all(not(target_arch = "wasm32"), test))]
147 pub fn new_with_resolver(
148 config: AgentConfig,
149 key_manager: Arc<AgentKeyManager>,
150 resolver: Arc<dyn SyncDIDResolver>,
151 ) -> Self {
152 #[cfg(feature = "native")]
153 {
154 let timeout = Duration::from_secs(config.timeout_seconds.unwrap_or(30));
155 let client = Client::builder().timeout(timeout).build().ok();
156
157 TapAgent {
158 config,
159 key_manager,
160 resolver: Some(resolver),
161 http_client: client,
162 }
163 }
164
165 #[cfg(not(feature = "native"))]
166 {
167 TapAgent {
168 config,
169 key_manager,
170 resolver: Some(resolver),
171 }
172 }
173 }
174
175 pub async fn from_ephemeral_key() -> crate::error::Result<(Self, String)> {
184 use crate::did::{DIDGenerationOptions, KeyType};
185
186 let key_manager = AgentKeyManager::new();
188
189 let key = key_manager.generate_key(DIDGenerationOptions {
191 key_type: KeyType::Ed25519,
192 })?;
193
194 let config = AgentConfig::new(key.did.clone()).with_debug(true);
196
197 #[cfg(all(not(target_arch = "wasm32"), test))]
199 {
200 let resolver = Arc::new(crate::did::MultiResolver::default());
202 let agent = Self::new_with_resolver(config, Arc::new(key_manager), resolver);
203 Ok((agent, key.did))
204 }
205
206 #[cfg(all(not(target_arch = "wasm32"), not(test)))]
207 {
208 let agent = Self::new(config, Arc::new(key_manager));
209 Ok((agent, key.did))
210 }
211
212 #[cfg(target_arch = "wasm32")]
213 {
214 let agent = Self::new(config, Arc::new(key_manager));
215 Ok((agent, key.did))
216 }
217 }
218
219 pub async fn from_stored_keys(did: Option<String>, debug: bool) -> Result<Self> {
232 use crate::storage::KeyStorage;
233
234 let key_manager_builder = AgentKeyManagerBuilder::new().load_from_default_storage();
236 let key_manager = key_manager_builder.build()?;
237
238 let dids = key_manager.list_keys()?;
240 if dids.is_empty() {
241 return Err(Error::Storage(
242 "No keys found in storage. Generate keys first with 'tap-agent-cli generate --save'".to_string(),
243 ));
244 }
245
246 let agent_did = if let Some(specified_did) = did {
248 if !dids.contains(&specified_did) {
249 return Err(Error::Storage(format!(
250 "Key with DID '{}' not found in storage",
251 specified_did
252 )));
253 }
254 specified_did
255 } else {
256 let storage = KeyStorage::load_default()?;
258 storage.default_did.unwrap_or_else(|| dids[0].clone())
259 };
260
261 let config = AgentConfig::new(agent_did).with_debug(debug);
263
264 #[cfg(all(not(target_arch = "wasm32"), test))]
266 {
267 let resolver = Arc::new(crate::did::MultiResolver::default());
269 Ok(TapAgent::new_with_resolver(
270 config,
271 Arc::new(key_manager),
272 resolver,
273 ))
274 }
275
276 #[cfg(all(not(target_arch = "wasm32"), not(test)))]
277 {
278 Ok(TapAgent::new(config, Arc::new(key_manager)))
279 }
280
281 #[cfg(target_arch = "wasm32")]
282 {
283 Ok(TapAgent::new(config, Arc::new(key_manager)))
284 }
285 }
286
287 pub async fn from_private_key(
303 private_key: &[u8],
304 key_type: crate::did::KeyType,
305 debug: bool,
306 ) -> Result<(Self, String)> {
307 use crate::did::{DIDKeyGenerator, GeneratedKey};
308 use crate::did::{VerificationMaterial, VerificationMethod, VerificationMethodType};
309 use curve25519_dalek::edwards::CompressedEdwardsY;
310 use multibase::{encode, Base};
311
312 let key_manager = AgentKeyManager::new();
314
315 let generated_key = match key_type {
317 crate::did::KeyType::Ed25519 => {
318 if private_key.len() != 32 {
319 return Err(Error::Validation(format!(
320 "Invalid Ed25519 private key length: {}, expected 32 bytes",
321 private_key.len()
322 )));
323 }
324
325 let mut private_key_bytes = [0u8; 32];
327 private_key_bytes.copy_from_slice(&private_key[0..32]);
328
329 let signing_key = ed25519_dalek::SigningKey::from_bytes(&private_key_bytes);
330
331 let verifying_key = ed25519_dalek::VerifyingKey::from(&signing_key);
333 let public_key = verifying_key.to_bytes().to_vec();
334
335 let mut prefixed_key = vec![0xed, 0x01];
338 prefixed_key.extend_from_slice(&public_key);
339
340 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
342 let did = format!("did:key:{}", multibase_encoded);
343
344 let vm_id = format!("{}#{}", did, multibase_encoded);
346
347 let verification_method = VerificationMethod {
349 id: vm_id.clone(),
350 type_: VerificationMethodType::Ed25519VerificationKey2018,
351 controller: did.clone(),
352 verification_material: VerificationMaterial::Multibase {
353 public_key_multibase: multibase_encoded.clone(),
354 },
355 };
356
357 let x25519_method_and_agreement = {
359 if public_key.len() != 32 {
361 None
362 } else {
363 let edwards_y = match CompressedEdwardsY::from_slice(&public_key) {
365 Ok(point) => point,
366 Err(_) => {
367 return Err(Error::Cryptography(
368 "Failed to create Edwards point".to_string(),
369 ))
370 }
371 };
372
373 let edwards_point = match edwards_y.decompress() {
375 Some(point) => point,
376 None => {
377 return Err(Error::Cryptography(
378 "Failed to decompress Edwards point".to_string(),
379 ))
380 }
381 };
382
383 let montgomery_point = edwards_point.to_montgomery();
385
386 let x25519_key = montgomery_point.to_bytes();
388
389 let mut x25519_prefixed = vec![0xEC, 0x01];
391 x25519_prefixed.extend_from_slice(&x25519_key);
392
393 let x25519_multibase = encode(Base::Base58Btc, &x25519_prefixed);
395
396 let x25519_vm_id = format!("{}#{}", did, x25519_multibase);
398
399 let x25519_verification_method = VerificationMethod {
401 id: x25519_vm_id.clone(),
402 type_: VerificationMethodType::X25519KeyAgreementKey2019,
403 controller: did.clone(),
404 verification_material: VerificationMaterial::Multibase {
405 public_key_multibase: x25519_multibase,
406 },
407 };
408
409 Some((x25519_verification_method, x25519_vm_id))
410 }
411 };
412
413 let mut verification_methods = vec![verification_method.clone()];
415 let mut key_agreement = Vec::new();
416
417 if let Some((x25519_vm, x25519_id)) = x25519_method_and_agreement {
418 verification_methods.push(x25519_vm);
419 key_agreement.push(x25519_id);
420 }
421
422 let did_doc = crate::did::DIDDoc {
424 id: did.clone(),
425 verification_method: verification_methods,
426 authentication: vec![vm_id],
427 key_agreement,
428 assertion_method: Vec::new(),
429 capability_invocation: Vec::new(),
430 capability_delegation: Vec::new(),
431 service: Vec::new(),
432 };
433
434 GeneratedKey {
436 key_type: crate::did::KeyType::Ed25519,
437 did: did.clone(),
438 public_key,
439 private_key: private_key.to_vec(),
440 did_doc,
441 }
442 }
443 crate::did::KeyType::P256 => {
444 if private_key.len() != 32 {
445 return Err(Error::Validation(format!(
446 "Invalid P-256 private key length: {}, expected 32 bytes",
447 private_key.len()
448 )));
449 }
450
451 let signing_key = match p256::ecdsa::SigningKey::from_slice(private_key) {
453 Ok(key) => key,
454 Err(e) => {
455 return Err(Error::Cryptography(format!(
456 "Failed to create P-256 signing key: {:?}",
457 e
458 )))
459 }
460 };
461
462 let public_key = signing_key
464 .verifying_key()
465 .to_encoded_point(false)
466 .to_bytes()
467 .to_vec();
468
469 let mut prefixed_key = vec![0x12, 0x00];
472 prefixed_key.extend_from_slice(&public_key);
473
474 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
476 let did = format!("did:key:{}", multibase_encoded);
477
478 let vm_id = format!("{}#{}", did, multibase_encoded);
480
481 let verification_method = VerificationMethod {
483 id: vm_id.clone(),
484 type_: VerificationMethodType::EcdsaSecp256k1VerificationKey2019, controller: did.clone(),
486 verification_material: VerificationMaterial::Multibase {
487 public_key_multibase: multibase_encoded.clone(),
488 },
489 };
490
491 let did_doc = crate::did::DIDDoc {
493 id: did.clone(),
494 verification_method: vec![verification_method],
495 authentication: vec![vm_id],
496 key_agreement: Vec::new(),
497 assertion_method: Vec::new(),
498 capability_invocation: Vec::new(),
499 capability_delegation: Vec::new(),
500 service: Vec::new(),
501 };
502
503 GeneratedKey {
505 key_type: crate::did::KeyType::P256,
506 did: did.clone(),
507 public_key,
508 private_key: private_key.to_vec(),
509 did_doc,
510 }
511 }
512 crate::did::KeyType::Secp256k1 => {
513 if private_key.len() != 32 {
514 return Err(Error::Validation(format!(
515 "Invalid Secp256k1 private key length: {}, expected 32 bytes",
516 private_key.len()
517 )));
518 }
519
520 let signing_key = match k256::ecdsa::SigningKey::from_slice(private_key) {
522 Ok(key) => key,
523 Err(e) => {
524 return Err(Error::Cryptography(format!(
525 "Failed to create Secp256k1 signing key: {:?}",
526 e
527 )))
528 }
529 };
530
531 let public_key = signing_key
533 .verifying_key()
534 .to_encoded_point(false)
535 .to_bytes()
536 .to_vec();
537
538 let mut prefixed_key = vec![0xe7, 0x01];
541 prefixed_key.extend_from_slice(&public_key);
542
543 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
545 let did = format!("did:key:{}", multibase_encoded);
546
547 let vm_id = format!("{}#{}", did, multibase_encoded);
549
550 let verification_method = VerificationMethod {
552 id: vm_id.clone(),
553 type_: VerificationMethodType::EcdsaSecp256k1VerificationKey2019,
554 controller: did.clone(),
555 verification_material: VerificationMaterial::Multibase {
556 public_key_multibase: multibase_encoded.clone(),
557 },
558 };
559
560 let did_doc = crate::did::DIDDoc {
562 id: did.clone(),
563 verification_method: vec![verification_method],
564 authentication: vec![vm_id],
565 key_agreement: Vec::new(),
566 assertion_method: Vec::new(),
567 capability_invocation: Vec::new(),
568 capability_delegation: Vec::new(),
569 service: Vec::new(),
570 };
571
572 GeneratedKey {
574 key_type: crate::did::KeyType::Secp256k1,
575 did: did.clone(),
576 public_key,
577 private_key: private_key.to_vec(),
578 did_doc,
579 }
580 }
581 };
582
583 let did_generator = DIDKeyGenerator::new();
585 let _secret = did_generator.create_secret_from_key(&generated_key);
586
587 key_manager.add_key(&generated_key)?;
589
590 let config = AgentConfig::new(generated_key.did.clone()).with_debug(debug);
592
593 #[cfg(all(not(target_arch = "wasm32"), test))]
595 {
596 let resolver = Arc::new(crate::did::MultiResolver::default());
598 let agent = Self::new_with_resolver(config, Arc::new(key_manager), resolver);
599 Ok((agent, generated_key.did))
600 }
601
602 #[cfg(all(not(target_arch = "wasm32"), not(test)))]
603 {
604 let agent = Self::new(config, Arc::new(key_manager));
605 Ok((agent, generated_key.did))
606 }
607
608 #[cfg(target_arch = "wasm32")]
609 {
610 let agent = Self::new(config, Arc::new(key_manager));
611 Ok((agent, generated_key.did))
612 }
613 }
614
615 #[cfg(not(target_arch = "wasm32"))]
630 fn determine_security_mode<T: TapMessageBody>(&self) -> SecurityMode {
631 if let Some(ref mode) = self.config.security_mode {
633 if mode.to_uppercase() == "AUTHCRYPT" {
634 return SecurityMode::AuthCrypt;
635 } else {
636 return SecurityMode::Signed;
638 }
639 }
640
641 let message_type = T::message_type();
643 if message_type == crate::message::PRESENTATION_MESSAGE_TYPE {
644 SecurityMode::AuthCrypt
645 } else {
646 SecurityMode::Signed
647 }
648 }
649
650 #[cfg(all(feature = "native", not(target_arch = "wasm32")))]
659 pub async fn send_to_endpoint(&self, packed_message: &str, endpoint: &str) -> Result<u16> {
660 let client = self
662 .http_client
663 .as_ref()
664 .ok_or_else(|| Error::Networking("HTTP client not available".to_string()))?;
665
666 let response = client
668 .post(endpoint)
669 .header("Content-Type", "application/didcomm-encrypted+json")
670 .body(packed_message.to_string())
671 .send()
672 .await
673 .map_err(|e| Error::Networking(format!("Failed to send message to endpoint: {}", e)))?;
674
675 let status = response.status().as_u16();
677
678 println!("Message sent to endpoint {}, status: {}", endpoint, status);
680
681 Ok(status)
682 }
683
684 #[cfg(any(not(feature = "native"), target_arch = "wasm32"))]
685 pub async fn send_to_endpoint(&self, _packed_message: &str, _endpoint: &str) -> Result<u16> {
686 Err(crate::error::Error::NotImplemented(
688 "HTTP client not available".to_string(),
689 ))
690 }
691}
692
693#[async_trait]
694#[cfg(not(target_arch = "wasm32"))]
695impl crate::agent::Agent for TapAgent {
696 fn get_agent_did(&self) -> &str {
697 &self.config.agent_did
698 }
699
700 async fn get_service_endpoint(&self, to: &str) -> Result<Option<String>> {
701 if to.starts_with("http://") || to.starts_with("https://") {
703 return Ok(Some(to.to_string()));
704 }
705
706 if to.starts_with("did:") {
708 #[cfg(test)]
713 if let Some(resolver) = self.resolver.as_ref() {
714 if let Ok(Some(did_doc)) = resolver.resolve(to).await {
715 if let Some(service) = did_doc
717 .service
718 .iter()
719 .find(|s| s.type_ == "DIDCommMessaging")
720 {
721 return Ok(Some(service.service_endpoint.clone()));
722 }
723
724 if let Some(service) = did_doc.service.iter().find(|s| s.type_ == "Web") {
726 return Ok(Some(service.service_endpoint.clone()));
727 }
728
729 if !did_doc.service.is_empty() {
731 return Ok(Some(did_doc.service[0].service_endpoint.clone()));
733 }
734 }
735 }
736
737 return Ok(Some(format!(
739 "https://example.com/did/{}",
740 to.replace(":", "_")
741 )));
742 }
743
744 Ok(None)
746 }
747
748 async fn send_message<
749 T: TapMessageBody + serde::Serialize + Send + Sync + std::fmt::Debug + 'static,
750 >(
751 &self,
752 message: &T,
753 to: Vec<&str>,
754 deliver: bool,
755 ) -> Result<(String, Vec<DeliveryResult>)> {
756 if to.is_empty() {
757 return Err(Error::Validation("No recipients specified".to_string()));
758 }
759
760 println!("\n==== SENDING TAP MESSAGE ====");
762 println!("Message Type: {}", T::message_type());
763 println!("Recipients: {:?}", to);
764 println!(
765 "--- PLAINTEXT CONTENT ---\n{}",
766 serde_json::to_string_pretty(message).unwrap_or_else(|_| format!("{:?}", message))
767 );
768
769 let plain_message =
771 message.to_didcomm_with_route(self.get_agent_did(), to.iter().copied())?;
772
773 let security_mode = self.determine_security_mode::<T>();
775 println!("Security Mode: {:?}", security_mode);
776
777 for recipient in &to {
779 if let Ok(Some(endpoint)) = self.get_service_endpoint(recipient).await {
780 println!("Found service endpoint for {}: {}", recipient, endpoint);
781 }
782 }
783
784 let pack_options = PackOptions {
786 security_mode,
787 sender_kid: Some(format!("{}#keys-1", self.get_agent_did())),
788 recipient_kid: if to.len() == 1 {
789 Some(format!("{}#keys-1", to[0]))
790 } else {
791 None
792 },
793 };
794
795 let packed = plain_message.pack(&*self.key_manager, pack_options).await?;
797
798 println!("--- PACKED MESSAGE ---");
800 println!(
801 "{}",
802 serde_json::from_str::<Value>(&packed)
803 .map(|v| serde_json::to_string_pretty(&v).unwrap_or(packed.clone()))
804 .unwrap_or(packed.clone())
805 );
806 println!("=====================");
807
808 if !deliver {
810 return Ok((packed, Vec::new()));
811 }
812
813 let mut delivery_results = Vec::new();
815
816 for recipient in &to {
817 match self.get_service_endpoint(recipient).await {
818 Ok(Some(endpoint)) => {
819 println!("Delivering message to {} at {}", recipient, endpoint);
820
821 let message_id = match serde_json::from_str::<Value>(&packed) {
823 Ok(json) => json
824 .get("id")
825 .and_then(|id| id.as_str())
826 .map(String::from)
827 .unwrap_or_else(|| "unknown".to_string()),
828 Err(_) => "unknown".to_string(),
829 };
830
831 match self.send_to_endpoint(&packed, &endpoint).await {
833 Ok(status) => {
834 println!(
835 "✅ Delivered message {} to {} at {}",
836 message_id, recipient, endpoint
837 );
838
839 delivery_results.push(DeliveryResult {
840 did: recipient.to_string(),
841 endpoint: endpoint.clone(),
842 status: Some(status),
843 error: None,
844 });
845 }
846 Err(e) => {
847 let error_msg = format!(
849 "Failed to deliver message {} to {} at {}: {}",
850 message_id, recipient, endpoint, e
851 );
852 println!("❌ {}", error_msg);
853
854 delivery_results.push(DeliveryResult {
855 did: recipient.to_string(),
856 endpoint: endpoint.clone(),
857 status: None,
858 error: Some(error_msg),
859 });
860 }
861 }
862 }
863 Ok(None) => {
864 println!(
865 "⚠️ No service endpoint found for {}, skipping delivery",
866 recipient
867 );
868 }
869 Err(e) => {
870 let error_msg = format!(
872 "Failed to resolve service endpoint for {}: {}",
873 recipient, e
874 );
875 println!("❌ {}", error_msg);
876 }
877 }
878 }
879
880 Ok((packed, delivery_results))
881 }
882
883 async fn receive_message<T: TapMessageBody + DeserializeOwned + Send>(
884 &self,
885 packed_message: &str,
886 ) -> Result<T> {
887 println!("\n==== RECEIVING TAP MESSAGE ====");
889 println!("--- PACKED MESSAGE ---");
890 println!(
891 "{}",
892 serde_json::from_str::<Value>(packed_message)
893 .map(|v| serde_json::to_string_pretty(&v).unwrap_or(packed_message.to_string()))
894 .unwrap_or(packed_message.to_string())
895 );
896 println!("---------------------");
897
898 let unpack_options = UnpackOptions {
900 expected_security_mode: SecurityMode::Any,
901 expected_recipient_kid: Some(format!("{}#keys-1", self.get_agent_did())),
902 require_signature: false,
903 };
904
905 let plain_message: PlainMessage = String::unpack(
907 &packed_message.to_string(),
908 &*self.key_manager,
909 unpack_options,
910 )
911 .await?;
912
913 println!("--- UNPACKED CONTENT ---");
915 println!(
916 "{}",
917 serde_json::to_string_pretty(&plain_message)
918 .unwrap_or_else(|_| format!("{:?}", plain_message))
919 );
920 println!("------------------------");
921
922 let message_type = &plain_message.type_;
924
925 if message_type != T::message_type() {
927 println!(
928 "❌ Message type validation failed: expected {}, got {}",
929 T::message_type(),
930 message_type
931 );
932 return Err(Error::Validation(format!(
933 "Expected message type {} but got {}",
934 T::message_type(),
935 message_type
936 )));
937 }
938 println!("✅ Message type validation passed: {}", message_type);
939
940 serde_json::from_value::<T>(plain_message.body.clone())
942 .map_err(|e| Error::Serialization(format!("Failed to deserialize message: {}", e)))
943 }
944}