openzeppelin_relayer/models/notification/
webhook_notification.rs

1use crate::{
2    domain::SwapResult,
3    jobs::NotificationSend,
4    models::{
5        RelayerRepoModel, RelayerResponse, SignAndSendTransactionResult, SignTransactionResult,
6        TransactionRepoModel, TransactionResponse, TransferTransactionResult,
7    },
8};
9use chrono::Utc;
10use serde::{Deserialize, Serialize};
11use uuid::Uuid;
12
13#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
14pub struct WebhookNotification {
15    pub id: String,
16    pub event: String,
17    pub payload: WebhookPayload,
18    pub timestamp: String,
19}
20
21impl WebhookNotification {
22    pub fn new(event: String, payload: WebhookPayload) -> Self {
23        Self {
24            id: Uuid::new_v4().to_string(),
25            event,
26            payload,
27            timestamp: Utc::now().to_rfc3339(),
28        }
29    }
30}
31
32#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
33pub struct TransactionFailurePayload {
34    pub transaction: TransactionResponse,
35    pub failure_reason: String,
36}
37
38#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
39pub struct RelayerDisabledPayload {
40    pub relayer: RelayerResponse,
41    pub disable_reason: String,
42}
43#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
44pub struct SolanaDexPayload {
45    pub swap_results: Vec<SwapResult>,
46}
47
48#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
49#[serde(rename_all = "lowercase")]
50#[serde(tag = "payload_type")]
51pub enum WebhookPayload {
52    Transaction(TransactionResponse),
53    #[serde(rename = "transaction_failure")]
54    TransactionFailure(TransactionFailurePayload),
55    #[serde(rename = "relayer_disabled")]
56    RelayerDisabled(Box<RelayerDisabledPayload>),
57    #[serde(rename = "solana_rpc")]
58    SolanaRpc(SolanaWebhookRpcPayload),
59    #[serde(rename = "solana_dex")]
60    SolanaDex(SolanaDexPayload),
61}
62
63#[derive(Debug, Serialize, Deserialize, Clone)]
64pub struct WebhookResponse {
65    pub status: String,
66    pub message: Option<String>,
67}
68
69pub fn produce_transaction_update_notification_payload(
70    notification_id: &str,
71    transaction: &TransactionRepoModel,
72) -> NotificationSend {
73    let tx_payload: TransactionResponse = transaction.clone().into();
74    NotificationSend::new(
75        notification_id.to_string(),
76        WebhookNotification::new(
77            "transaction_update".to_string(),
78            WebhookPayload::Transaction(tx_payload),
79        ),
80    )
81}
82
83pub fn produce_relayer_disabled_payload(
84    notification_id: &str,
85    relayer: &RelayerRepoModel,
86    reason: &str,
87) -> NotificationSend {
88    let relayer_response: RelayerResponse = relayer.clone().into();
89    let payload = RelayerDisabledPayload {
90        relayer: relayer_response,
91        disable_reason: reason.to_string(),
92    };
93    NotificationSend::new(
94        notification_id.to_string(),
95        WebhookNotification::new(
96            "relayer_state_update".to_string(),
97            WebhookPayload::RelayerDisabled(Box::new(payload)),
98        ),
99    )
100}
101
102#[allow(clippy::enum_variant_names)]
103#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
104#[serde(untagged)]
105pub enum SolanaWebhookRpcPayload {
106    SignAndSendTransaction(SignAndSendTransactionResult),
107    SignTransaction(SignTransactionResult),
108    TransferTransaction(TransferTransactionResult),
109}
110
111/// Produces a notification payload for a Solana RPC webhook event
112pub fn produce_solana_rpc_webhook_payload(
113    notification_id: &str,
114    event: String,
115    payload: SolanaWebhookRpcPayload,
116) -> NotificationSend {
117    NotificationSend::new(
118        notification_id.to_string(),
119        WebhookNotification::new(event, WebhookPayload::SolanaRpc(payload)),
120    )
121}
122
123pub fn produce_solana_dex_webhook_payload(
124    notification_id: &str,
125    event: String,
126    payload: SolanaDexPayload,
127) -> NotificationSend {
128    NotificationSend::new(
129        notification_id.to_string(),
130        WebhookNotification::new(event, WebhookPayload::SolanaDex(payload)),
131    )
132}