1use clap::ValueEnum;
9
10#[derive(thiserror::Error, Debug)]
11pub enum Error {
12 #[error(
13 "--auth-mode=enforce requires a transaction with existing authorization entries; use a different auth mode when building new transactions"
14 )]
15 EnforceRequiresExistingAuth,
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)]
19pub enum AuthMode {
20 Enforce,
22 Root,
25 #[value(name = "non-root")]
27 NonRoot,
28}
29
30impl AuthMode {
31 pub fn to_rpc(self) -> soroban_rpc::AuthMode {
33 match self {
34 AuthMode::Enforce => soroban_rpc::AuthMode::Enforce,
35 AuthMode::Root => soroban_rpc::AuthMode::Record,
36 AuthMode::NonRoot => soroban_rpc::AuthMode::RecordAllowNonRoot,
37 }
38 }
39}
40
41#[derive(Debug, clap::Args, Clone, Default)]
50#[group(skip)]
51pub struct Args {
52 #[arg(
58 long,
59 env = "STELLAR_AUTH_MODE",
60 help_heading = crate::commands::HEADING_RPC,
61 )]
62 pub auth_mode: Option<AuthMode>,
63}
64
65impl Args {
66 pub fn to_rpc(&self) -> Option<soroban_rpc::AuthMode> {
67 self.auth_mode.map(AuthMode::to_rpc)
68 }
69
70 pub fn validate_not_enforce(&self) -> Result<(), Error> {
71 if matches!(self.auth_mode, Some(AuthMode::Enforce)) {
72 return Err(Error::EnforceRequiresExistingAuth);
73 }
74 Ok(())
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn unset_omits_rpc_auth_mode() {
84 assert!(Args::default().to_rpc().is_none());
85 }
86
87 #[test]
88 fn enforce_maps_to_enforce() {
89 assert!(matches!(
90 AuthMode::Enforce.to_rpc(),
91 soroban_rpc::AuthMode::Enforce
92 ));
93 }
94
95 #[test]
96 fn root_maps_to_record() {
97 assert!(matches!(
98 AuthMode::Root.to_rpc(),
99 soroban_rpc::AuthMode::Record
100 ));
101 }
102
103 #[test]
104 fn non_root_maps_to_record_allow_non_root() {
105 assert!(matches!(
106 AuthMode::NonRoot.to_rpc(),
107 soroban_rpc::AuthMode::RecordAllowNonRoot
108 ));
109 }
110
111 #[test]
112 fn validate_not_enforce_requires_recording_mode() {
113 assert!(matches!(
114 Args {
115 auth_mode: Some(AuthMode::Enforce)
116 }
117 .validate_not_enforce(),
118 Err(Error::EnforceRequiresExistingAuth)
119 ));
120 }
121
122 #[test]
123 fn validate_not_enforce_allows_recording_modes() {
124 assert!(Args {
125 auth_mode: Some(AuthMode::Root)
126 }
127 .validate_not_enforce()
128 .is_ok());
129 assert!(Args {
130 auth_mode: Some(AuthMode::NonRoot)
131 }
132 .validate_not_enforce()
133 .is_ok());
134 assert!(Args::default().validate_not_enforce().is_ok());
135 }
136}