1use std::collections::HashMap;
8use std::sync::Arc;
9
10use async_trait::async_trait;
11
12use bsv::primitives::public_key::PublicKey;
13use bsv::services::overlay_tools::LookupResolver;
14use bsv::transaction::beef_party::BeefParty;
15use bsv::wallet::cached_key_deriver::CachedKeyDeriver;
16use bsv::wallet::error::WalletError as SdkWalletError;
17use bsv::wallet::interfaces::{
18 AbortActionArgs, AbortActionResult, AcquireCertificateArgs, AcquisitionProtocol,
19 AuthenticatedResult, Certificate, CreateActionArgs, CreateActionOptions, CreateActionResult,
20 CreateHmacArgs, CreateHmacResult, CreateSignatureArgs, CreateSignatureResult, DecryptArgs,
21 DecryptResult, DiscoverByAttributesArgs, DiscoverByIdentityKeyArgs, DiscoverCertificatesResult,
22 EncryptArgs, EncryptResult, GetHeaderArgs, GetHeaderResult, GetHeightResult, GetNetworkResult,
23 GetPublicKeyArgs, GetPublicKeyResult, GetVersionResult, InternalizeActionArgs,
24 InternalizeActionResult, ListActionsArgs, ListActionsResult, ListCertificatesArgs,
25 ListCertificatesResult, ListOutputsArgs, ListOutputsResult, Network, ProveCertificateArgs,
26 ProveCertificateResult, RelinquishCertificateArgs, RelinquishCertificateResult,
27 RelinquishOutputArgs, RelinquishOutputResult, RevealCounterpartyKeyLinkageArgs,
28 RevealCounterpartyKeyLinkageResult, RevealSpecificKeyLinkageArgs,
29 RevealSpecificKeyLinkageResult, SignActionArgs, SignActionOptions, SignActionResult, TrustSelf,
30 VerifyHmacArgs, VerifyHmacResult, VerifySignatureArgs, VerifySignatureResult, WalletInterface,
31};
32use bsv::wallet::proto_wallet::ProtoWallet;
33
34use crate::wallet::discovery::OverlayCache;
35
36use crate::error::WalletError;
37use crate::services::traits::WalletServices;
38use crate::signer::default_signer::DefaultWalletSigner;
39use crate::signer::traits::WalletSigner;
40use crate::storage::manager::WalletStorageManager;
41use crate::storage::traits::provider::StorageProvider;
42use crate::types::Chain;
43use crate::wallet::privileged::PrivilegedKeyManager;
44use crate::wallet::settings::WalletSettingsManager;
45use crate::wallet::types::{
46 AdminStatsResult, AuthId, KeyPair, PendingSignAction, StorageIdentity, UtxoInfo, WalletArgs,
47 WalletBalance, SPEC_OP_FAILED_ACTIONS, SPEC_OP_INVALID_CHANGE, SPEC_OP_NO_SEND_ACTIONS,
48 SPEC_OP_SET_WALLET_CHANGE_PARAMS, SPEC_OP_WALLET_BALANCE,
49};
50use crate::wallet::validation::validate_originator;
51
52pub struct Wallet {
84 pub chain: Chain,
86 pub key_deriver: Arc<CachedKeyDeriver>,
88 pub storage: WalletStorageManager,
90 pub services: Option<Arc<dyn WalletServices>>,
92 pub monitor: Option<Arc<crate::monitor::Monitor>>,
94 pub privileged_key_manager: Option<Arc<dyn PrivilegedKeyManager>>,
96 pub settings_manager: WalletSettingsManager,
98 pub identity_key: PublicKey,
100 pub proto: ProtoWallet,
102
103 beef: tokio::sync::Mutex<BeefParty>,
105 pub include_all_source_transactions: bool,
107 pub auto_known_txids: bool,
109 pub return_txid_only: bool,
111 pub trust_self: Option<TrustSelf>,
113 user_party: String,
114
115 pub pending_sign_actions: tokio::sync::Mutex<HashMap<String, PendingSignAction>>,
117
118 overlay_cache: OverlayCache,
120 pub lookup_resolver: Option<Arc<LookupResolver>>,
122
123 pub random_vals: Option<Vec<f64>>,
125
126 signer: DefaultWalletSigner,
128}
129
130impl Wallet {
135 pub fn new(args: WalletArgs) -> Result<Self, WalletError> {
139 let identity_key = args.key_deriver.identity_key();
141 let identity_key_hex = identity_key.to_der_hex();
142 let storage_auth_id = args.storage.auth_id().to_string();
143 if identity_key_hex != storage_auth_id {
144 return Err(WalletError::InvalidParameter {
145 parameter: "key_deriver".to_string(),
146 must_be: format!(
147 "consistent with storage auth_id. key_deriver identity_key={} but storage auth_id={}",
148 identity_key_hex, storage_auth_id
149 ),
150 });
151 }
152
153 let root_key = args.key_deriver.root_key().clone();
155 let proto = ProtoWallet::new(root_key);
156
157 let root_pub_hex = args.key_deriver.root_key().to_public_key().to_der_hex();
159 let user_party = format!("user {}", root_pub_hex);
160
161 let beef = BeefParty::new([user_party.clone()]);
163
164 let services_for_signer = args.services.clone().ok_or_else(|| {
166 WalletError::InvalidOperation(
167 "WalletServices required for Wallet construction".to_string(),
168 )
169 })?;
170
171 let signer = DefaultWalletSigner::new(
173 Arc::new(WalletStorageManager::new(
174 identity_key_hex.clone(),
175 args.storage.active().cloned(),
176 args.storage.backups().to_vec(),
177 )),
178 services_for_signer,
179 args.key_deriver.clone(),
180 args.chain.clone(),
181 identity_key.clone(),
182 );
183
184 let settings_manager = args.settings_manager.unwrap_or_else(|| {
186 let active_provider = args
189 .storage
190 .active()
191 .cloned()
192 .expect("WalletStorageManager must have at least one storage provider");
193 WalletSettingsManager::new(active_provider)
194 });
195
196 Ok(Wallet {
197 chain: args.chain,
198 key_deriver: args.key_deriver,
199 storage: args.storage,
200 services: args.services,
201 monitor: args.monitor,
202 privileged_key_manager: args.privileged_key_manager,
203 settings_manager,
204 identity_key,
205 proto,
206 beef: tokio::sync::Mutex::new(beef),
207 include_all_source_transactions: true,
208 auto_known_txids: false,
209 return_txid_only: false,
210 trust_self: Some(TrustSelf::Known),
211 user_party,
212 pending_sign_actions: tokio::sync::Mutex::new(HashMap::new()),
213 overlay_cache: OverlayCache::new(),
214 lookup_resolver: args.lookup_resolver,
215 random_vals: None,
216 signer,
217 })
218 }
219
220 fn auth_id(&self) -> AuthId {
222 AuthId {
223 identity_key: self.identity_key.to_der_hex(),
224 user_id: None,
225 is_active: None,
226 }
227 }
228
229 fn validate_originator(&self, originator: Option<&str>) -> Result<(), WalletError> {
231 validate_originator(originator)
232 }
233
234 fn get_services(&self) -> Result<&Arc<dyn WalletServices>, WalletError> {
236 self.services.as_ref().ok_or_else(|| {
237 WalletError::InvalidOperation("Wallet services not configured".to_string())
238 })
239 }
240
241 pub fn get_client_change_key_pair(&self) -> KeyPair {
243 let root = self.key_deriver.root_key();
244 KeyPair {
245 private_key: root.to_hex(),
246 public_key: root.to_public_key().to_der_hex(),
247 }
248 }
249
250 pub async fn get_storage_identity(&self) -> StorageIdentity {
255 let key = self
256 .storage
257 .get_storage_identity_key()
258 .await
259 .unwrap_or_else(|_| self.identity_key.to_der_hex());
260 StorageIdentity {
261 storage_identity_key: key,
262 storage_name: "default".to_string(),
263 }
264 }
265
266 pub async fn storage_party(&self) -> String {
268 let si = self.get_storage_identity().await;
269 format!("storage {}", si.storage_identity_key)
270 }
271
272 pub async fn get_identity_key(&self) -> Result<String, SdkWalletError> {
274 let result = self
275 .get_public_key(
276 GetPublicKeyArgs {
277 identity_key: true,
278 protocol_id: None,
279 key_id: None,
280 counterparty: None,
281 privileged: false,
282 privileged_reason: None,
283 for_self: None,
284 seek_permission: None,
285 },
286 None,
287 )
288 .await?;
289 Ok(result.public_key.to_der_hex())
290 }
291
292 pub async fn destroy(&self) -> Result<(), WalletError> {
294 self.storage.destroy().await?;
295 if let Some(ref pkm) = self.privileged_key_manager {
296 pkm.destroy_key().await.map_err(|e| {
297 WalletError::Internal(format!("Failed to destroy privileged key: {}", e))
298 })?;
299 }
300 Ok(())
301 }
302
303 pub async fn balance(&self, args: Option<ListOutputsArgs>) -> Result<u64, WalletError> {
313 let args = match args {
314 Some(mut a) => {
315 if a.basket != SPEC_OP_WALLET_BALANCE {
316 a.tags.push(SPEC_OP_WALLET_BALANCE.to_string());
317 }
318 a
319 }
320 None => ListOutputsArgs {
321 basket: SPEC_OP_WALLET_BALANCE.to_string(),
322 tags: vec![],
323 tag_query_mode: None,
324 include: None,
325 include_custom_instructions: Default::default(),
326 include_tags: Default::default(),
327 include_labels: Default::default(),
328 limit: None,
329 offset: None,
330 seek_permission: Default::default(),
331 },
332 };
333
334 let r = self
335 .list_outputs(args, None)
336 .await
337 .map_err(|e| WalletError::Internal(e.to_string()))?;
338 Ok(r.total_outputs as u64)
339 }
340
341 pub async fn balance_and_utxos(
345 &self,
346 args: Option<ListOutputsArgs>,
347 ) -> Result<WalletBalance, WalletError> {
348 let args = match args {
349 Some(mut a) => {
350 if a.basket != SPEC_OP_WALLET_BALANCE {
351 a.tags.push(SPEC_OP_WALLET_BALANCE.to_string());
352 }
353 a
354 }
355 None => ListOutputsArgs {
356 basket: SPEC_OP_WALLET_BALANCE.to_string(),
357 tags: vec![],
358 tag_query_mode: None,
359 include: None,
360 include_custom_instructions: Default::default(),
361 include_tags: Default::default(),
362 include_labels: Default::default(),
363 limit: None,
364 offset: None,
365 seek_permission: Default::default(),
366 },
367 };
368
369 let r = self
370 .list_outputs(args, None)
371 .await
372 .map_err(|e| WalletError::Internal(e.to_string()))?;
373
374 let utxos: Vec<UtxoInfo> = r
375 .outputs
376 .iter()
377 .map(|o| UtxoInfo {
378 satoshis: o.satoshis,
379 outpoint: o.outpoint.clone(),
380 })
381 .collect();
382
383 Ok(WalletBalance {
384 total: r.total_outputs as u64,
385 utxos,
386 })
387 }
388
389 pub async fn sweep_to(&self, to_wallet: &Wallet) -> Result<(), WalletError> {
394 use crate::storage::methods::generate_change::MAX_POSSIBLE_SATOSHIS;
395 use crate::utility::script_template_brc29::ScriptTemplateBRC29;
396 use bsv::wallet::types::BooleanDefaultFalse;
397
398 let derivation_prefix = random_base64(8);
400 let derivation_suffix = random_base64(8);
401
402 let template =
403 ScriptTemplateBRC29::new(derivation_prefix.clone(), derivation_suffix.clone());
404
405 let sender_priv = self.key_deriver.root_key().clone();
407 let receiver_pub = to_wallet.identity_key.clone();
408 let lock_script = template.lock(&sender_priv, &receiver_pub)?;
409
410 let custom_instructions = serde_json::json!({
411 "derivationPrefix": derivation_prefix,
412 "derivationSuffix": derivation_suffix,
413 "type": "BRC29"
414 })
415 .to_string();
416
417 let car = self
418 .create_action(
419 CreateActionArgs {
420 description: "sweep".to_string(),
421 input_beef: None,
422 inputs: vec![],
423 outputs: vec![bsv::wallet::interfaces::CreateActionOutput {
424 locking_script: Some(lock_script),
425 satoshis: MAX_POSSIBLE_SATOSHIS,
426 output_description: "sweep".to_string(),
427 basket: None,
428 custom_instructions: Some(custom_instructions),
429 tags: vec!["relinquish".to_string()],
430 }],
431 lock_time: None,
432 version: None,
433 labels: vec!["sweep".to_string()],
434 options: Some(CreateActionOptions {
435 randomize_outputs: bsv::wallet::types::BooleanDefaultTrue(Some(false)),
436 accept_delayed_broadcast: bsv::wallet::types::BooleanDefaultTrue(Some(
437 false,
438 )),
439 ..Default::default()
440 }),
441 reference: None,
442 },
443 None,
444 )
445 .await
446 .map_err(|e| WalletError::Internal(e.to_string()))?;
447
448 let tx = car.tx.ok_or_else(|| {
449 WalletError::Internal("sweep createAction returned no tx".to_string())
450 })?;
451
452 to_wallet
454 .internalize_action(
455 InternalizeActionArgs {
456 tx,
457 description: "sweep".to_string(),
458 labels: vec!["sweep".to_string()],
459 seek_permission: bsv::wallet::types::BooleanDefaultTrue(Some(false)),
460 outputs: vec![bsv::wallet::interfaces::InternalizeOutput::WalletPayment {
461 output_index: 0,
462 payment: bsv::wallet::interfaces::Payment {
463 derivation_prefix: derivation_prefix.into_bytes(),
464 derivation_suffix: derivation_suffix.into_bytes(),
465 sender_identity_key: self.identity_key.clone(),
466 },
467 }],
468 },
469 None,
470 )
471 .await
472 .map_err(|e| WalletError::Internal(e.to_string()))?;
473
474 Ok(())
475 }
476
477 pub async fn review_spendable_outputs(
482 &self,
483 release: bool,
484 all: bool,
485 ) -> Result<ListOutputsResult, WalletError> {
486 let mut tags = Vec::new();
487 if release {
488 tags.push("release".to_string());
489 }
490 if all {
491 tags.push("all".to_string());
492 }
493
494 let args = ListOutputsArgs {
495 basket: SPEC_OP_INVALID_CHANGE.to_string(),
496 tags,
497 tag_query_mode: None,
498 include: None,
499 include_custom_instructions: Default::default(),
500 include_tags: Default::default(),
501 include_labels: Default::default(),
502 limit: None,
503 offset: None,
504 seek_permission: Default::default(),
505 };
506
507 self.list_outputs(args, None)
508 .await
509 .map_err(|e| WalletError::Internal(e.to_string()))
510 }
511
512 pub async fn set_wallet_change_params(
516 &self,
517 count: u32,
518 satoshis: u64,
519 ) -> Result<(), WalletError> {
520 let args = ListOutputsArgs {
521 basket: SPEC_OP_SET_WALLET_CHANGE_PARAMS.to_string(),
522 tags: vec![count.to_string(), satoshis.to_string()],
523 tag_query_mode: None,
524 include: None,
525 include_custom_instructions: Default::default(),
526 include_tags: Default::default(),
527 include_labels: Default::default(),
528 limit: None,
529 offset: None,
530 seek_permission: Default::default(),
531 };
532
533 let _ = self
534 .list_outputs(args, None)
535 .await
536 .map_err(|e| WalletError::Internal(e.to_string()))?;
537 Ok(())
538 }
539
540 pub async fn list_no_send_actions(
544 &self,
545 abort: bool,
546 ) -> Result<ListActionsResult, WalletError> {
547 let mut labels = vec![SPEC_OP_NO_SEND_ACTIONS.to_string()];
548 if abort {
549 labels.push("abort".to_string());
550 }
551
552 let args = ListActionsArgs {
553 labels,
554 label_query_mode: None,
555 include_labels: Default::default(),
556 include_inputs: Default::default(),
557 include_input_source_locking_scripts: Default::default(),
558 include_input_unlocking_scripts: Default::default(),
559 include_outputs: Default::default(),
560 include_output_locking_scripts: Default::default(),
561 limit: None,
562 offset: None,
563 seek_permission: Default::default(),
564 };
565
566 self.list_actions(args, None)
567 .await
568 .map_err(|e| WalletError::Internal(e.to_string()))
569 }
570
571 pub async fn list_failed_actions(
575 &self,
576 unfail: bool,
577 ) -> Result<ListActionsResult, WalletError> {
578 let mut labels = vec![SPEC_OP_FAILED_ACTIONS.to_string()];
579 if unfail {
580 labels.push("unfail".to_string());
581 }
582
583 let args = ListActionsArgs {
584 labels,
585 label_query_mode: None,
586 include_labels: Default::default(),
587 include_inputs: Default::default(),
588 include_input_source_locking_scripts: Default::default(),
589 include_input_unlocking_scripts: Default::default(),
590 include_outputs: Default::default(),
591 include_output_locking_scripts: Default::default(),
592 limit: None,
593 offset: None,
594 seek_permission: Default::default(),
595 };
596
597 self.list_actions(args, None)
598 .await
599 .map_err(|e| WalletError::Internal(e.to_string()))
600 }
601
602 pub async fn admin_stats(&self) -> Result<AdminStatsResult, WalletError> {
606 let identity_key_hex = self.identity_key.to_der_hex();
607 self.storage.admin_stats(&identity_key_hex).await
608 }
609}
610
611fn random_base64(n: usize) -> String {
613 use base64::Engine;
614 use rand::RngCore;
615 let mut buf = vec![0u8; n];
616 rand::thread_rng().fill_bytes(&mut buf);
617 base64::engine::general_purpose::STANDARD.encode(&buf)
618}
619
620fn to_sdk_error(e: WalletError) -> SdkWalletError {
625 match e {
626 WalletError::InvalidParameter { parameter, must_be } => SdkWalletError::InvalidParameter(
627 format!("The {} parameter must be {}", parameter, must_be),
628 ),
629 WalletError::NotImplemented(msg) => SdkWalletError::NotImplemented(msg),
630 WalletError::InvalidOperation(msg) => SdkWalletError::Internal(msg),
631 _ => SdkWalletError::Internal(e.to_string()),
632 }
633}
634
635#[async_trait]
640impl WalletInterface for Wallet {
641 async fn get_public_key(
646 &self,
647 args: GetPublicKeyArgs,
648 originator: Option<&str>,
649 ) -> Result<GetPublicKeyResult, SdkWalletError> {
650 self.validate_originator(originator).map_err(to_sdk_error)?;
651 bsv::wallet::validation::validate_get_public_key_args(&args)?;
652
653 if args.privileged {
654 if let Some(ref pkm) = self.privileged_key_manager {
655 return pkm.get_public_key(args).await;
656 }
657 return Err(SdkWalletError::Internal(
658 "No privileged key manager configured".to_string(),
659 ));
660 }
661 self.proto.get_public_key(args, originator).await
662 }
663
664 async fn encrypt(
665 &self,
666 args: EncryptArgs,
667 originator: Option<&str>,
668 ) -> Result<EncryptResult, SdkWalletError> {
669 self.validate_originator(originator).map_err(to_sdk_error)?;
670 bsv::wallet::validation::validate_encrypt_args(&args)?;
671
672 if args.privileged {
673 if let Some(ref pkm) = self.privileged_key_manager {
674 return pkm.encrypt(args).await;
675 }
676 return Err(SdkWalletError::Internal(
677 "No privileged key manager configured".to_string(),
678 ));
679 }
680 self.proto.encrypt(args, originator).await
681 }
682
683 async fn decrypt(
684 &self,
685 args: DecryptArgs,
686 originator: Option<&str>,
687 ) -> Result<DecryptResult, SdkWalletError> {
688 self.validate_originator(originator).map_err(to_sdk_error)?;
689 bsv::wallet::validation::validate_decrypt_args(&args)?;
690
691 if args.privileged {
692 if let Some(ref pkm) = self.privileged_key_manager {
693 return pkm.decrypt(args).await;
694 }
695 return Err(SdkWalletError::Internal(
696 "No privileged key manager configured".to_string(),
697 ));
698 }
699 self.proto.decrypt(args, originator).await
700 }
701
702 async fn create_hmac(
703 &self,
704 args: CreateHmacArgs,
705 originator: Option<&str>,
706 ) -> Result<CreateHmacResult, SdkWalletError> {
707 self.validate_originator(originator).map_err(to_sdk_error)?;
708 bsv::wallet::validation::validate_create_hmac_args(&args)?;
709
710 if args.privileged {
711 if let Some(ref pkm) = self.privileged_key_manager {
712 return pkm.create_hmac(args).await;
713 }
714 return Err(SdkWalletError::Internal(
715 "No privileged key manager configured".to_string(),
716 ));
717 }
718 self.proto.create_hmac(args, originator).await
719 }
720
721 async fn verify_hmac(
722 &self,
723 args: VerifyHmacArgs,
724 originator: Option<&str>,
725 ) -> Result<VerifyHmacResult, SdkWalletError> {
726 self.validate_originator(originator).map_err(to_sdk_error)?;
727 bsv::wallet::validation::validate_verify_hmac_args(&args)?;
728
729 if args.privileged {
730 if let Some(ref pkm) = self.privileged_key_manager {
731 return pkm.verify_hmac(args).await;
732 }
733 return Err(SdkWalletError::Internal(
734 "No privileged key manager configured".to_string(),
735 ));
736 }
737 self.proto.verify_hmac(args, originator).await
738 }
739
740 async fn create_signature(
741 &self,
742 args: CreateSignatureArgs,
743 originator: Option<&str>,
744 ) -> Result<CreateSignatureResult, SdkWalletError> {
745 self.validate_originator(originator).map_err(to_sdk_error)?;
746 bsv::wallet::validation::validate_create_signature_args(&args)?;
747
748 if args.privileged {
749 if let Some(ref pkm) = self.privileged_key_manager {
750 return pkm.create_signature(args).await;
751 }
752 return Err(SdkWalletError::Internal(
753 "No privileged key manager configured".to_string(),
754 ));
755 }
756 self.proto.create_signature(args, originator).await
757 }
758
759 async fn verify_signature(
760 &self,
761 args: VerifySignatureArgs,
762 originator: Option<&str>,
763 ) -> Result<VerifySignatureResult, SdkWalletError> {
764 self.validate_originator(originator).map_err(to_sdk_error)?;
765 bsv::wallet::validation::validate_verify_signature_args(&args)?;
766
767 if args.privileged {
768 if let Some(ref pkm) = self.privileged_key_manager {
769 return pkm.verify_signature(args).await;
770 }
771 return Err(SdkWalletError::Internal(
772 "No privileged key manager configured".to_string(),
773 ));
774 }
775 self.proto.verify_signature(args, originator).await
776 }
777
778 async fn reveal_counterparty_key_linkage(
779 &self,
780 args: RevealCounterpartyKeyLinkageArgs,
781 originator: Option<&str>,
782 ) -> Result<RevealCounterpartyKeyLinkageResult, SdkWalletError> {
783 self.validate_originator(originator).map_err(to_sdk_error)?;
784 bsv::wallet::validation::validate_reveal_counterparty_key_linkage_args(&args)?;
785
786 if args.privileged.unwrap_or(false) {
787 if let Some(ref pkm) = self.privileged_key_manager {
788 return pkm.reveal_counterparty_key_linkage(args).await;
789 }
790 return Err(SdkWalletError::Internal(
791 "No privileged key manager configured".to_string(),
792 ));
793 }
794 self.proto
795 .reveal_counterparty_key_linkage(args, originator)
796 .await
797 }
798
799 async fn reveal_specific_key_linkage(
800 &self,
801 args: RevealSpecificKeyLinkageArgs,
802 originator: Option<&str>,
803 ) -> Result<RevealSpecificKeyLinkageResult, SdkWalletError> {
804 self.validate_originator(originator).map_err(to_sdk_error)?;
805 bsv::wallet::validation::validate_reveal_specific_key_linkage_args(&args)?;
806
807 if args.privileged.unwrap_or(false) {
808 if let Some(ref pkm) = self.privileged_key_manager {
809 return pkm.reveal_specific_key_linkage(args).await;
810 }
811 return Err(SdkWalletError::Internal(
812 "No privileged key manager configured".to_string(),
813 ));
814 }
815 self.proto
816 .reveal_specific_key_linkage(args, originator)
817 .await
818 }
819
820 async fn is_authenticated(
825 &self,
826 originator: Option<&str>,
827 ) -> Result<AuthenticatedResult, SdkWalletError> {
828 self.validate_originator(originator).map_err(to_sdk_error)?;
829 Ok(AuthenticatedResult {
830 authenticated: true,
831 })
832 }
833
834 async fn wait_for_authentication(
835 &self,
836 originator: Option<&str>,
837 ) -> Result<AuthenticatedResult, SdkWalletError> {
838 self.validate_originator(originator).map_err(to_sdk_error)?;
839 Ok(AuthenticatedResult {
840 authenticated: true,
841 })
842 }
843
844 async fn get_height(
845 &self,
846 originator: Option<&str>,
847 ) -> Result<GetHeightResult, SdkWalletError> {
848 self.validate_originator(originator).map_err(to_sdk_error)?;
849 let services = self.get_services().map_err(to_sdk_error)?;
850 let height = services
851 .get_height()
852 .await
853 .map_err(|e| SdkWalletError::Internal(e.to_string()))?;
854 Ok(GetHeightResult { height })
855 }
856
857 async fn get_header_for_height(
858 &self,
859 args: GetHeaderArgs,
860 originator: Option<&str>,
861 ) -> Result<GetHeaderResult, SdkWalletError> {
862 self.validate_originator(originator).map_err(to_sdk_error)?;
863 bsv::wallet::validation::validate_get_header_args(&args)?;
864 let services = self.get_services().map_err(to_sdk_error)?;
865 let header = services
866 .get_header_for_height(args.height)
867 .await
868 .map_err(|e| SdkWalletError::Internal(e.to_string()))?;
869 Ok(GetHeaderResult { header })
870 }
871
872 async fn get_network(
873 &self,
874 originator: Option<&str>,
875 ) -> Result<GetNetworkResult, SdkWalletError> {
876 self.validate_originator(originator).map_err(to_sdk_error)?;
877 let network = match self.chain {
878 Chain::Main => Network::Mainnet,
879 Chain::Test => Network::Testnet,
880 };
881 Ok(GetNetworkResult { network })
882 }
883
884 async fn get_version(
885 &self,
886 originator: Option<&str>,
887 ) -> Result<GetVersionResult, SdkWalletError> {
888 self.validate_originator(originator).map_err(to_sdk_error)?;
889 Ok(GetVersionResult {
890 version: "wallet-brc100-1.0.0".to_string(),
891 })
892 }
893
894 async fn create_action(
899 &self,
900 args: CreateActionArgs,
901 originator: Option<&str>,
902 ) -> Result<CreateActionResult, SdkWalletError> {
903 self.validate_originator(originator).map_err(to_sdk_error)?;
904 bsv::wallet::validation::validate_create_action_args(&args)?;
905
906 let mut options = args.options.clone().unwrap_or_default();
908
909 if options.trust_self.is_none() {
911 options.trust_self = self.trust_self.clone();
912 }
913
914 if self.auto_known_txids {
916 let mut beef_lock = self.beef.lock().await;
917 let known = crate::wallet::beef_helpers::get_known_txids(
918 &mut beef_lock,
919 Some(&options.known_txids),
920 );
921 options.known_txids = known;
922 }
923
924 let sign_and_process = *options.sign_and_process;
926 let no_send = *options.no_send;
927 let accept_delayed = *options.accept_delayed_broadcast;
928
929 let valid_args = crate::signer::types::ValidCreateActionArgs {
930 description: args.description,
931 inputs: args
932 .inputs
933 .iter()
934 .map(|input| {
935 let parts: Vec<&str> = input.outpoint.rsplitn(2, '.').collect();
936 let (vout_str, txid_str) = if parts.len() == 2 {
937 (parts[0], parts[1])
938 } else {
939 ("0", input.outpoint.as_str())
940 };
941 crate::signer::types::ValidCreateActionInput {
942 outpoint: crate::signer::types::OutpointInfo {
943 txid: txid_str.to_string(),
944 vout: vout_str.parse().unwrap_or(0),
945 },
946 input_description: input.input_description.clone(),
947 unlocking_script: input.unlocking_script.clone(),
948 unlocking_script_length: input.unlocking_script_length.unwrap_or(0)
949 as usize,
950 sequence_number: input.sequence_number.unwrap_or(0xffffffff),
951 }
952 })
953 .collect(),
954 outputs: args.outputs,
955 lock_time: args.lock_time.unwrap_or(0),
956 version: args.version.unwrap_or(1),
957 labels: args.labels,
958 options: options.clone(),
959 input_beef: args.input_beef,
960 is_new_tx: true,
961 is_sign_action: !sign_and_process,
962 is_no_send: no_send,
963 is_delayed: !accept_delayed,
964 is_send_with: !options.send_with.is_empty(),
965 };
966
967 let signer_result = self
968 .signer
969 .create_action(valid_args)
970 .await
971 .map_err(to_sdk_error)?;
972
973 let mut result = CreateActionResult {
975 txid: signer_result.txid,
976 tx: signer_result.tx,
977 no_send_change: signer_result.no_send_change,
978 send_with_results: signer_result.send_with_results,
979 signable_transaction: signer_result.signable_transaction.map(|st| {
980 bsv::wallet::interfaces::SignableTransaction {
981 reference: st.reference.into_bytes(),
982 tx: st.tx,
983 }
984 }),
985 };
986
987 if let Some(ref tx_bytes) = result.tx {
989 let mut beef_lock = self.beef.lock().await;
990 if let Ok(beef) =
991 bsv::transaction::beef::Beef::from_binary(&mut std::io::Cursor::new(tx_bytes))
992 {
993 let _ = beef_lock.beef.merge_beef(&beef);
994 }
995 }
996
997 if let Some(ref mut tx_bytes) = result.tx {
999 let beef_lock = self.beef.lock().await;
1000 let verified = crate::wallet::beef_helpers::verify_returned_txid_only_atomic_beef(
1001 tx_bytes,
1002 &beef_lock,
1003 self.return_txid_only,
1004 None,
1005 )?;
1006 *tx_bytes = verified;
1007 }
1008
1009 crate::wallet::error_helpers::throw_if_any_unsuccessful_create_actions(&result)?;
1011
1012 Ok(result)
1013 }
1014
1015 async fn sign_action(
1016 &self,
1017 args: SignActionArgs,
1018 originator: Option<&str>,
1019 ) -> Result<SignActionResult, SdkWalletError> {
1020 self.validate_originator(originator).map_err(to_sdk_error)?;
1021 bsv::wallet::validation::validate_sign_action_args(&args)?;
1022
1023 let reference = String::from_utf8_lossy(&args.reference).to_string();
1024 let raw_options = &args.options;
1025 let options = raw_options.clone().unwrap_or_default();
1026
1027 let (is_no_send, is_delayed, is_send_with) = match raw_options {
1032 Some(opts) => (
1033 opts.no_send.0,
1034 opts.accept_delayed_broadcast.0.map(|abd| !abd),
1035 if opts.send_with.is_empty() {
1036 None
1037 } else {
1038 Some(true)
1039 },
1040 ),
1041 None => (None, None, None),
1042 };
1043
1044 let valid_args = crate::signer::types::ValidSignActionArgs {
1045 reference: reference.clone(),
1046 spends: args.spends,
1047 options,
1048 is_new_tx: true,
1049 is_no_send,
1050 is_delayed,
1051 is_send_with,
1052 };
1053
1054 let signer_result = self
1055 .signer
1056 .sign_action(valid_args)
1057 .await
1058 .map_err(to_sdk_error)?;
1059
1060 let mut result = SignActionResult {
1061 txid: signer_result.txid,
1062 tx: signer_result.tx,
1063 send_with_results: signer_result.send_with_results,
1064 };
1065
1066 if let Some(ref mut tx_bytes) = result.tx {
1068 let beef_lock = self.beef.lock().await;
1069 let verified = crate::wallet::beef_helpers::verify_returned_txid_only_atomic_beef(
1070 tx_bytes,
1071 &beef_lock,
1072 self.return_txid_only,
1073 None,
1074 )?;
1075 *tx_bytes = verified;
1076 }
1077
1078 crate::wallet::error_helpers::throw_if_any_unsuccessful_sign_actions(&result)?;
1080
1081 Ok(result)
1082 }
1083
1084 async fn internalize_action(
1085 &self,
1086 args: InternalizeActionArgs,
1087 originator: Option<&str>,
1088 ) -> Result<InternalizeActionResult, SdkWalletError> {
1089 self.validate_originator(originator).map_err(to_sdk_error)?;
1090 bsv::wallet::validation::validate_internalize_action_args(&args)?;
1091
1092 for label in &args.labels {
1094 if crate::wallet::types::is_spec_op_throw_label(label) {
1095 return Err(SdkWalletError::Internal(
1096 "WERR_REVIEW_ACTIONS: internalizeAction specOp throw review actions"
1097 .to_string(),
1098 ));
1099 }
1100 }
1101
1102 let valid_args = crate::signer::types::ValidInternalizeActionArgs {
1104 tx: args.tx,
1105 description: args.description,
1106 labels: args.labels,
1107 outputs: args.outputs,
1108 };
1109
1110 let signer_result = self
1111 .signer
1112 .internalize_action(valid_args)
1113 .await
1114 .map_err(to_sdk_error)?;
1115
1116 let result = InternalizeActionResult {
1117 accepted: signer_result.accepted,
1118 };
1119
1120 crate::wallet::error_helpers::throw_if_unsuccessful_internalize_action(&result)?;
1121
1122 Ok(result)
1123 }
1124
1125 async fn abort_action(
1126 &self,
1127 args: AbortActionArgs,
1128 originator: Option<&str>,
1129 ) -> Result<AbortActionResult, SdkWalletError> {
1130 self.validate_originator(originator).map_err(to_sdk_error)?;
1131 bsv::wallet::validation::validate_abort_action_args(&args)?;
1132
1133 let auth = self.auth_id();
1134 self.storage
1135 .abort_action(&auth, &args)
1136 .await
1137 .map_err(to_sdk_error)
1138 }
1139
1140 async fn list_actions(
1145 &self,
1146 args: ListActionsArgs,
1147 originator: Option<&str>,
1148 ) -> Result<ListActionsResult, SdkWalletError> {
1149 self.validate_originator(originator).map_err(to_sdk_error)?;
1150 bsv::wallet::validation::validate_list_actions_args(&args)?;
1151
1152 let auth = self.auth_id();
1153 let mut result = self
1154 .storage
1155 .list_actions(&auth, &args)
1156 .await
1157 .map_err(to_sdk_error)?;
1158
1159 for action in &mut result.actions {
1161 for output in &mut action.outputs {
1162 output.custom_instructions = None;
1163 }
1164 }
1165
1166 Ok(result)
1167 }
1168
1169 async fn list_outputs(
1170 &self,
1171 args: ListOutputsArgs,
1172 originator: Option<&str>,
1173 ) -> Result<ListOutputsResult, SdkWalletError> {
1174 use bsv::transaction::beef::{Beef, BEEF_V2};
1175 use bsv::wallet::interfaces::OutputInclude;
1176 use std::collections::HashSet;
1177 use std::io::Cursor;
1178
1179 self.validate_originator(originator).map_err(to_sdk_error)?;
1180 bsv::wallet::validation::validate_list_outputs_args(&args)?;
1181
1182 let auth = self.auth_id();
1183 let mut result = self
1184 .storage
1185 .list_outputs(&auth, &args)
1186 .await
1187 .map_err(to_sdk_error)?;
1188
1189 if matches!(args.include, Some(OutputInclude::EntireTransactions)) && result.beef.is_none()
1193 {
1194 let mut unique_txids: Vec<String> = Vec::new();
1196 let mut seen: HashSet<String> = HashSet::new();
1197 for output in &result.outputs {
1198 if let Some(dot_pos) = output.outpoint.find('.') {
1199 let txid = output.outpoint[..dot_pos].to_string();
1200 if seen.insert(txid.clone()) {
1201 unique_txids.push(txid);
1202 }
1203 }
1204 }
1205
1206 if !unique_txids.is_empty() {
1207 let beef_trust_self = match &self.trust_self {
1209 Some(TrustSelf::Known) => crate::storage::beef::TrustSelf::Known,
1210 None => crate::storage::beef::TrustSelf::No,
1211 };
1212 let known_txids: HashSet<String> = HashSet::new();
1213 let storage_provider = self.storage.get_active().await.map_err(to_sdk_error)?;
1214
1215 let mut merged_beef = Beef::new(BEEF_V2);
1217 for txid in &unique_txids {
1218 let beef_bytes_opt = crate::storage::beef::get_valid_beef_for_txid(
1219 storage_provider.as_ref(),
1220 txid,
1221 beef_trust_self,
1222 &known_txids,
1223 )
1224 .await
1225 .map_err(to_sdk_error)?;
1226
1227 if let Some(beef_bytes) = beef_bytes_opt {
1228 let mut cursor = Cursor::new(&beef_bytes);
1230 let parsed = Beef::from_binary(&mut cursor).map_err(|e| {
1231 to_sdk_error(crate::error::WalletError::Internal(format!(
1232 "Failed to parse BEEF for {}: {}",
1233 txid, e
1234 )))
1235 })?;
1236 let bump_offset = merged_beef.bumps.len();
1238 merged_beef.bumps.extend(parsed.bumps);
1239 for mut beef_tx in parsed.txs {
1241 if let Some(ref mut idx) = beef_tx.bump_index {
1242 *idx += bump_offset;
1243 }
1244 let tx_txid = beef_tx.txid.clone();
1246 if !merged_beef.txs.iter().any(|t| t.txid == tx_txid) {
1247 merged_beef.txs.push(beef_tx);
1248 }
1249 }
1250 }
1251 }
1252
1253 if !merged_beef.txs.is_empty() {
1254 let mut buf = Vec::new();
1255 merged_beef.to_binary(&mut buf).map_err(|e| {
1256 to_sdk_error(crate::error::WalletError::Internal(format!(
1257 "Failed to serialize merged BEEF: {}",
1258 e
1259 )))
1260 })?;
1261 result.beef = Some(buf);
1262 }
1263 }
1264 }
1265
1266 if let Some(ref mut beef_bytes) = result.beef {
1268 let beef_lock = self.beef.lock().await;
1269 let verified = crate::wallet::beef_helpers::verify_returned_txid_only_beef(
1270 beef_bytes,
1271 &beef_lock,
1272 self.return_txid_only,
1273 )?;
1274 *beef_bytes = verified;
1275 }
1276
1277 Ok(result)
1278 }
1279
1280 async fn list_certificates(
1281 &self,
1282 args: ListCertificatesArgs,
1283 originator: Option<&str>,
1284 ) -> Result<ListCertificatesResult, SdkWalletError> {
1285 self.validate_originator(originator).map_err(to_sdk_error)?;
1286 bsv::wallet::validation::validate_list_certificates_args(&args)?;
1287
1288 let auth = self.auth_id();
1289 self.storage
1290 .list_certificates(&auth, &args)
1291 .await
1292 .map_err(to_sdk_error)
1293 }
1294
1295 async fn relinquish_output(
1300 &self,
1301 args: RelinquishOutputArgs,
1302 originator: Option<&str>,
1303 ) -> Result<RelinquishOutputResult, SdkWalletError> {
1304 self.validate_originator(originator).map_err(to_sdk_error)?;
1305 bsv::wallet::validation::validate_relinquish_output_args(&args)?;
1306
1307 let auth = self.auth_id();
1308 self.storage
1309 .relinquish_output(&auth, &args)
1310 .await
1311 .map(|_| bsv::wallet::interfaces::RelinquishOutputResult { relinquished: true })
1312 .map_err(to_sdk_error)
1313 }
1314
1315 async fn relinquish_certificate(
1316 &self,
1317 args: RelinquishCertificateArgs,
1318 originator: Option<&str>,
1319 ) -> Result<RelinquishCertificateResult, SdkWalletError> {
1320 self.validate_originator(originator).map_err(to_sdk_error)?;
1321 bsv::wallet::validation::validate_relinquish_certificate_args(&args)?;
1322
1323 let auth = self.auth_id();
1324 self.storage
1325 .relinquish_certificate(&auth, &args)
1326 .await
1327 .map(|_| bsv::wallet::interfaces::RelinquishCertificateResult { relinquished: true })
1328 .map_err(to_sdk_error)
1329 }
1330
1331 async fn acquire_certificate(
1336 &self,
1337 args: AcquireCertificateArgs,
1338 originator: Option<&str>,
1339 ) -> Result<Certificate, SdkWalletError> {
1340 self.validate_originator(originator).map_err(to_sdk_error)?;
1341 bsv::wallet::validation::validate_acquire_certificate_args(&args)?;
1342
1343 let auth = self.auth_id();
1344
1345 let result = match args.acquisition_protocol {
1346 AcquisitionProtocol::Direct => crate::wallet::certificates::acquire_direct_certificate(
1347 &self.storage,
1348 self,
1349 &auth,
1350 &args,
1351 )
1352 .await
1353 .map_err(to_sdk_error)?,
1354 AcquisitionProtocol::Issuance => {
1355 crate::wallet::certificates::acquire_issuance_certificate(
1356 &self.storage,
1357 self,
1358 &auth,
1359 &args,
1360 )
1361 .await
1362 .map_err(to_sdk_error)?
1363 }
1364 };
1365
1366 let subject_pk = PublicKey::from_string(&result.subject)
1368 .map_err(|e| SdkWalletError::Internal(format!("Invalid subject key: {}", e)))?;
1369 let certifier_pk = PublicKey::from_string(&result.certifier)
1370 .map_err(|e| SdkWalletError::Internal(format!("Invalid certifier key: {}", e)))?;
1371
1372 Ok(Certificate {
1373 cert_type: args.cert_type,
1374 serial_number: args
1375 .serial_number
1376 .unwrap_or(bsv::wallet::interfaces::SerialNumber([0u8; 32])),
1377 subject: subject_pk,
1378 certifier: certifier_pk,
1379 revocation_outpoint: Some(result.revocation_outpoint),
1380 fields: Some(result.fields),
1381 signature: args.signature,
1382 })
1383 }
1384
1385 async fn prove_certificate(
1386 &self,
1387 args: ProveCertificateArgs,
1388 originator: Option<&str>,
1389 ) -> Result<ProveCertificateResult, SdkWalletError> {
1390 self.validate_originator(originator).map_err(to_sdk_error)?;
1391 bsv::wallet::validation::validate_prove_certificate_args(&args)?;
1392
1393 let auth = self.auth_id();
1394 crate::wallet::certificates::prove_certificate(&self.storage, self, &auth, &args)
1395 .await
1396 .map_err(to_sdk_error)
1397 }
1398
1399 async fn discover_by_identity_key(
1400 &self,
1401 args: DiscoverByIdentityKeyArgs,
1402 originator: Option<&str>,
1403 ) -> Result<DiscoverCertificatesResult, SdkWalletError> {
1404 self.validate_originator(originator).map_err(to_sdk_error)?;
1405 bsv::wallet::validation::validate_discover_by_identity_key_args(&args)?;
1406
1407 let resolver = self
1408 .lookup_resolver
1409 .as_ref()
1410 .ok_or_else(|| SdkWalletError::Internal("No lookup resolver configured".to_string()))?;
1411
1412 crate::wallet::discovery::discover_by_identity_key(
1413 &self.settings_manager,
1414 resolver,
1415 &self.overlay_cache,
1416 &args,
1417 )
1418 .await
1419 .map_err(to_sdk_error)
1420 }
1421
1422 async fn discover_by_attributes(
1423 &self,
1424 args: DiscoverByAttributesArgs,
1425 originator: Option<&str>,
1426 ) -> Result<DiscoverCertificatesResult, SdkWalletError> {
1427 self.validate_originator(originator).map_err(to_sdk_error)?;
1428 bsv::wallet::validation::validate_discover_by_attributes_args(&args)?;
1429
1430 let resolver = self
1431 .lookup_resolver
1432 .as_ref()
1433 .ok_or_else(|| SdkWalletError::Internal("No lookup resolver configured".to_string()))?;
1434
1435 crate::wallet::discovery::discover_by_attributes(
1436 &self.settings_manager,
1437 resolver,
1438 &self.overlay_cache,
1439 &args,
1440 )
1441 .await
1442 .map_err(to_sdk_error)
1443 }
1444}
1445
1446#[derive(Clone)]
1460pub struct WalletArc(pub Arc<Wallet>);
1461
1462impl WalletArc {
1463 pub fn new(wallet: Arc<Wallet>) -> Self {
1465 Self(wallet)
1466 }
1467}
1468
1469#[async_trait]
1470impl WalletInterface for WalletArc {
1471 async fn get_public_key(
1472 &self,
1473 args: GetPublicKeyArgs,
1474 originator: Option<&str>,
1475 ) -> Result<GetPublicKeyResult, SdkWalletError> {
1476 self.0.as_ref().get_public_key(args, originator).await
1477 }
1478
1479 async fn encrypt(
1480 &self,
1481 args: EncryptArgs,
1482 originator: Option<&str>,
1483 ) -> Result<EncryptResult, SdkWalletError> {
1484 self.0.as_ref().encrypt(args, originator).await
1485 }
1486
1487 async fn decrypt(
1488 &self,
1489 args: DecryptArgs,
1490 originator: Option<&str>,
1491 ) -> Result<DecryptResult, SdkWalletError> {
1492 self.0.as_ref().decrypt(args, originator).await
1493 }
1494
1495 async fn create_hmac(
1496 &self,
1497 args: CreateHmacArgs,
1498 originator: Option<&str>,
1499 ) -> Result<CreateHmacResult, SdkWalletError> {
1500 self.0.as_ref().create_hmac(args, originator).await
1501 }
1502
1503 async fn verify_hmac(
1504 &self,
1505 args: VerifyHmacArgs,
1506 originator: Option<&str>,
1507 ) -> Result<VerifyHmacResult, SdkWalletError> {
1508 self.0.as_ref().verify_hmac(args, originator).await
1509 }
1510
1511 async fn create_signature(
1512 &self,
1513 args: CreateSignatureArgs,
1514 originator: Option<&str>,
1515 ) -> Result<CreateSignatureResult, SdkWalletError> {
1516 self.0.as_ref().create_signature(args, originator).await
1517 }
1518
1519 async fn verify_signature(
1520 &self,
1521 args: VerifySignatureArgs,
1522 originator: Option<&str>,
1523 ) -> Result<VerifySignatureResult, SdkWalletError> {
1524 self.0.as_ref().verify_signature(args, originator).await
1525 }
1526
1527 async fn reveal_counterparty_key_linkage(
1528 &self,
1529 args: RevealCounterpartyKeyLinkageArgs,
1530 originator: Option<&str>,
1531 ) -> Result<RevealCounterpartyKeyLinkageResult, SdkWalletError> {
1532 self.0
1533 .as_ref()
1534 .reveal_counterparty_key_linkage(args, originator)
1535 .await
1536 }
1537
1538 async fn reveal_specific_key_linkage(
1539 &self,
1540 args: RevealSpecificKeyLinkageArgs,
1541 originator: Option<&str>,
1542 ) -> Result<RevealSpecificKeyLinkageResult, SdkWalletError> {
1543 self.0
1544 .as_ref()
1545 .reveal_specific_key_linkage(args, originator)
1546 .await
1547 }
1548
1549 async fn is_authenticated(
1550 &self,
1551 originator: Option<&str>,
1552 ) -> Result<AuthenticatedResult, SdkWalletError> {
1553 self.0.as_ref().is_authenticated(originator).await
1554 }
1555
1556 async fn wait_for_authentication(
1557 &self,
1558 originator: Option<&str>,
1559 ) -> Result<AuthenticatedResult, SdkWalletError> {
1560 self.0.as_ref().wait_for_authentication(originator).await
1561 }
1562
1563 async fn get_height(
1564 &self,
1565 originator: Option<&str>,
1566 ) -> Result<GetHeightResult, SdkWalletError> {
1567 self.0.as_ref().get_height(originator).await
1568 }
1569
1570 async fn get_header_for_height(
1571 &self,
1572 args: GetHeaderArgs,
1573 originator: Option<&str>,
1574 ) -> Result<GetHeaderResult, SdkWalletError> {
1575 self.0
1576 .as_ref()
1577 .get_header_for_height(args, originator)
1578 .await
1579 }
1580
1581 async fn get_network(
1582 &self,
1583 originator: Option<&str>,
1584 ) -> Result<GetNetworkResult, SdkWalletError> {
1585 self.0.as_ref().get_network(originator).await
1586 }
1587
1588 async fn get_version(
1589 &self,
1590 originator: Option<&str>,
1591 ) -> Result<GetVersionResult, SdkWalletError> {
1592 self.0.as_ref().get_version(originator).await
1593 }
1594
1595 async fn create_action(
1596 &self,
1597 args: CreateActionArgs,
1598 originator: Option<&str>,
1599 ) -> Result<CreateActionResult, SdkWalletError> {
1600 self.0.as_ref().create_action(args, originator).await
1601 }
1602
1603 async fn sign_action(
1604 &self,
1605 args: SignActionArgs,
1606 originator: Option<&str>,
1607 ) -> Result<SignActionResult, SdkWalletError> {
1608 self.0.as_ref().sign_action(args, originator).await
1609 }
1610
1611 async fn internalize_action(
1612 &self,
1613 args: InternalizeActionArgs,
1614 originator: Option<&str>,
1615 ) -> Result<InternalizeActionResult, SdkWalletError> {
1616 self.0.as_ref().internalize_action(args, originator).await
1617 }
1618
1619 async fn abort_action(
1620 &self,
1621 args: AbortActionArgs,
1622 originator: Option<&str>,
1623 ) -> Result<AbortActionResult, SdkWalletError> {
1624 self.0.as_ref().abort_action(args, originator).await
1625 }
1626
1627 async fn list_actions(
1628 &self,
1629 args: ListActionsArgs,
1630 originator: Option<&str>,
1631 ) -> Result<ListActionsResult, SdkWalletError> {
1632 self.0.as_ref().list_actions(args, originator).await
1633 }
1634
1635 async fn list_outputs(
1636 &self,
1637 args: ListOutputsArgs,
1638 originator: Option<&str>,
1639 ) -> Result<ListOutputsResult, SdkWalletError> {
1640 self.0.as_ref().list_outputs(args, originator).await
1641 }
1642
1643 async fn list_certificates(
1644 &self,
1645 args: ListCertificatesArgs,
1646 originator: Option<&str>,
1647 ) -> Result<ListCertificatesResult, SdkWalletError> {
1648 self.0.as_ref().list_certificates(args, originator).await
1649 }
1650
1651 async fn relinquish_output(
1652 &self,
1653 args: RelinquishOutputArgs,
1654 originator: Option<&str>,
1655 ) -> Result<RelinquishOutputResult, SdkWalletError> {
1656 self.0.as_ref().relinquish_output(args, originator).await
1657 }
1658
1659 async fn relinquish_certificate(
1660 &self,
1661 args: RelinquishCertificateArgs,
1662 originator: Option<&str>,
1663 ) -> Result<RelinquishCertificateResult, SdkWalletError> {
1664 self.0
1665 .as_ref()
1666 .relinquish_certificate(args, originator)
1667 .await
1668 }
1669
1670 async fn acquire_certificate(
1671 &self,
1672 args: AcquireCertificateArgs,
1673 originator: Option<&str>,
1674 ) -> Result<Certificate, SdkWalletError> {
1675 self.0.as_ref().acquire_certificate(args, originator).await
1676 }
1677
1678 async fn prove_certificate(
1679 &self,
1680 args: ProveCertificateArgs,
1681 originator: Option<&str>,
1682 ) -> Result<ProveCertificateResult, SdkWalletError> {
1683 self.0.as_ref().prove_certificate(args, originator).await
1684 }
1685
1686 async fn discover_by_identity_key(
1687 &self,
1688 args: DiscoverByIdentityKeyArgs,
1689 originator: Option<&str>,
1690 ) -> Result<DiscoverCertificatesResult, SdkWalletError> {
1691 self.0
1692 .as_ref()
1693 .discover_by_identity_key(args, originator)
1694 .await
1695 }
1696
1697 async fn discover_by_attributes(
1698 &self,
1699 args: DiscoverByAttributesArgs,
1700 originator: Option<&str>,
1701 ) -> Result<DiscoverCertificatesResult, SdkWalletError> {
1702 self.0
1703 .as_ref()
1704 .discover_by_attributes(args, originator)
1705 .await
1706 }
1707}