x402_kit/networks/
svm.rs

1use std::{
2    fmt::{Debug, Display},
3    str::FromStr,
4};
5
6use serde::{Deserialize, Serialize};
7use solana_pubkey::{ParsePubkeyError, Pubkey};
8
9use crate::core::{Address, NetworkFamily};
10
11pub struct SvmNetwork {
12    pub name: &'static str,
13    pub caip_2_id: &'static str,
14}
15
16impl NetworkFamily for SvmNetwork {
17    fn network_name(&self) -> &str {
18        self.name
19    }
20
21    fn network_id(&self) -> &str {
22        self.caip_2_id
23    }
24}
25
26#[derive(Clone, Copy, PartialEq, Eq, Hash)]
27pub struct SvmAddress(pub Pubkey);
28
29impl From<Pubkey> for SvmAddress {
30    fn from(pk: Pubkey) -> Self {
31        SvmAddress(pk)
32    }
33}
34
35impl FromStr for SvmAddress {
36    type Err = ParsePubkeyError;
37
38    fn from_str(s: &str) -> Result<Self, Self::Err> {
39        let pk = Pubkey::from_str(s)?;
40        Ok(SvmAddress(pk))
41    }
42}
43
44impl Display for SvmAddress {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        write!(f, "{}", self.0)
47    }
48}
49
50impl Debug for SvmAddress {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        write!(f, "SvmAddress({})", self.0)
53    }
54}
55
56impl Serialize for SvmAddress {
57    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58    where
59        S: serde::Serializer,
60    {
61        serializer.serialize_str(&self.to_string())
62    }
63}
64
65impl<'de> Deserialize<'de> for SvmAddress {
66    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
67    where
68        D: serde::Deserializer<'de>,
69    {
70        let s = String::deserialize(deserializer)?;
71        let pk = Pubkey::from_str(&s).map_err(serde::de::Error::custom)?;
72        Ok(SvmAddress(pk))
73    }
74}
75
76#[derive(Clone, Copy, PartialEq, Eq, Hash)]
77pub struct SvmSignature(pub solana_signature::Signature);
78
79impl FromStr for SvmSignature {
80    type Err = solana_signature::ParseSignatureError;
81
82    fn from_str(s: &str) -> Result<Self, Self::Err> {
83        let sig = solana_signature::Signature::from_str(s)?;
84        Ok(SvmSignature(sig))
85    }
86}
87
88impl Debug for SvmSignature {
89    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90        write!(f, "SvmSignature({})", self.0)
91    }
92}
93
94impl Display for SvmSignature {
95    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96        write!(f, "{}", self.0)
97    }
98}
99
100impl Serialize for SvmSignature {
101    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
102    where
103        S: serde::Serializer,
104    {
105        serializer.serialize_str(&self.to_string())
106    }
107}
108
109impl<'de> Deserialize<'de> for SvmSignature {
110    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
111    where
112        D: serde::Deserializer<'de>,
113    {
114        let s = String::deserialize(deserializer)?;
115        let sig = solana_signature::Signature::from_str(&s).map_err(serde::de::Error::custom)?;
116        Ok(SvmSignature(sig))
117    }
118}
119
120impl Address for SvmAddress {
121    type Network = SvmNetwork;
122}
123
124pub type SvmAsset = crate::core::Asset<SvmAddress>;
125
126pub trait ExplicitSvmNetwork {
127    const NETWORK: SvmNetwork;
128}
129
130pub trait ExplicitSvmAsset {
131    type Network: ExplicitSvmNetwork;
132    const ASSET: SvmAsset;
133}
134
135pub mod networks {
136    use super::*;
137
138    pub struct Solana;
139    impl ExplicitSvmNetwork for Solana {
140        const NETWORK: SvmNetwork = SvmNetwork {
141            name: "solana",
142            caip_2_id: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
143        };
144    }
145
146    pub struct SolanaDevnet;
147    impl ExplicitSvmNetwork for SolanaDevnet {
148        const NETWORK: SvmNetwork = SvmNetwork {
149            name: "solana-devnet",
150            caip_2_id: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
151        };
152    }
153
154    pub struct SolanaTestnet;
155    impl ExplicitSvmNetwork for SolanaTestnet {
156        const NETWORK: SvmNetwork = SvmNetwork {
157            name: "solana-testnet",
158            caip_2_id: "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z",
159        };
160    }
161}
162
163pub mod assets {
164    use solana_pubkey::pubkey;
165
166    use super::*;
167
168    macro_rules! create_usdc {
169        ($addr:expr) => {
170            SvmAsset {
171                address: SvmAddress($addr),
172                decimals: 6,
173                name: "USD Coin",
174                symbol: "USDC",
175            }
176        };
177    }
178
179    pub struct UsdcSolana;
180    impl ExplicitSvmAsset for UsdcSolana {
181        type Network = networks::Solana;
182        const ASSET: SvmAsset =
183            create_usdc!(pubkey!("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"));
184    }
185
186    pub struct UsdcSolanaDevnet;
187    impl ExplicitSvmAsset for UsdcSolanaDevnet {
188        type Network = networks::SolanaDevnet;
189        const ASSET: SvmAsset =
190            create_usdc!(pubkey!("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"));
191    }
192}