Skip to main content

rpc/guarantee/
mod.rs

1use alloy_primitives::U256;
2use serde::{Deserialize, Serialize};
3
4pub mod codec;
5
6const DEFAULT_ASSET_ADDRESS: &str = "0x0000000000000000000000000000000000000000";
7
8pub const GUARANTEE_CLAIMS_VERSION: u64 = 1;
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11pub struct PaymentGuaranteeClaims {
12    pub domain: [u8; 32],
13    pub user_address: String,
14    pub recipient_address: String,
15    pub tab_id: U256,
16    pub req_id: U256,
17    pub amount: U256,
18    pub total_amount: U256,
19    pub asset_address: String,
20    pub timestamp: u64,
21    pub version: u64,
22}
23
24impl PaymentGuaranteeClaims {
25    pub fn from_request(
26        request: &PaymentGuaranteeRequestClaims,
27        domain: [u8; 32],
28        total_amount: U256,
29    ) -> Self {
30        match request {
31            PaymentGuaranteeRequestClaims::V1(claims) => Self {
32                domain,
33                user_address: claims.user_address.clone(),
34                recipient_address: claims.recipient_address.clone(),
35                tab_id: claims.tab_id,
36                req_id: claims.req_id,
37                amount: claims.amount,
38                total_amount,
39                asset_address: claims.asset_address.clone(),
40                timestamp: claims.timestamp,
41                version: GUARANTEE_CLAIMS_VERSION,
42            },
43        }
44    }
45}
46
47impl TryInto<Vec<u8>> for PaymentGuaranteeClaims {
48    type Error = anyhow::Error;
49
50    fn try_into(self) -> Result<Vec<u8>, Self::Error> {
51        codec::encode_guarantee_claims(self)
52            .map_err(|e| anyhow::anyhow!("Failed to encode guarantee bytes: {}", e))
53    }
54}
55
56impl TryFrom<&[u8]> for PaymentGuaranteeClaims {
57    type Error = anyhow::Error;
58
59    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
60        let claims = codec::decode_guarantee_claims(value)?;
61        Ok(claims)
62    }
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct PaymentGuaranteeRequestClaimsV1 {
67    pub user_address: String,
68    pub recipient_address: String,
69    pub tab_id: U256,
70    pub req_id: U256,
71    pub amount: U256,
72    pub asset_address: String,
73    pub timestamp: u64,
74}
75
76impl PaymentGuaranteeRequestClaimsV1 {
77    pub fn new(
78        user_address: String,
79        recipient_address: String,
80        tab_id: U256,
81        req_id: U256,
82        amount: U256,
83        timestamp: u64,
84        erc20_token: Option<String>,
85    ) -> Self {
86        let asset_address = erc20_token.unwrap_or(DEFAULT_ASSET_ADDRESS.to_string());
87        Self {
88            user_address,
89            recipient_address,
90            tab_id,
91            req_id,
92            amount,
93            asset_address,
94            timestamp,
95        }
96    }
97}
98
99pub trait PaymentGuaranteeRequestEssentials {
100    fn user_address(&self) -> &str;
101
102    fn recipient_address(&self) -> &str;
103
104    fn tab_id(&self) -> U256;
105
106    fn amount(&self) -> U256;
107}
108
109impl PaymentGuaranteeRequestEssentials for PaymentGuaranteeRequestClaims {
110    fn user_address(&self) -> &str {
111        match self {
112            PaymentGuaranteeRequestClaims::V1(claims) => &claims.user_address,
113        }
114    }
115
116    fn recipient_address(&self) -> &str {
117        match self {
118            PaymentGuaranteeRequestClaims::V1(claims) => &claims.recipient_address,
119        }
120    }
121
122    fn tab_id(&self) -> U256 {
123        match self {
124            PaymentGuaranteeRequestClaims::V1(claims) => claims.tab_id,
125        }
126    }
127
128    fn amount(&self) -> U256 {
129        match self {
130            PaymentGuaranteeRequestClaims::V1(claims) => claims.amount,
131        }
132    }
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
136#[serde(rename_all = "snake_case", tag = "version")]
137pub enum PaymentGuaranteeRequestClaims {
138    V1(PaymentGuaranteeRequestClaimsV1),
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
142#[serde(rename_all = "snake_case")]
143pub enum SigningScheme {
144    Eip712,
145    Eip191, // optional fallback (personal_sign)
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct PaymentGuaranteeRequest {
150    pub claims: PaymentGuaranteeRequestClaims,
151    /// 65-byte signature as 0x-prefixed hex
152    pub signature: String,
153    pub scheme: SigningScheme,
154}
155
156impl PaymentGuaranteeRequest {
157    pub fn new(
158        claims: PaymentGuaranteeRequestClaims,
159        signature: String,
160        scheme: SigningScheme,
161    ) -> Self {
162        Self {
163            claims,
164            signature,
165            scheme,
166        }
167    }
168}