Skip to content

Commit 390ae9e

Browse files
ASCII Art, delete an api key, new key, get usage, account balance
1 parent 9b53fc5 commit 390ae9e

5 files changed

Lines changed: 142 additions & 31 deletions

File tree

src/commands/account_info.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use reqwest::Client;
2+
use serde::Deserialize;
3+
4+
#[derive(Debug, Deserialize)]
5+
pub struct UserBalances {
6+
pub calls: i64,
7+
pub balance: i64,
8+
}
9+
10+
pub async fn get_rpc_calls(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
11+
let res = client
12+
.get("https://api.cloud.developerdao.com/api/balances")
13+
.send()
14+
.await?
15+
.error_for_status()?
16+
.json::<UserBalances>()
17+
.await?;
18+
19+
println!("You've made {} RPC calls this month\n", res.calls);
20+
Ok(())
21+
}
22+
23+
pub async fn get_balance(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
24+
let res = client
25+
.get("https://api.cloud.developerdao.com/api/balances")
26+
.send()
27+
.await?
28+
.error_for_status()?
29+
.json::<UserBalances>()
30+
.await?;
31+
32+
println!(
33+
"Your account has a balance of ${}\n",
34+
res.balance as f64 / 100.0
35+
);
36+
Ok(())
37+
}

src/commands/keys.rs

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use arboard::Clipboard;
22
use console::Term;
3-
use dialoguer::{FuzzySelect, theme::ColorfulTheme};
3+
use dialoguer::{Confirm, FuzzySelect, theme::ColorfulTheme};
44
use reqwest::Client;
55

66
use crate::types::{CHAINS, Key, RedactedKey};
@@ -106,3 +106,74 @@ pub async fn get_keys_interactive(
106106

107107
Ok(())
108108
}
109+
110+
pub async fn new_api_key(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
111+
let mut clipboard = Clipboard::new()?;
112+
let new_key = Key {
113+
apikey: client
114+
.post("https://api.cloud.developerdao.com/api/keys")
115+
.send()
116+
.await?
117+
.error_for_status()?
118+
.text()
119+
.await?,
120+
};
121+
122+
let redacted_key = new_key.as_redacted();
123+
clipboard.set_text(new_key.apikey)?;
124+
125+
println!("Your new API key:\n{redacted_key}\nSuccessfully created and copied to clipboard!");
126+
Ok(())
127+
}
128+
129+
pub async fn delete_api_key(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
130+
let api_keys: Vec<Key> = client
131+
.get("https://api.cloud.developerdao.com/api/keys")
132+
.send()
133+
.await?
134+
.error_for_status()?
135+
.json::<Vec<Key>>()
136+
.await?;
137+
138+
if api_keys.is_empty() {
139+
Err("Err: deletion failed. No API keys found.")?
140+
}
141+
142+
let redacted_keys = api_keys
143+
.iter()
144+
.map(|e| e.as_redacted())
145+
.collect::<Vec<RedactedKey>>();
146+
147+
let index = dialoguer::Select::with_theme(&ColorfulTheme::default())
148+
.items(&redacted_keys)
149+
.with_prompt("Select an API key to delete")
150+
.interact()?;
151+
152+
let confirmation = Confirm::new()
153+
.with_prompt(format!(
154+
"Are you want you want to delete {}?",
155+
redacted_keys[index].redacted
156+
))
157+
.interact()
158+
.unwrap();
159+
160+
if !confirmation {
161+
Err("API key deletion aborted")?
162+
}
163+
164+
client
165+
.delete(format!(
166+
"https://api.cloud.developerdao.com/api/keys/{}",
167+
api_keys[index].apikey
168+
))
169+
.send()
170+
.await?
171+
.error_for_status()?;
172+
173+
println!(
174+
"Successfully deleted api key: {}",
175+
redacted_keys[index].redacted
176+
);
177+
178+
Ok(())
179+
}

