Skip to main content

ows_pay/
types.rs

1use serde::{Deserialize, Serialize};
2
3// ===========================================================================
4// Unified public types
5// ===========================================================================
6
7/// Which payment protocol was used.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum Protocol {
10    X402,
11}
12
13impl std::fmt::Display for Protocol {
14    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        match self {
16            Protocol::X402 => write!(f, "x402"),
17        }
18    }
19}
20
21/// Details about a payment that was made.
22#[derive(Debug, Clone)]
23pub struct PaymentInfo {
24    /// Human-readable amount (e.g. "$0.01").
25    pub amount: String,
26    /// Network/chain name (e.g. "Base", "Tempo").
27    pub network: String,
28    /// Token symbol (e.g. "USDC").
29    pub token: String,
30}
31
32/// Result of a `pay()` call.
33#[derive(Debug, Clone)]
34pub struct PayResult {
35    /// Which protocol handled the payment.
36    pub protocol: Protocol,
37    /// HTTP status of the final response.
38    pub status: u16,
39    /// Response body.
40    pub body: String,
41    /// Payment details. `None` if no payment was required (non-402).
42    pub payment: Option<PaymentInfo>,
43}
44
45/// A discovered payable service, normalized across protocols.
46#[derive(Debug, Clone)]
47pub struct Service {
48    /// Protocol this service uses.
49    pub protocol: Protocol,
50    /// Human-readable name.
51    pub name: String,
52    /// Full endpoint URL.
53    pub url: String,
54    /// Short description.
55    pub description: String,
56    /// Cheapest price display (e.g. "$0.01", "free").
57    pub price: String,
58    /// Network or chain (e.g. "base", "Tempo").
59    pub network: String,
60    /// Categories / tags.
61    pub tags: Vec<String>,
62}
63
64/// Result of a `discover()` call, including pagination info.
65#[derive(Debug, Clone)]
66pub struct DiscoverResult {
67    /// Discovered services on this page.
68    pub services: Vec<Service>,
69    /// Total number of services in the directory.
70    pub total: u64,
71    /// Limit used for this page.
72    pub limit: u64,
73    /// Offset used for this page.
74    pub offset: u64,
75}
76
77// ===========================================================================
78// x402 wire types (internal, used by x402 module)
79// ===========================================================================
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
82#[serde(rename_all = "camelCase")]
83pub struct PaymentRequirements {
84    pub scheme: String,
85    pub network: String,
86    #[serde(alias = "maxAmountRequired")]
87    pub amount: String,
88    pub asset: String,
89    #[serde(alias = "payTo")]
90    pub pay_to: String,
91    #[serde(default = "default_timeout")]
92    pub max_timeout_seconds: u64,
93    #[serde(default)]
94    pub extra: serde_json::Value,
95    #[serde(default)]
96    pub description: Option<String>,
97    #[serde(default)]
98    pub resource: Option<String>,
99}
100
101fn default_timeout() -> u64 {
102    30
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
106#[serde(rename_all = "camelCase")]
107pub struct X402Response {
108    #[serde(default)]
109    pub x402_version: Option<u32>,
110    pub accepts: Vec<PaymentRequirements>,
111    #[serde(default)]
112    pub resource: Option<serde_json::Value>,
113}
114
115/// The signed payment payload sent to the server in the payment header.
116#[derive(Debug, Clone, Serialize, Deserialize)]
117#[serde(untagged)]
118pub enum PaymentPayload {
119    V1(PaymentPayloadV1),
120    V2(PaymentPayloadV2),
121}
122
123/// x402 v1 payment payload.
124#[derive(Debug, Clone, Serialize, Deserialize)]
125#[serde(rename_all = "camelCase")]
126pub struct PaymentPayloadV1 {
127    pub x402_version: u32,
128    pub scheme: String,
129    pub network: String,
130    pub payload: serde_json::Value,
131}
132
133/// x402 v2 payment payload.
134#[derive(Debug, Clone, Serialize, Deserialize)]
135#[serde(rename_all = "camelCase")]
136pub struct PaymentPayloadV2 {
137    pub x402_version: u32,
138    pub accepted: PaymentRequirements,
139    pub resource: Option<serde_json::Value>,
140    pub payload: serde_json::Value,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct Eip3009Payload {
145    pub signature: String,
146    pub authorization: Eip3009Authorization,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
150#[serde(rename_all = "camelCase")]
151pub struct Eip3009Authorization {
152    pub from: String,
153    pub to: String,
154    pub value: String,
155    pub valid_after: String,
156    pub valid_before: String,
157    pub nonce: String,
158}
159
160// ===========================================================================
161// x402 discovery wire types
162// ===========================================================================
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
165#[serde(rename_all = "camelCase")]
166pub struct DiscoveredService {
167    pub resource: String,
168    #[serde(default)]
169    pub r#type: Option<String>,
170    #[serde(default)]
171    pub x402_version: Option<u32>,
172    #[serde(default)]
173    pub accepts: Vec<PaymentRequirements>,
174    #[serde(default)]
175    pub metadata: Option<ServiceMetadata>,
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct ServiceMetadata {
180    pub description: Option<String>,
181    #[serde(default)]
182    pub input: Option<serde_json::Value>,
183    #[serde(default)]
184    pub output: Option<serde_json::Value>,
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct DiscoveryResponse {
189    pub items: Vec<DiscoveredService>,
190    #[serde(default)]
191    pub pagination: Option<Pagination>,
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct Pagination {
196    pub limit: u64,
197    pub offset: u64,
198    pub total: u64,
199}
200
201// ===========================================================================
202// MoonPay wire types
203// ===========================================================================
204
205#[derive(Debug, Clone, Serialize)]
206pub struct MoonPayDepositRequest {
207    pub name: String,
208    pub wallet: String,
209    pub chain: String,
210    pub token: String,
211}
212
213#[derive(Debug, Clone, Deserialize)]
214#[serde(rename_all = "camelCase")]
215pub struct MoonPayDepositResponse {
216    pub id: String,
217    pub destination_wallet: String,
218    pub destination_chain: String,
219    pub customer_token: String,
220    pub deposit_url: String,
221    pub wallets: Vec<DepositWallet>,
222    pub instructions: String,
223}
224
225#[derive(Debug, Clone, Deserialize)]
226#[serde(rename_all = "camelCase")]
227pub struct DepositWallet {
228    pub address: String,
229    pub chain: String,
230    pub qr_code: String,
231}
232
233#[derive(Debug, Clone, Serialize)]
234pub struct MoonPayBalanceRequest {
235    pub wallet: String,
236    pub chain: String,
237}
238
239#[derive(Debug, Clone, Deserialize)]
240pub struct MoonPayBalanceResponse {
241    pub items: Vec<TokenBalance>,
242}
243
244#[derive(Debug, Clone, Deserialize)]
245pub struct TokenBalance {
246    pub address: String,
247    pub name: String,
248    pub symbol: String,
249    pub chain: String,
250    pub decimals: u32,
251    pub balance: BalanceInfo,
252}
253
254#[derive(Debug, Clone, Deserialize)]
255pub struct BalanceInfo {
256    pub amount: f64,
257    pub value: f64,
258    pub price: f64,
259}
260
261/// Result of `ows fund`.
262#[derive(Debug, Clone)]
263pub struct FundResult {
264    pub deposit_id: String,
265    pub deposit_url: String,
266    pub wallets: Vec<(String, String)>,
267    pub instructions: String,
268}