Skip to main content

xmtp_api/
scw_verifier.rs

1use crate::ApiClientWrapper;
2use xmtp_id::scw_verifier::SmartContractSignatureVerifier;
3use xmtp_id::scw_verifier::VerifierError;
4use xmtp_id::{BlockNumber, Bytes, associations::AccountId, scw_verifier::ValidationResponse};
5use xmtp_proto::backend_v1::VerifySmartContractWalletSignaturesRequest;
6use xmtp_proto::backend_v1::VerifySmartContractWalletSignaturesResponse;
7use xmtp_proto::backend_v1::verify_smart_contract_wallet_signatures_request::Signature as VerifySmartContractWalletSignatureRequestSignature;
8use xmtp_proto::prelude::XmtpBackendClient;
9
10#[xmtp_common::async_trait]
11impl<C> SmartContractSignatureVerifier for ApiClientWrapper<C>
12where
13    C: XmtpBackendClient,
14{
15    /// Verifies an ERC-6492<https://eips.ethereum.org/EIPS/eip-6492> signature.
16    ///
17    /// # Arguments
18    ///
19    /// * `signer` - can be the smart wallet address or EOA address.
20    /// * `hash` - Message digest for the signature.
21    /// * `signature` - Could be encoded smart wallet signature or raw ECDSA signature.
22    async fn is_valid_signature(
23        &self,
24        account_id: AccountId,
25        hash: [u8; 32],
26        signature: Bytes,
27        block_number: Option<BlockNumber>,
28    ) -> Result<ValidationResponse, VerifierError> {
29        let result = self
30            .verify_smart_contract_wallet_signatures(VerifySmartContractWalletSignaturesRequest {
31                signatures: vec![VerifySmartContractWalletSignatureRequestSignature {
32                    account_id: account_id.into(),
33                    block_number,
34                    signature: signature.to_vec(),
35                    hash: hash.to_vec(),
36                }],
37            })
38            .await
39            .map_err(|e| VerifierError::Other(Box::new(e) as Box<_>))?;
40
41        let VerifySmartContractWalletSignaturesResponse { responses } = result;
42
43        let response =
44            responses
45                .into_iter()
46                .next()
47                .ok_or(VerifierError::Io(std::io::Error::new(
48                    std::io::ErrorKind::InvalidData,
49                    "API returned empty response for signature verification request",
50                )))?;
51        Ok(ValidationResponse {
52            is_valid: response.is_valid,
53            block_number: response.block_number,
54            error: response.error,
55        })
56    }
57}