Skip to main content

x402_cli/x402/
mod.rs

1pub mod deploy;
2pub mod facilitator;
3pub mod project;
4pub mod test;
5pub mod wallet;
6
7use anyhow::Result;
8use clap::Parser;
9use colored::Colorize;
10
11pub use facilitator::Facilitator;
12pub use project::Project;
13pub use wallet::Wallet;
14
15#[derive(Parser)]
16pub enum WalletCommands {
17    #[command(name = "create")]
18    Create {
19        #[arg(short, long, default_value = "testnet")]
20        network: String,
21    },
22    #[command(name = "import")]
23    Import {
24        #[arg(short, long)]
25        private_key: String,
26        #[arg(short, long, default_value = "testnet")]
27        network: String,
28    },
29}
30
31#[derive(Parser)]
32pub enum FacilitatorCommands {
33    #[command(name = "start")]
34    Start {
35        #[arg(short, long, default_value = "3001")]
36        port: u16,
37        #[arg(long)]
38        wallet: Option<String>,
39        #[arg(long)]
40        private_key: Option<String>,
41        #[arg(short, long, default_value = "testnet")]
42        network: String,
43    },
44    #[command(name = "stop")]
45    Stop,
46}
47
48#[derive(Parser)]
49pub enum TestCommands {
50    #[command(name = "payment")]
51    Payment {
52        #[arg(short, long)]
53        api: String,
54        #[arg(short, long, default_value = "1000")]
55        amount: u64,
56    },
57}
58
59pub async fn init(name: String, chain: String, framework: String) -> Result<()> {
60    println!(
61        "{}",
62        format!("Initializing x402 project: {}", name.cyan()).bold()
63    );
64
65    let project = Project::new(name.clone(), chain, framework);
66
67    println!("{}", "  Creating project structure...".dimmed());
68    project.create_directories()?;
69
70    println!("{}", "  Creating configuration files...".dimmed());
71    project.create_config_files()?;
72
73    println!("{}", "  Installing dependencies...".dimmed());
74    project.install_dependencies()?;
75
76    project.generate_readme()?;
77
78    println!(
79        "{}",
80        format!("✓ Project initialized: {}", name.green()).bold()
81    );
82
83    println!(
84        "{}",
85        format!("  Project location: {}/", name.cyan()).dimmed()
86    );
87
88    Ok(())
89}
90
91pub async fn handle_wallet(command: WalletCommands) -> Result<()> {
92    match command {
93        WalletCommands::Create { network } => {
94            println!("{}", "Creating wallet...".cyan());
95
96            let wallet = Wallet::create(&network).await?;
97
98            wallet.save_to_file()?;
99
100            wallet.fund_from_faucet().await?;
101
102            println!(
103                "{}",
104                format!("  Wallet Address: {}", wallet.address.cyan()).dimmed()
105            );
106
107            Ok(())
108        }
109        WalletCommands::Import { private_key, network } => {
110            println!("{}", "Importing wallet...".cyan());
111
112            let wallet = Wallet::import(&private_key, &network)?;
113
114            wallet.save_to_file()?;
115
116            println!(
117                "{}",
118                format!("  Wallet Address: {}", wallet.address.cyan()).dimmed()
119            );
120
121            Ok(())
122        }
123    }
124}
125
126pub async fn handle_facilitator(command: FacilitatorCommands) -> Result<()> {
127    match command {
128        FacilitatorCommands::Start { port, wallet, private_key, network } => {
129            let wallet = if let Some(private_key) = private_key {
130                Wallet::import(&private_key, &network)?
131            } else if let Some(wallet_address) = wallet {
132                Wallet::load_from_address(&wallet_address)?
133            } else {
134                Wallet::find_default()?
135            };
136
137            let _facilitator = Facilitator::start(port, wallet)?;
138
139            println!("{}", "  Start facilitator in background...".dimmed());
140            println!(
141                "{}",
142                "  Run `x402 facilitator stop` to stop".yellow().dimmed()
143            );
144
145            Ok(())
146        }
147        FacilitatorCommands::Stop => {
148            Facilitator::stop()?;
149            println!("{}", "✓ Facilitator stopped".green().bold());
150            Ok(())
151        }
152    }
153}
154
155pub async fn handle_test(command: TestCommands) -> Result<()> {
156    match command {
157        TestCommands::Payment { api, amount } => {
158            println!("{}", "Testing payment flow...".cyan());
159            println!("{}", format!("  API URL: {}", api.cyan()).dimmed());
160            println!("{}", format!("  Amount: {}", amount));
161
162            test::test_payment_flow(&api, amount).await?;
163
164            Ok(())
165        }
166    }
167}
168
169pub async fn deploy(provider: String) -> Result<()> {
170    println!("{}", format!("Deploying to {}", provider.cyan()).bold());
171
172    deploy::deploy(&provider).await?;
173
174    Ok(())
175}