Skip to main content

bsv/wallet/substrates/
wallet_client.rs

1//! WalletClient: validates args before delegating to wire transport.
2//!
3//! Wraps a WalletWireTransceiver and adds argument validation to each
4//! method call before sending over the wire. This prevents invalid
5//! requests from being transmitted.
6//!
7//! Translated from Go SDK wallet/substrates/wallet_client.go.
8
9use crate::wallet::error::WalletError;
10use crate::wallet::interfaces::*;
11use crate::wallet::substrates::{WalletWire, WalletWireTransceiver};
12use crate::wallet::validation;
13
14/// Client that validates all arguments before delegating to wire transport.
15pub struct WalletClient<W: WalletWire> {
16    transceiver: WalletWireTransceiver<W>,
17}
18
19impl<W: WalletWire> WalletClient<W> {
20    /// Create a new WalletClient wrapping the given wire substrate.
21    pub fn new(substrate: W) -> Self {
22        Self {
23            transceiver: WalletWireTransceiver::new(substrate),
24        }
25    }
26}
27
28/// Macro to reduce boilerplate: validate args then delegate to transceiver.
29/// Uses desugared async-trait form so it works inside #[async_trait] impl blocks.
30macro_rules! impl_validated_method {
31    // Methods with args
32    ($method:ident, $args_type:ty, $result_type:ty, $validator:path) => {
33        fn $method<'life0, 'life1, 'async_trait>(
34            &'life0 self,
35            args: $args_type,
36            originator: Option<&'life1 str>,
37        ) -> ::core::pin::Pin<Box<dyn ::core::future::Future<Output = Result<$result_type, WalletError>> + ::core::marker::Send + 'async_trait>>
38        where
39            'life0: 'async_trait,
40            'life1: 'async_trait,
41            Self: 'async_trait,
42        {
43            Box::pin(async move {
44                $validator(&args)?;
45                self.transceiver.$method(args, originator).await
46            })
47        }
48    };
49    // Methods without args (no validation needed, just delegate)
50    (no_args $method:ident, $result_type:ty) => {
51        fn $method<'life0, 'life1, 'async_trait>(
52            &'life0 self,
53            originator: Option<&'life1 str>,
54        ) -> ::core::pin::Pin<Box<dyn ::core::future::Future<Output = Result<$result_type, WalletError>> + ::core::marker::Send + 'async_trait>>
55        where
56            'life0: 'async_trait,
57            'life1: 'async_trait,
58            Self: 'async_trait,
59        {
60            Box::pin(async move {
61                self.transceiver.$method(originator).await
62            })
63        }
64    };
65}
66
67#[async_trait::async_trait]
68impl<W: WalletWire> WalletInterface for WalletClient<W> {
69    impl_validated_method!(
70        create_action,
71        CreateActionArgs,
72        CreateActionResult,
73        validation::validate_create_action_args
74    );
75
76    impl_validated_method!(
77        sign_action,
78        SignActionArgs,
79        SignActionResult,
80        validation::validate_sign_action_args
81    );
82
83    impl_validated_method!(
84        abort_action,
85        AbortActionArgs,
86        AbortActionResult,
87        validation::validate_abort_action_args
88    );
89
90    impl_validated_method!(
91        list_actions,
92        ListActionsArgs,
93        ListActionsResult,
94        validation::validate_list_actions_args
95    );
96
97    impl_validated_method!(
98        internalize_action,
99        InternalizeActionArgs,
100        InternalizeActionResult,
101        validation::validate_internalize_action_args
102    );
103
104    impl_validated_method!(
105        list_outputs,
106        ListOutputsArgs,
107        ListOutputsResult,
108        validation::validate_list_outputs_args
109    );
110
111    impl_validated_method!(
112        relinquish_output,
113        RelinquishOutputArgs,
114        RelinquishOutputResult,
115        validation::validate_relinquish_output_args
116    );
117
118    impl_validated_method!(
119        get_public_key,
120        GetPublicKeyArgs,
121        GetPublicKeyResult,
122        validation::validate_get_public_key_args
123    );
124
125    impl_validated_method!(
126        reveal_counterparty_key_linkage,
127        RevealCounterpartyKeyLinkageArgs,
128        RevealCounterpartyKeyLinkageResult,
129        validation::validate_reveal_counterparty_key_linkage_args
130    );
131
132    impl_validated_method!(
133        reveal_specific_key_linkage,
134        RevealSpecificKeyLinkageArgs,
135        RevealSpecificKeyLinkageResult,
136        validation::validate_reveal_specific_key_linkage_args
137    );
138
139    impl_validated_method!(
140        encrypt,
141        EncryptArgs,
142        EncryptResult,
143        validation::validate_encrypt_args
144    );
145
146    impl_validated_method!(
147        decrypt,
148        DecryptArgs,
149        DecryptResult,
150        validation::validate_decrypt_args
151    );
152
153    impl_validated_method!(
154        create_hmac,
155        CreateHmacArgs,
156        CreateHmacResult,
157        validation::validate_create_hmac_args
158    );
159
160    impl_validated_method!(
161        verify_hmac,
162        VerifyHmacArgs,
163        VerifyHmacResult,
164        validation::validate_verify_hmac_args
165    );
166
167    impl_validated_method!(
168        create_signature,
169        CreateSignatureArgs,
170        CreateSignatureResult,
171        validation::validate_create_signature_args
172    );
173
174    impl_validated_method!(
175        verify_signature,
176        VerifySignatureArgs,
177        VerifySignatureResult,
178        validation::validate_verify_signature_args
179    );
180
181    impl_validated_method!(
182        acquire_certificate,
183        AcquireCertificateArgs,
184        Certificate,
185        validation::validate_acquire_certificate_args
186    );
187
188    impl_validated_method!(
189        list_certificates,
190        ListCertificatesArgs,
191        ListCertificatesResult,
192        validation::validate_list_certificates_args
193    );
194
195    impl_validated_method!(
196        prove_certificate,
197        ProveCertificateArgs,
198        ProveCertificateResult,
199        validation::validate_prove_certificate_args
200    );
201
202    impl_validated_method!(
203        relinquish_certificate,
204        RelinquishCertificateArgs,
205        RelinquishCertificateResult,
206        validation::validate_relinquish_certificate_args
207    );
208
209    impl_validated_method!(
210        discover_by_identity_key,
211        DiscoverByIdentityKeyArgs,
212        DiscoverCertificatesResult,
213        validation::validate_discover_by_identity_key_args
214    );
215
216    impl_validated_method!(
217        discover_by_attributes,
218        DiscoverByAttributesArgs,
219        DiscoverCertificatesResult,
220        validation::validate_discover_by_attributes_args
221    );
222
223    impl_validated_method!(no_args is_authenticated, AuthenticatedResult);
224    impl_validated_method!(no_args wait_for_authentication, AuthenticatedResult);
225    impl_validated_method!(no_args get_height, GetHeightResult);
226
227    impl_validated_method!(
228        get_header_for_height,
229        GetHeaderArgs,
230        GetHeaderResult,
231        validation::validate_get_header_args
232    );
233
234    impl_validated_method!(no_args get_network, GetNetworkResult);
235    impl_validated_method!(no_args get_version, GetVersionResult);
236}