1use crate::ApiClientWrapper;
2use xmtp_id::scw_verifier::SmartContractSignatureVerifier;
3use xmtp_id::scw_verifier::VerifierError;
4use xmtp_id::scw_verifier::{ScwInput, ValidationResponse};
5use xmtp_id::{BlockNumber, Bytes, associations::AccountId};
6use xmtp_proto::backend_v1::VerifySmartContractWalletSignaturesRequest;
7use xmtp_proto::backend_v1::VerifySmartContractWalletSignaturesResponse;
8use xmtp_proto::backend_v1::verify_smart_contract_wallet_signatures_request::Signature as VerifySmartContractWalletSignatureRequestSignature;
9use xmtp_proto::backend_v1::verify_smart_contract_wallet_signatures_response::Response as VerifySmartContractWalletSignatureResponse;
10use xmtp_proto::prelude::XmtpBackendClient;
11
12fn verdict(response: VerifySmartContractWalletSignatureResponse) -> ValidationResponse {
13 ValidationResponse {
14 is_valid: response.is_valid,
15 block_number: response.block_number,
16 error: response.error,
17 }
18}
19
20#[xmtp_common::async_trait]
21impl<C> SmartContractSignatureVerifier for ApiClientWrapper<C>
22where
23 C: XmtpBackendClient,
24{
25 async fn is_valid_signature(
33 &self,
34 account_id: AccountId,
35 hash: [u8; 32],
36 signature: Bytes,
37 block_number: Option<BlockNumber>,
38 ) -> Result<ValidationResponse, VerifierError> {
39 let result = self
40 .verify_smart_contract_wallet_signatures(VerifySmartContractWalletSignaturesRequest {
41 signatures: vec![VerifySmartContractWalletSignatureRequestSignature {
42 account_id: account_id.into(),
43 block_number,
44 signature: signature.to_vec(),
45 hash: hash.to_vec(),
46 }],
47 })
48 .await
49 .map_err(|e| VerifierError::Other(Box::new(e) as Box<_>))?;
50
51 let VerifySmartContractWalletSignaturesResponse { responses } = result;
52
53 let response =
54 responses
55 .into_iter()
56 .next()
57 .ok_or(VerifierError::Io(std::io::Error::new(
58 std::io::ErrorKind::InvalidData,
59 "API returned empty response for signature verification request",
60 )))?;
61 Ok(verdict(response))
62 }
63
64 async fn verify_many(
70 &self,
71 inputs: &[ScwInput],
72 ) -> Result<Vec<ValidationResponse>, VerifierError> {
73 let signatures = inputs
74 .iter()
75 .map(|input| VerifySmartContractWalletSignatureRequestSignature {
76 account_id: input.account_id().clone().into(),
77 block_number: input.block_number(),
78 signature: input.signature().to_vec(),
79 hash: input.hash().to_vec(),
80 })
81 .collect();
82 let VerifySmartContractWalletSignaturesResponse { responses } = self
83 .verify_smart_contract_wallet_signatures(VerifySmartContractWalletSignaturesRequest {
84 signatures,
85 })
86 .await
87 .map_err(|e| VerifierError::Other(Box::new(e) as Box<_>))?;
88 Ok(responses.into_iter().map(verdict).collect())
89 }
90}