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