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<
38            Box<
39                dyn ::core::future::Future<Output = Result<$result_type, WalletError>>
40                    + ::core::marker::Send
41                    + 'async_trait,
42            >,
43        >
44        where
45            'life0: 'async_trait,
46            'life1: 'async_trait,
47            Self: 'async_trait,
48        {
49            Box::pin(async move {
50                $validator(&args)?;
51                self.transceiver.$method(args, originator).await
52            })
53        }
54    };
55    // Methods without args (no validation needed, just delegate)
56    (no_args $method:ident, $result_type:ty) => {
57        fn $method<'life0, 'life1, 'async_trait>(
58            &'life0 self,
59            originator: Option<&'life1 str>,
60        ) -> ::core::pin::Pin<
61            Box<
62                dyn ::core::future::Future<Output = Result<$result_type, WalletError>>
63                    + ::core::marker::Send
64                    + 'async_trait,
65            >,
66        >
67        where
68            'life0: 'async_trait,
69            'life1: 'async_trait,
70            Self: 'async_trait,
71        {
72            Box::pin(async move { self.transceiver.$method(originator).await })
73        }
74    };
75}
76
77#[async_trait::async_trait]
78impl<W: WalletWire> WalletInterface for WalletClient<W> {
79    impl_validated_method!(
80        create_action,
81        CreateActionArgs,
82        CreateActionResult,
83        validation::validate_create_action_args
84    );
85
86    impl_validated_method!(
87        sign_action,
88        SignActionArgs,
89        SignActionResult,
90        validation::validate_sign_action_args
91    );
92
93    impl_validated_method!(
94        abort_action,
95        AbortActionArgs,
96        AbortActionResult,
97        validation::validate_abort_action_args
98    );
99
100    impl_validated_method!(
101        list_actions,
102        ListActionsArgs,
103        ListActionsResult,
104        validation::validate_list_actions_args
105    );
106
107    impl_validated_method!(
108        internalize_action,
109        InternalizeActionArgs,
110        InternalizeActionResult,
111        validation::validate_internalize_action_args
112    );
113
114    impl_validated_method!(
115        list_outputs,
116        ListOutputsArgs,
117        ListOutputsResult,
118        validation::validate_list_outputs_args
119    );
120
121    impl_validated_method!(
122        relinquish_output,
123        RelinquishOutputArgs,
124        RelinquishOutputResult,
125        validation::validate_relinquish_output_args
126    );
127
128    impl_validated_method!(
129        get_public_key,
130        GetPublicKeyArgs,
131        GetPublicKeyResult,
132        validation::validate_get_public_key_args
133    );
134
135    impl_validated_method!(
136        reveal_counterparty_key_linkage,
137        RevealCounterpartyKeyLinkageArgs,
138        RevealCounterpartyKeyLinkageResult,
139        validation::validate_reveal_counterparty_key_linkage_args
140    );
141
142    impl_validated_method!(
143        reveal_specific_key_linkage,
144        RevealSpecificKeyLinkageArgs,
145        RevealSpecificKeyLinkageResult,
146        validation::validate_reveal_specific_key_linkage_args
147    );
148
149    impl_validated_method!(
150        encrypt,
151        EncryptArgs,
152        EncryptResult,
153        validation::validate_encrypt_args
154    );
155
156    impl_validated_method!(
157        decrypt,
158        DecryptArgs,
159        DecryptResult,
160        validation::validate_decrypt_args
161    );
162
163    impl_validated_method!(
164        create_hmac,
165        CreateHmacArgs,
166        CreateHmacResult,
167        validation::validate_create_hmac_args
168    );
169
170    impl_validated_method!(
171        verify_hmac,
172        VerifyHmacArgs,
173        VerifyHmacResult,
174        validation::validate_verify_hmac_args
175    );
176
177    impl_validated_method!(
178        create_signature,
179        CreateSignatureArgs,
180        CreateSignatureResult,
181        validation::validate_create_signature_args
182    );
183
184    impl_validated_method!(
185        verify_signature,
186        VerifySignatureArgs,
187        VerifySignatureResult,
188        validation::validate_verify_signature_args
189    );
190
191    impl_validated_method!(
192        acquire_certificate,
193        AcquireCertificateArgs,
194        Certificate,
195        validation::validate_acquire_certificate_args
196    );
197
198    impl_validated_method!(
199        list_certificates,
200        ListCertificatesArgs,
201        ListCertificatesResult,
202        validation::validate_list_certificates_args
203    );
204
205    impl_validated_method!(
206        prove_certificate,
207        ProveCertificateArgs,
208        ProveCertificateResult,
209        validation::validate_prove_certificate_args
210    );
211
212    impl_validated_method!(
213        relinquish_certificate,
214        RelinquishCertificateArgs,
215        RelinquishCertificateResult,
216        validation::validate_relinquish_certificate_args
217    );
218
219    impl_validated_method!(
220        discover_by_identity_key,
221        DiscoverByIdentityKeyArgs,
222        DiscoverCertificatesResult,
223        validation::validate_discover_by_identity_key_args
224    );
225
226    impl_validated_method!(
227        discover_by_attributes,
228        DiscoverByAttributesArgs,
229        DiscoverCertificatesResult,
230        validation::validate_discover_by_attributes_args
231    );
232
233    impl_validated_method!(no_args is_authenticated, AuthenticatedResult);
234    impl_validated_method!(no_args wait_for_authentication, AuthenticatedResult);
235    impl_validated_method!(no_args get_height, GetHeightResult);
236
237    impl_validated_method!(
238        get_header_for_height,
239        GetHeaderArgs,
240        GetHeaderResult,
241        validation::validate_get_header_args
242    );
243
244    impl_validated_method!(no_args get_network, GetNetworkResult);
245    impl_validated_method!(no_args get_version, GetVersionResult);
246}