Skip to main content

x402_sdk/
types.rs

1/// Type definitions for global use.
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
5pub enum ChainType {
6    Evm(EvmChain),
7    Aptos(AptosChain),
8    Sui(SuiChain),
9    Solana(SolanaChain),
10    Custom(String),
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
14pub enum EvmChain {
15    Ethereum,
16    Polygon,
17    BinanceSmartChain,
18    Arbitrum,
19    Optimism,
20    Avalanche,
21    Base,
22    Custom(String),
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
26pub enum AptosChain {
27    Mainnet,
28    Testnet,
29    Devnet,
30    Custom(String),
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
34pub enum SuiChain {
35    Mainnet,
36    Testnet,
37    Devnet,
38    Custom(String),
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
42pub enum SolanaChain {
43    Mainnet,
44    Testnet,
45    Devnet,
46    Custom(String),
47}
48
49impl ChainType {
50    pub fn get_standard_chain_id(&self) -> String {
51        match self {
52            ChainType::Evm(evm_chain) => match evm_chain {
53                EvmChain::Ethereum => "1",
54                EvmChain::Polygon => "137",
55                EvmChain::BinanceSmartChain => "56",
56                EvmChain::Arbitrum => "42161",
57                EvmChain::Optimism => "10",
58                EvmChain::Avalanche => "43114",
59                EvmChain::Base => "8453",
60                EvmChain::Custom(id) => id,
61            }
62            .to_string(),
63            ChainType::Aptos(aptos_chain) => match aptos_chain {
64                AptosChain::Mainnet => "1",
65                AptosChain::Testnet => "2",
66                AptosChain::Devnet => "devnet",
67                AptosChain::Custom(id) => id,
68            }
69            .to_string(),
70            ChainType::Sui(sui_chain) => match sui_chain {
71                SuiChain::Mainnet => "mainnet",
72                SuiChain::Testnet => "testnet",
73                SuiChain::Devnet => "devnet",
74                SuiChain::Custom(id) => id,
75            }
76            .to_string(),
77            ChainType::Solana(solana_chain) => match solana_chain {
78                SolanaChain::Mainnet => "mainnet-beta",
79                SolanaChain::Testnet => "testnet",
80                SolanaChain::Devnet => "devnet",
81                SolanaChain::Custom(id) => id,
82            }
83            .to_string(),
84            ChainType::Custom(id) => id.clone(),
85        }
86    }
87
88    pub fn get_display_name(&self) -> String {
89        match self {
90            ChainType::Evm(evm_chain) => match evm_chain {
91                EvmChain::Ethereum => "Ethereum",
92                EvmChain::Polygon => "Polygon",
93                EvmChain::BinanceSmartChain => "BNB Smart Chain",
94                EvmChain::Arbitrum => "Arbitrum",
95                EvmChain::Optimism => "Optimism",
96                EvmChain::Avalanche => "Avalanche",
97                EvmChain::Base => "Base",
98                EvmChain::Custom(name) => name,
99            }
100            .to_string(),
101            ChainType::Aptos(aptos_chain) => match aptos_chain {
102                AptosChain::Mainnet => "Aptos Mainnet",
103                AptosChain::Testnet => "Aptos Testnet",
104                AptosChain::Devnet => "Aptos Devnet",
105                AptosChain::Custom(name) => name,
106            }
107            .to_string(),
108            ChainType::Sui(sui_chain) => match sui_chain {
109                SuiChain::Mainnet => "Sui Mainnet",
110                SuiChain::Testnet => "Sui Testnet",
111                SuiChain::Devnet => "Sui Devnet",
112                SuiChain::Custom(name) => name,
113            }
114            .to_string(),
115            ChainType::Solana(solana_chain) => match solana_chain {
116                SolanaChain::Mainnet => "Solana Mainnet",
117                SolanaChain::Testnet => "Solana Testnet",
118                SolanaChain::Devnet => "Solana Devnet",
119                SolanaChain::Custom(name) => name,
120            }
121            .to_string(),
122            ChainType::Custom(name) => name.clone(),
123        }
124    }
125
126    pub fn is_evm(&self) -> bool {
127        matches!(self, ChainType::Evm(_))
128    }
129
130    pub fn is_aptos(&self) -> bool {
131        matches!(self, ChainType::Aptos(_))
132    }
133
134    pub fn is_sui(&self) -> bool {
135        matches!(self, ChainType::Sui(_))
136    }
137
138    pub fn is_solana(&self) -> bool {
139        matches!(self, ChainType::Solana(_))
140    }
141}
142
143impl ChainType {
144    pub fn ethereum() -> Self {
145        ChainType::Evm(EvmChain::Ethereum)
146    }
147
148    pub fn polygon() -> Self {
149        ChainType::Evm(EvmChain::Polygon)
150    }
151
152    pub fn bsc() -> Self {
153        ChainType::Evm(EvmChain::BinanceSmartChain)
154    }
155
156    pub fn aptos_mainnet() -> Self {
157        ChainType::Aptos(AptosChain::Mainnet)
158    }
159
160    pub fn sui_mainnet() -> Self {
161        ChainType::Sui(SuiChain::Mainnet)
162    }
163
164    pub fn solana_mainnet() -> Self {
165        ChainType::Solana(SolanaChain::Mainnet)
166    }
167}
168
169#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct ChainConfig {
171    pub chain_type: ChainType,
172    pub chain_id: String,
173    pub rpc_url: Option<String>,
174}
175
176impl ChainConfig {
177    pub fn new(chain_type: ChainType, rpc_url: Option<String>) -> Self {
178        let chain_id = chain_type.get_standard_chain_id();
179        Self {
180            chain_type,
181            chain_id,
182            rpc_url,
183        }
184    }
185
186    pub fn from_chain_type(chain_type: ChainType) -> Self {
187        Self::new(chain_type, None)
188    }
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct PaymentRequest {
193    pub amount: String,
194    pub currency: Currency,
195    pub recipient: String,
196    pub chain: ChainConfig,
197    pub description: Option<String>,
198    pub expires_at: Option<u64>,
199    pub nonce: String,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
203pub enum Currency {
204    Native,
205    Token { address: String, decimals: u8 },
206}
207
208#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct PaymentVerification {
210    pub is_paid: bool,
211    pub paid_amount: String,
212    pub transaction_hash: Option<String>,
213    pub verified_at: u64,
214    pub chain: ChainConfig,
215    pub transaction_logs: Vec<TransactionLog>,
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
219pub struct X402ProtocolResponse {
220    pub status: u16,
221    pub payment_required: PaymentRequest,
222    pub verification_url: Option<String>,
223}
224
225#[derive(Debug, Clone)]
226pub struct VerificationResult {
227    pub should_serve_content: bool,
228    pub http_status: u16,
229    pub x402_response: Option<X402ProtocolResponse>,
230    pub verification: Option<PaymentVerification>,
231}
232
233#[derive(Debug, Clone)]
234pub struct X402Config {
235    pub default_chain: ChainConfig,
236    pub service_address: String,
237    pub service_fee: String,
238    pub cache_ttl: u64,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct TransactionLog {
243    pub transaction_hash: String,
244    pub from: String,
245    pub to: String,
246    pub value: String,
247    pub block_number: u64,
248    pub log_index: u64,
249    pub data: Option<String>,
250}