src/commands/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod keys;
2+
pub mod account_info;

src/main.rs

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
use crate::types::LoginRequest;
2-
use clap::{Parser, Subcommand, ValueEnum};
1+
use crate::{
2+
commands::{
3+
account_info::{get_balance, get_rpc_calls},
4+
keys::{delete_api_key, new_api_key},
5+
},
6+
types::{ASCII_ART, LoginRequest},
7+
};
8+
use clap::{Parser, Subcommand};
39
use commands::keys::get_keys_interactive;
410
use console::Term;
511
use dialoguer::{Input, Password, theme::ColorfulTheme};
@@ -18,29 +24,13 @@ pub enum Command {
1824
GetApiKey {
1925
#[arg(short, long)]
2026
unsafe_print: bool,
21-
},
22-
DeleteApiKey {
2327
#[arg(short, long)]
24-
key: String,
28+
no_url: bool,
2529
},
30+
DeleteApiKey,
2631
NewApiKey,
27-
TrackUsage {
28-
#[arg(short)]
29-
service: Service,
30-
},
32+
TrackUsage,
3133
Balance,
32-
GetPaymentInfo,
33-
SubmitPayment {
34-
#[arg(short, long)]
35-
hash: String,
36-
#[arg(short, long)]
37-
plan: Option<String>,
38-
},
39-
}
40-
41-
#[derive(Debug, Copy, Clone, ValueEnum)]
42-
pub enum Service {
43-
Rpc,
4434
}
4535

4636
#[tokio::main]
@@ -49,7 +39,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
4939
let mut term = Term::stdout();
5040
term.clear_screen()?;
5141
term.set_title("Developer DAO Cloud");
52-
term.write_line("Login to Developer DAO Cloud")?;
42+
term.write_line(ASCII_ART)?;
43+
term.write_line("Login")?;
5344
term.write_line("")?;
5445

5546
let email: String = Input::with_theme(&ColorfulTheme::default())
@@ -71,18 +62,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
7162
.json(&login)
7263
.send()
7364
.await?
74-
.error_for_status()?;
65+
.error_for_status()
66+
.map_err(|_| "Invalid username or password")?;
7567

7668
match cli_input.cmd {
77-
Command::GetApiKey { unsafe_print } => {
69+
Command::GetApiKey { unsafe_print, .. } => {
7870
get_keys_interactive(&client, &mut term, unsafe_print).await?
7971
}
80-
Command::DeleteApiKey { key: _ } => todo!(),
81-
Command::NewApiKey => todo!(),
82-
Command::TrackUsage { service: _ } => todo!(),
83-
Command::Balance => todo!(),
84-
Command::GetPaymentInfo => todo!(),
85-
Command::SubmitPayment { hash: _, plan: _ } => todo!(),
72+
Command::DeleteApiKey => delete_api_key(&client).await?,
73+
Command::NewApiKey => new_api_key(&client).await?,
74+
Command::TrackUsage => get_rpc_calls(&client).await?,
75+
Command::Balance => get_balance(&client).await?,
8676
};
8777

8878
Ok(())

src/types.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
use std::fmt::Display;
22

33
use serde::{Deserialize, Serialize};
4+
5+
pub const ASCII_ART: &'static str = {
6+
r#"
7+
██████╗ ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗
8+
██╔══██╗ ██╔══██╗ ██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗
9+
██║ ██║ ██║ ██║ ██║ ██║ ██║ ██║██║ ██║██║ ██║
10+
██║ ██║ ██║ ██║ ██║ ██║ ██║ ██║██║ ██║██║ ██║
11+
██████╔╝███████╗██████╔╝ ╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝
12+
╚═════╝ ╚══════╝╚═════╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝
13+
"#
14+
};
15+
416
pub static CHAINS: &[Chains] = &[
517
Chains::Ethereum,
618
Chains::Base,

0 commit comments

Comments
 (0)