Skip to main content

xmtp_id/scw_verifier/
remote_signature_verifier.rs

1use super::{SmartContractSignatureVerifier, ValidationResponse, VerifierError};
2use crate::associations::AccountId;
3use alloy::primitives::{BlockNumber, Bytes};
4
5use xmtp_proto::{
6    backend_v1::{
7        VerifySmartContractWalletSignaturesRequest, VerifySmartContractWalletSignaturesResponse,
8        verify_smart_contract_wallet_signatures_request::Signature as VerifySmartContractWalletSignatureRequestSignature,
9    },
10    prelude::XmtpBackendClient,
11};
12
13pub struct RemoteSignatureVerifier<C> {
14    api: C,
15}
16
17impl<ApiClient> RemoteSignatureVerifier<ApiClient> {
18    pub fn new(api: ApiClient) -> Self {
19        Self { api }
20    }
21}
22
23#[xmtp_common::async_trait]
24impl<C> SmartContractSignatureVerifier for RemoteSignatureVerifier<C>
25where
26    C: XmtpBackendClient,
27{
28    async fn is_valid_signature(
29        &self,
30        account_id: AccountId,
31        hash: [u8; 32],
32        signature: Bytes,
33        block_number: Option<BlockNumber>,
34    ) -> Result<ValidationResponse, VerifierError> {
35        let result = self
36            .api
37            .verify_smart_contract_wallet_signatures(VerifySmartContractWalletSignaturesRequest {
38                signatures: vec![VerifySmartContractWalletSignatureRequestSignature {
39                    account_id: account_id.into(),
40                    block_number,
41                    signature: signature.to_vec(),
42                    hash: hash.to_vec(),
43                }],
44            })
45            .await
46            .map_err(|e| VerifierError::Other(Box::new(e) as Box<_>))?;
47
48        let VerifySmartContractWalletSignaturesResponse { responses } = result;
49
50        let response =
51            responses
52                .into_iter()
53                .next()
54                .ok_or(VerifierError::Io(std::io::Error::new(
55                    std::io::ErrorKind::InvalidData,
56                    "API returned empty response for signature verification request",
57                )))?;
58        Ok(ValidationResponse {
59            is_valid: response.is_valid,
60            block_number: response.block_number,
61            error: response.error,
62        })
63    }
64}
65
66impl<T> Clone for RemoteSignatureVerifier<T>
67where
68    T: Clone,
69{
70    fn clone(&self) -> Self {
71        Self {
72            api: self.api.clone(),
73        }
74    }
75}