Skip to main content

r402_protocol/payment/
mod.rs

1//! Payment envelopes for the x402 protocol.
2//!
3//! JSON is camelCase with `deny_unknown_fields`. Identifier strings use
4//! [`compact_str::CompactString`].
5
6mod codec;
7mod extensions;
8mod overrides;
9mod payload;
10mod price;
11mod required;
12mod requirements;
13mod resource;
14mod settle;
15mod supported;
16mod verify;
17
18use std::str::FromStr;
19
20pub use codec::{Base64Bytes, U64String, UnixTimestamp, V2, Version, Version2};
21pub use extensions::{
22    EXTENSION_RESPONSE_LOG_FIELDS, ExtensionEntry, Extensions, schema_has_external_ref,
23};
24pub use overrides::{
25    DEFAULT_ASSET_DECIMALS, SettlementOverrideError, SettlementOverrides,
26    asset_decimals_from_extra, resolve_settlement_override_amount,
27};
28pub use payload::PaymentPayload;
29pub use price::PriceTag;
30pub use required::PaymentRequired;
31pub use requirements::{PaymentRequirements, find_matching_requirements};
32pub use resource::ResourceInfo;
33pub use settle::{SettleRequest, SettleResponse};
34pub use supported::{SupportedPaymentKind, SupportedResponse};
35pub use verify::{TypedVerifyRequest, VerifyRequest, VerifyResponse};
36
37use crate::network::ChainId;
38use crate::scheme::SchemeSlug;
39
40pub(crate) fn scheme_slug_from_json(json: &serde_json::Value) -> Option<SchemeSlug> {
41    let version = json.get("x402Version")?.as_u64()?;
42    let version: u8 = version.try_into().ok()?;
43    if version != Version2::VALUE {
44        return None;
45    }
46    let accepted = json.get("paymentPayload")?.get("accepted")?;
47    let chain_id = ChainId::from_str(accepted.get("network")?.as_str()?).ok()?;
48    let scheme = accepted.get("scheme")?.as_str()?;
49    Some(SchemeSlug::new(chain_id, scheme.into()))
50}
51
52pub(crate) fn network_from_json(json: &serde_json::Value) -> &str {
53    json.get("paymentRequirements")
54        .and_then(|req| req.get("network"))
55        .and_then(serde_json::Value::as_str)
56        .unwrap_or_default()
57}