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}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
114#[serde(rename_all = "camelCase")]
115pub struct PaymentPayload {
116    pub x402_version: u32,
117    pub scheme: String,
118    pub network: String,
119    /// Scheme-specific payload. For "exact" (EVM): contains `Eip3009Payload`.
120    pub payload: serde_json::Value,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct Eip3009Payload {
125    pub signature: String,
126    pub authorization: Eip3009Authorization,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
130#[serde(rename_all = "camelCase")]
131pub struct Eip3009Authorization {
132    pub from: String,
133    pub to: String,
134    pub value: String,
135    pub valid_after: String,
136    pub valid_before: String,
137    pub nonce: String,
138}
139
140// ===========================================================================
141// x402 discovery wire types
142// ===========================================================================
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
145#[serde(rename_all = "camelCase")]
146pub struct DiscoveredService {
147    pub resource: String,
148    #[serde(default)]
149    pub r#type: Option<String>,
150    #[serde(default)]
151    pub x402_version: Option<u32>,
152    #[serde(default)]
153    pub accepts: Vec<PaymentRequirements>,
154    #[serde(default)]
155    pub metadata: Option<ServiceMetadata>,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct ServiceMetadata {
160    pub description: Option<String>,
161    #[serde(default)]
162    pub input: Option<serde_json::Value>,
163    #[serde(default)]
164    pub output: Option<serde_json::Value>,
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct DiscoveryResponse {
169    pub items: Vec<DiscoveredService>,
170    #[serde(default)]
171    pub pagination: Option<Pagination>,
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct Pagination {
176    pub limit: u64,
177    pub offset: u64,
178    pub total: u64,
179}
180
181// ===========================================================================
182// MoonPay wire types
183// ===========================================================================
184
185#[derive(Debug, Clone, Serialize)]
186pub struct MoonPayDepositRequest {
187    pub name: String,
188    pub wallet: String,
189    pub chain: String,
190    pub token: String,
191}
192
193#[derive(Debug, Clone, Deserialize)]
194#[serde(rename_all = "camelCase")]
195pub struct MoonPayDepositResponse {
196    pub id: String,
197    pub destination_wallet: String,
198    pub destination_chain: String,
199    pub customer_token: String,
200    pub deposit_url: String,
201    pub wallets: Vec<DepositWallet>,
202    pub instructions: String,
203}
204
205#[derive(Debug, Clone, Deserialize)]
206#[serde(rename_all = "camelCase")]
207pub struct DepositWallet {
208    pub address: String,
209    pub chain: String,
210    pub qr_code: String,
211}
212
213#[derive(Debug, Clone, Serialize)]
214pub struct MoonPayBalanceRequest {
215    pub wallet: String,
216    pub chain: String,
217}
218
219#[derive(Debug, Clone, Deserialize)]
220pub struct MoonPayBalanceResponse {
221    pub items: Vec<TokenBalance>,
222}
223
224#[derive(Debug, Clone, Deserialize)]
225pub struct TokenBalance {
226    pub address: String,
227    pub name: String,
228    pub symbol: String,
229    pub chain: String,
230    pub decimals: u32,
231    pub balance: BalanceInfo,
232}
233
234#[derive(Debug, Clone, Deserialize)]
235pub struct BalanceInfo {
236    pub amount: f64,
237    pub value: f64,
238    pub price: f64,
239}
240
241/// Result of `ows fund`.
242#[derive(Debug, Clone)]
243pub struct FundResult {
244    pub deposit_id: String,
245    pub deposit_url: String,
246    pub wallets: Vec<(String, String)>,
247    pub instructions: String,
248}