1use serde::{Deserialize, Serialize};
2
3use crate::{
4 transport::{PaymentPayload, PaymentRequirements, SettlementResponse},
5 types::{AnyJson, Base64EncodedHeader, Record, X402V2},
6};
7
8#[derive(Debug, Clone)]
9pub struct PaymentRequest {
10 pub payment_signature: Base64EncodedHeader,
11 pub payment_payload: PaymentPayload,
12 pub payment_requirements: PaymentRequirements,
13}
14
15#[derive(Debug, Clone)]
16pub enum VerifyResult {
17 Valid(VerifyValid),
18 Invalid(VerifyInvalid),
19}
20
21impl VerifyResult {
22 pub fn is_valid(&self) -> bool {
23 matches!(self, VerifyResult::Valid(_))
24 }
25
26 pub fn valid(valid: VerifyValid) -> Self {
27 VerifyResult::Valid(valid)
28 }
29
30 pub fn invalid(invalid: VerifyInvalid) -> Self {
31 VerifyResult::Invalid(invalid)
32 }
33
34 pub fn as_valid(&self) -> Option<&VerifyValid> {
35 match self {
36 VerifyResult::Valid(v) => Some(v),
37 _ => None,
38 }
39 }
40
41 pub fn as_invalid(&self) -> Option<&VerifyInvalid> {
42 match self {
43 VerifyResult::Invalid(v) => Some(v),
44 _ => None,
45 }
46 }
47}
48
49#[derive(Debug, Clone)]
50pub struct VerifyValid {
51 pub payer: String,
52}
53
54#[derive(Debug, Clone)]
55pub struct VerifyInvalid {
56 pub invalid_reason: String,
57 pub payer: Option<String>,
58}
59
60#[derive(Debug, Clone)]
61pub enum SettleResult {
62 Success(SettleSuccess),
63 Failed(SettleFailed),
64}
65
66impl SettleResult {
67 pub fn is_success(&self) -> bool {
68 matches!(self, SettleResult::Success(_))
69 }
70
71 pub fn success(success: SettleSuccess) -> Self {
72 SettleResult::Success(success)
73 }
74
75 pub fn failed(failed: SettleFailed) -> Self {
76 SettleResult::Failed(failed)
77 }
78
79 pub fn as_success(&self) -> Option<&SettleSuccess> {
80 match self {
81 SettleResult::Success(v) => Some(v),
82 _ => None,
83 }
84 }
85
86 pub fn as_failed(&self) -> Option<&SettleFailed> {
87 match self {
88 SettleResult::Failed(v) => Some(v),
89 _ => None,
90 }
91 }
92}
93
94#[derive(Debug, Clone)]
95pub struct SettleSuccess {
96 pub payer: String,
97 pub transaction: String,
98 pub network: String,
99}
100
101#[derive(Debug, Clone)]
102pub struct SettleFailed {
103 pub error_reason: String,
104 pub payer: Option<String>,
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
108#[serde(rename_all = "camelCase")]
109pub struct SupportedKinds {
110 pub x402_version: X402V2,
111 pub scheme: String,
112 pub network: String,
113 pub extra: Option<AnyJson>,
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
117#[serde(rename_all = "camelCase")]
118pub struct SupportedResponse {
119 pub kinds: Vec<SupportedKinds>,
120
121 pub extensions: Vec<AnyJson>,
124 pub signers: Record<Vec<String>>,
126}
127
128impl From<SettleSuccess> for SettlementResponse {
129 fn from(success: SettleSuccess) -> Self {
130 SettlementResponse {
131 success: true,
132 transaction: success.transaction,
133 network: success.network,
134 payer: success.payer,
135 }
136 }
137}
138
139pub trait Facilitator {
141 type Error: std::error::Error;
142
143 fn supported(&self) -> impl Future<Output = Result<SupportedResponse, Self::Error>>;
144
145 fn verify(
146 &self,
147 request: PaymentRequest,
148 ) -> impl Future<Output = Result<VerifyResult, Self::Error>>;
149
150 fn settle(
151 &self,
152 request: PaymentRequest,
153 ) -> impl Future<Output = Result<SettleResult, Self::Error>>;
154}