1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use std::sync::Arc;

use async_trait::async_trait;
use aws_sdk_lambda::primitives::Blob;
pub use ethers::providers::JsonRpcClient;
use serde::de::DeserializeOwned;
use serde::Serialize;

use self::error::ClientError;
use super::TxSitterInner;
use crate::rpc::data::{JsonRpcResponse, JsonRpcVersion, RpcLambdaRequest, RpcPayload};

mod data;
mod error;

#[derive(Clone, Debug)]
pub struct TxSitterRpcClient {
    relayer_id: String,
    inner: Arc<TxSitterInner>,
}

impl TxSitterRpcClient {
    pub(super) fn new(relayer_id: String, inner: Arc<TxSitterInner>) -> Self {
        Self { relayer_id, inner }
    }
}

#[async_trait]
impl JsonRpcClient for TxSitterRpcClient {
    type Error = ClientError;

    /// Sends a request with the provided JSON-RPC and parameters serialized as JSON
    async fn request<T, R>(&self, method: &str, params: T) -> Result<R, Self::Error>
    where
        T: std::fmt::Debug + Serialize + Send + Sync,
        R: DeserializeOwned + Send,
    {
        let payload = RpcPayload {
            id: 1,
            method: method.into(),
            params: serde_json::to_value(params)?,
            jsonrpc: JsonRpcVersion::V2,
        };

        let lambda_request = RpcLambdaRequest {
            payload,
            relayer_id: self.relayer_id.clone(),
        };

        let payload = serde_json::to_vec(&lambda_request)?;

        let res = self
            .inner
            .client
            .invoke()
            .function_name(self.inner.config.rpc_lambda_name.clone())
            .payload(Blob::new(payload))
            .send()
            .await?;

        let payload = res.payload.ok_or(ClientError::MissingPayload)?;

        let result: JsonRpcResponse<R> = serde_json::from_slice(&payload.into_inner())?;

        match (result.result, result.error) {
            (Some(result), None) => Ok(result),
            (None, Some(error)) => Err(ClientError::Rpc(error)),
            _ => Err(ClientError::Other(
                "Invalid response from the RPC".to_string(),
            )),
        }
    }
}