r402_core/wire/
supported.rs1use std::collections::HashMap;
4
5use compact_str::CompactString;
6use serde::{Deserialize, Serialize};
7use serde_with::{VecSkipError, serde_as};
8
9use crate::chain::ChainId;
10
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13#[serde(rename_all = "camelCase", deny_unknown_fields)]
14#[non_exhaustive]
15pub struct SupportedPaymentKind {
16 pub x402_version: u8,
18 pub scheme: CompactString,
20 pub network: CompactString,
22 #[serde(default, skip_serializing_if = "Option::is_none")]
24 pub extra: Option<serde_json::Value>,
25}
26
27impl SupportedPaymentKind {
28 #[must_use]
31 pub fn new(
32 x402_version: u8,
33 scheme: impl Into<CompactString>,
34 network: impl Into<CompactString>,
35 ) -> Self {
36 Self {
37 x402_version,
38 scheme: scheme.into(),
39 network: network.into(),
40 extra: None,
41 }
42 }
43
44 #[must_use]
46 pub fn with_extra(mut self, extra: serde_json::Value) -> Self {
47 self.extra = Some(extra);
48 self
49 }
50
51 #[must_use]
54 pub fn with_optional_extra(mut self, extra: Option<serde_json::Value>) -> Self {
55 self.extra = extra;
56 self
57 }
58}
59
60#[serde_as]
65#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
66#[serde(rename_all = "camelCase", deny_unknown_fields)]
67#[non_exhaustive]
68pub struct SupportedResponse {
69 #[serde_as(as = "VecSkipError<_>")]
71 pub kinds: Vec<SupportedPaymentKind>,
72 #[serde(default)]
74 pub extensions: Vec<CompactString>,
75 #[serde(default)]
78 pub signers: HashMap<CompactString, Vec<CompactString>>,
79}
80
81impl SupportedResponse {
82 #[must_use]
86 pub fn new() -> Self {
87 Self::default()
88 }
89
90 #[must_use]
92 pub fn with_kinds(mut self, kinds: Vec<SupportedPaymentKind>) -> Self {
93 self.kinds = kinds;
94 self
95 }
96
97 #[must_use]
99 pub fn with_extensions(mut self, extensions: Vec<CompactString>) -> Self {
100 self.extensions = extensions;
101 self
102 }
103
104 #[must_use]
106 pub fn with_signers(mut self, signers: HashMap<CompactString, Vec<CompactString>>) -> Self {
107 self.signers = signers;
108 self
109 }
110
111 #[must_use]
116 pub fn signers_for_chain(&self, chain_id: &ChainId) -> Vec<&str> {
117 let exact = CompactString::from(chain_id.to_string());
118 let wildcard = CompactString::from(format!("{}:*", chain_id.namespace()));
119 let mut out = Vec::new();
120 if let Some(list) = self.signers.get(&exact) {
121 out.extend(list.iter().map(CompactString::as_str));
122 }
123 if let Some(list) = self.signers.get(&wildcard) {
124 out.extend(list.iter().map(CompactString::as_str));
125 }
126 out
127 }
128}