├── .gitignore ├── src ├── widgets │ ├── mod.rs │ └── settings_widget.rs ├── util.rs ├── settings.rs ├── nip59.rs ├── db.rs └── main.rs ├── static ├── logo.png └── mostrui.png ├── settings.tpl.toml ├── Cargo.toml ├── LICENSE ├── README.md └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.vscode -------------------------------------------------------------------------------- /src/widgets/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod settings_widget; 2 | -------------------------------------------------------------------------------- /static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MostroP2P/mostrui/HEAD/static/logo.png -------------------------------------------------------------------------------- /static/mostrui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MostroP2P/mostrui/HEAD/static/mostrui.png -------------------------------------------------------------------------------- /settings.tpl.toml: -------------------------------------------------------------------------------- 1 | # Mostro pubkey, it can be hex or npub 2 | mostro_pubkey = "0000000000000000000000000000000000000000000000000000000000000000" 3 | # Relays to connect to 4 | relays = ["wss://relay.mostro.network", "wss://nostr.bilthon.dev"] 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mostrui" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license = "MIT" 6 | authors = ["Francisco Calderón "] 7 | description = "Mostro P2P TUI client" 8 | homepage = "https://mostro.network" 9 | repository = "https://github.com/MostroP2P/mostrui" 10 | 11 | [dependencies] 12 | chrono = { version = "0.4.38", features = ["clock"] } 13 | config = "0.14.0" 14 | crossterm = { version = "0.28.1", features = ["event-stream"] } 15 | mostro-core = "0.6.11" 16 | nostr-sdk = "0.35.0" 17 | ratatui = "0.29.0" 18 | serde = "1.0.213" 19 | sqlx = { version = "0.8.2", features = ["sqlite", "runtime-tokio-native-tls"] } 20 | tokio = { version = "1.40.0", features = ["full"] } 21 | tui-input = "0.10.1" 22 | uuid = "1.10.0" 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Francisco Calderón 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mostrui 🧌 2 | 3 | ![Mostro-logo](static/logo.png) 4 | 5 | **This is work in progres** 6 | 7 | Terminal client for p2p using Mostro protocol. 8 | 9 | ![tui](static/mostrui.png) 10 | 11 | ## Requirements: 12 | 13 | 0. You need Rust version 1.64 or higher to compile. 14 | 15 | ## Install dependencies: 16 | 17 | To compile on Ubuntu/Pop!\_OS, please install [cargo](https://www.rust-lang.org/tools/install), then run the following commands: 18 | 19 | ```bash 20 | $ sudo apt update 21 | $ sudo apt install -y cmake build-essential pkg-config 22 | ``` 23 | 24 | ## Install 25 | 26 | ```bash 27 | $ git clone https://github.com/MostroP2P/mostrui.git 28 | $ cd mostrui 29 | ``` 30 | 31 | ### Settings 32 | 33 | Make sure that you have the following settings in your `~/.mostrui/settings.toml` file, you can find an example of the settings file in `settings.tpl.toml`, so you can copy it and modify it to your needs. 34 | 35 | ```toml 36 | mostro_pubkey = "0000000000000000000000000000000000000000000000000000000000000000" 37 | relays = ["wss://relay.mostro.network", "wss://nostr.bilthon.dev"] 38 | ``` 39 | 40 | ### Run 41 | 42 | ```bash 43 | $ cargo run 44 | ``` 45 | 46 | ## Progress Overview 47 | - [x] Displays order list 48 | - [x] Settings tab 49 | - [ ] Take orders (Buy & Sell) 50 | - [ ] Posts Orders (Buy & Sell) 51 | - [ ] Direct message with peers (use nip-17) 52 | - [ ] Fiat sent 53 | - [ ] Release 54 | - [ ] Maker cancel pending order 55 | - [ ] Cooperative cancellation 56 | - [ ] Buyer: add new invoice if payment fails 57 | - [ ] Rate users 58 | - [ ] List own orders 59 | - [ ] Dispute flow (users) 60 | - [ ] Dispute management (for admins) 61 | - [ ] Conversation key management 62 | - [ ] Create buy orders with LN address 63 | - [ ] Nip-06 support (identity management) 64 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | use mostro_core::order::{Kind as OrderKind, SmallOrder as Order, Status}; 2 | use nostr_sdk::prelude::*; 3 | use std::str::FromStr; 4 | use uuid::Uuid; 5 | 6 | pub fn order_from_tags(event: Event) -> Result { 7 | let tags = event.tags; 8 | let mut order = Order { 9 | created_at: Some(event.created_at.as_u64() as i64), 10 | ..Default::default() 11 | }; 12 | for tag in tags { 13 | let t = tag.as_slice(); 14 | let v = t.get(1).unwrap().as_str(); 15 | match t.first().unwrap().as_str() { 16 | "d" => { 17 | let id = v.parse::(); 18 | let id = match id { 19 | core::result::Result::Ok(id) => id, 20 | Err(_) => continue, 21 | }; 22 | order.id = Some(id); 23 | } 24 | "k" => { 25 | order.kind = Some(OrderKind::from_str(v).unwrap()); 26 | } 27 | "f" => { 28 | order.fiat_code = v.to_string(); 29 | } 30 | "s" => { 31 | order.status = Some(Status::from_str(v).unwrap_or(Status::Dispute)); 32 | } 33 | "amt" => { 34 | order.amount = v.parse::().unwrap(); 35 | } 36 | "fa" => { 37 | if v.contains('.') { 38 | continue; 39 | } 40 | let max = t.get(2); 41 | if max.is_some() { 42 | order.min_amount = v.parse::().ok(); 43 | order.max_amount = max.unwrap().parse::().ok(); 44 | } else { 45 | let fa = v.parse::(); 46 | order.fiat_amount = fa.unwrap_or(0); 47 | } 48 | } 49 | "pm" => { 50 | order.payment_method = v.to_string(); 51 | } 52 | "premium" => { 53 | order.premium = v.parse::().unwrap(); 54 | } 55 | _ => {} 56 | } 57 | } 58 | 59 | Ok(order) 60 | } 61 | -------------------------------------------------------------------------------- /src/widgets/settings_widget.rs: -------------------------------------------------------------------------------- 1 | use nostr_sdk::prelude::{PublicKey, SecretKey}; 2 | use nostr_sdk::ToBech32; 3 | use ratatui::{ 4 | buffer::Buffer, 5 | layout::{Constraint, Direction, Layout, Rect}, 6 | style::{Color, Style}, 7 | widgets::{Block, Widget}, 8 | }; 9 | use std::str::FromStr; 10 | 11 | pub struct SettingsWidget { 12 | pub pubkey: PublicKey, 13 | pub secret: SecretKey, 14 | } 15 | 16 | impl SettingsWidget { 17 | pub fn new(pubkey: PublicKey, secret: SecretKey) -> Self { 18 | Self { pubkey, secret } 19 | } 20 | } 21 | 22 | impl Widget for SettingsWidget { 23 | fn render(self, area: Rect, buf: &mut Buffer) { 24 | let layout = create_layout(area); 25 | render_block( 26 | layout[0], 27 | buf, 28 | "Mostro info ℹ️", 29 | "Public key of this mostro operator", 30 | &self.pubkey.to_bech32().unwrap(), 31 | ); 32 | render_block( 33 | layout[1], 34 | buf, 35 | "Secret key 🔑", 36 | "Be mindful of this information", 37 | &self.secret.to_bech32().unwrap(), 38 | ); 39 | } 40 | } 41 | 42 | fn create_layout(area: Rect) -> Vec { 43 | Layout::default() 44 | .direction(Direction::Vertical) 45 | .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()) 46 | .split(area) 47 | .to_vec() 48 | } 49 | 50 | fn render_block(area: Rect, buf: &mut Buffer, title: &str, label: &str, value: &str) { 51 | let block = Block::bordered().title(title); 52 | let inner_area = block.inner(area); 53 | block.render(area, buf); 54 | 55 | render_label_and_value(inner_area, buf, label, value); 56 | } 57 | 58 | fn render_label_and_value(inner_area: Rect, buf: &mut Buffer, label: &str, value: &str) { 59 | let label_color = Style::default().fg(Color::from_str("#14161C").unwrap()); 60 | let value_color = Style::default().fg(Color::White); 61 | 62 | buf.set_string(inner_area.x + 2, inner_area.y + 1, label, label_color); 63 | buf.set_string(inner_area.x + 2, inner_area.y + 3, value, value_color); 64 | } 65 | -------------------------------------------------------------------------------- /src/settings.rs: -------------------------------------------------------------------------------- 1 | use crate::SETTINGS; 2 | use config::{Config, ConfigError, Environment, File}; 3 | use serde::Deserialize; 4 | #[cfg(unix)] 5 | use std::os::unix::ffi::OsStrExt; 6 | #[cfg(windows)] 7 | use std::os::windows::ffi::OsStrExt; 8 | use std::{ 9 | env, 10 | ffi::OsString, 11 | fs, 12 | path::{Path, PathBuf}, 13 | }; 14 | 15 | #[derive(Debug, Deserialize, Clone)] 16 | pub struct Settings { 17 | pub mostro_pubkey: String, 18 | pub relays: Vec, 19 | } 20 | 21 | #[cfg(windows)] 22 | fn has_trailing_slash(p: &Path) -> bool { 23 | let last = p.as_os_str().encode_wide().last(); 24 | last == Some(b'\\' as u16) || last == Some(b'/' as u16) 25 | } 26 | #[cfg(unix)] 27 | fn has_trailing_slash(p: &Path) -> bool { 28 | p.as_os_str().as_bytes().last() == Some(&b'/') 29 | } 30 | 31 | fn add_trailing_slash(p: &mut PathBuf) { 32 | let fname = p.file_name(); 33 | let dirname = if let Some(fname) = fname { 34 | let mut s = OsString::with_capacity(fname.len() + 1); 35 | s.push(fname); 36 | if cfg!(windows) { 37 | s.push("\\"); 38 | } else { 39 | s.push("/"); 40 | } 41 | s 42 | } else { 43 | OsString::new() 44 | }; 45 | 46 | if p.pop() { 47 | p.push(dirname); 48 | } 49 | } 50 | impl Settings { 51 | pub fn new(mut config_path: PathBuf) -> Result { 52 | let file_name = { 53 | if !has_trailing_slash(config_path.as_path()) { 54 | add_trailing_slash(&mut config_path); 55 | let tmp = format!("{}settings.toml", config_path.display()); 56 | tmp 57 | } else { 58 | format!("{}settings.toml", config_path.display()) 59 | } 60 | }; 61 | if !Path::new(&file_name).exists() { 62 | println!("Settings file not found: {}", file_name); 63 | return Err(ConfigError::NotFound(file_name)); 64 | } 65 | println!("Loading settings from: {}", file_name); 66 | 67 | let s = Config::builder() 68 | .add_source(File::with_name(&file_name).required(true)) 69 | // Add in settings from the environment (with a prefix of APP) 70 | // Eg.. `APP_DEBUG=1 ./target/app` would set the `debug` key 71 | .add_source(Environment::with_prefix("app")) 72 | .build()?; 73 | 74 | // You can deserialize the entire configuration as 75 | s.try_deserialize() 76 | } 77 | 78 | pub fn get() -> Self { 79 | SETTINGS.get().unwrap().clone() 80 | } 81 | } 82 | 83 | pub fn init_global_settings(settings: Settings) { 84 | SETTINGS.set(settings).unwrap() 85 | } 86 | 87 | pub fn get_settings_path() -> String { 88 | let home_dir = env::var("HOME").expect("Couldn't get HOME directory"); 89 | let settings_path = format!("{}/.mostrui", home_dir); 90 | if !Path::new(&settings_path).exists() { 91 | fs::create_dir(&settings_path).expect("Couldn't create mostrui directory"); 92 | println!("Directory {} created.", settings_path); 93 | } 94 | 95 | settings_path 96 | } 97 | -------------------------------------------------------------------------------- /src/nip59.rs: -------------------------------------------------------------------------------- 1 | use base64::engine::{general_purpose, Engine}; 2 | use nip44::v2::{decrypt_to_bytes, encrypt_to_bytes, ConversationKey}; 3 | use nostr_sdk::event::builder::Error as BuilderError; 4 | use nostr_sdk::prelude::*; 5 | 6 | /// Creates a new nip59 event 7 | /// 8 | /// # Arguments 9 | /// 10 | /// * `sender_keys` - The keys of the sender 11 | /// * `receiver` - The public key of the receiver 12 | /// * `content` - The message 13 | /// * `expiration` - Time of the expiration of the event 14 | /// 15 | /// # Returns 16 | /// Returns a gift wrap event 17 | /// 18 | pub fn gift_wrap( 19 | sender_keys: &Keys, 20 | receiver: PublicKey, 21 | content: String, 22 | expiration: Option, 23 | pow: u8, 24 | ) -> Result { 25 | let rumor: UnsignedEvent = 26 | EventBuilder::text_note(content, []).to_unsigned_event(sender_keys.public_key()); 27 | let seal: Event = seal(sender_keys, &receiver, rumor)?.to_event(sender_keys)?; 28 | 29 | gift_wrap_from_seal(&receiver, &seal, expiration, pow) 30 | } 31 | 32 | pub fn seal( 33 | sender_keys: &Keys, 34 | receiver_pubkey: &PublicKey, 35 | rumor: UnsignedEvent, 36 | ) -> Result { 37 | let sender_private_key = sender_keys.secret_key(); 38 | 39 | // Derive conversation key 40 | let ck = ConversationKey::derive(sender_private_key, receiver_pubkey); 41 | // Encrypt content 42 | let encrypted_content = encrypt_to_bytes(&ck, rumor.as_json())?; 43 | // Encode with base64 44 | let b64decoded_content = general_purpose::STANDARD.encode(encrypted_content); 45 | // Compose builder 46 | Ok(EventBuilder::new(Kind::Seal, b64decoded_content, []) 47 | .custom_created_at(Timestamp::tweaked(nip59::RANGE_RANDOM_TIMESTAMP_TWEAK))) 48 | } 49 | 50 | pub fn gift_wrap_from_seal( 51 | receiver: &PublicKey, 52 | seal: &Event, 53 | expiration: Option, 54 | pow: u8, 55 | ) -> Result { 56 | let ephemeral_keys: Keys = Keys::generate(); 57 | // Derive conversation key 58 | let ck = ConversationKey::derive(ephemeral_keys.secret_key(), receiver); 59 | // Encrypt content 60 | let encrypted_content = encrypt_to_bytes(&ck, seal.as_json())?; 61 | 62 | let mut tags: Vec = Vec::with_capacity(1 + usize::from(expiration.is_some())); 63 | tags.push(Tag::public_key(*receiver)); 64 | 65 | if let Some(timestamp) = expiration { 66 | tags.push(Tag::expiration(timestamp)); 67 | } 68 | // Encode with base64 69 | let b64decoded_content = general_purpose::STANDARD.encode(encrypted_content); 70 | EventBuilder::new(Kind::GiftWrap, b64decoded_content, tags) 71 | .custom_created_at(Timestamp::tweaked(nip59::RANGE_RANDOM_TIMESTAMP_TWEAK)) 72 | .pow(pow) 73 | .to_event(&ephemeral_keys) 74 | } 75 | 76 | pub fn unwrap_gift_wrap( 77 | keys: Option<&Keys>, 78 | gw_ck: Option, 79 | seal_ck: Option, 80 | gift_wrap: &Event, 81 | ) -> Result { 82 | let gw_ck = match keys { 83 | Some(keys) => ConversationKey::derive(keys.secret_key(), &gift_wrap.pubkey), 84 | None => match gw_ck { 85 | Some(ck) => ck, 86 | None => { 87 | return Err(BuilderError::NIP44( 88 | nostr_sdk::nips::nip44::Error::NotFound( 89 | "No keys or conversation key".to_string(), 90 | ), 91 | )) 92 | } 93 | }, 94 | }; 95 | let b64decoded_content = match general_purpose::STANDARD.decode(gift_wrap.content.as_bytes()) { 96 | Ok(b64decoded_content) => b64decoded_content, 97 | Err(e) => { 98 | return Err(BuilderError::NIP44( 99 | nostr_sdk::nips::nip44::Error::NotFound(e.to_string()), 100 | )); 101 | } 102 | }; 103 | // Decrypt and verify seal 104 | let seal = decrypt_to_bytes(&gw_ck, b64decoded_content)?; 105 | let seal = String::from_utf8(seal).expect("Found invalid UTF-8"); 106 | let seal = match Event::from_json(seal) { 107 | Ok(seal) => seal, 108 | Err(e) => { 109 | println!("Error: {:#?}", e); 110 | return Err(BuilderError::NIP44( 111 | nostr_sdk::nips::nip44::Error::NotFound(e.to_string()), 112 | )); 113 | } 114 | }; 115 | let seal_ck = match keys { 116 | Some(keys) => ConversationKey::derive(keys.secret_key(), &seal.pubkey), 117 | None => match seal_ck { 118 | Some(ck) => ck, 119 | None => { 120 | return Err(BuilderError::NIP44( 121 | nostr_sdk::nips::nip44::Error::NotFound( 122 | "No keys or conversation key".to_string(), 123 | ), 124 | )) 125 | } 126 | }, 127 | }; 128 | let b64decoded_content = match general_purpose::STANDARD.decode(seal.content.as_bytes()) { 129 | Ok(b64decoded_content) => b64decoded_content, 130 | Err(e) => { 131 | return Err(BuilderError::NIP44( 132 | nostr_sdk::nips::nip44::Error::NotFound(e.to_string()), 133 | )) 134 | } 135 | }; 136 | // Decrypt rumor 137 | let rumor = decrypt_to_bytes(&seal_ck, b64decoded_content)?; 138 | let rumor = String::from_utf8(rumor).expect("Found invalid UTF-8"); 139 | 140 | Ok(UnwrappedGift { 141 | sender: seal.pubkey, 142 | rumor: UnsignedEvent::from_json(rumor)?, 143 | }) 144 | } 145 | -------------------------------------------------------------------------------- /src/db.rs: -------------------------------------------------------------------------------- 1 | use crate::settings::get_settings_path; 2 | use sqlx::pool::Pool; 3 | use sqlx::Sqlite; 4 | use sqlx::SqlitePool; 5 | use std::fs::File; 6 | use std::path::Path; 7 | 8 | pub async fn connect() -> Result, sqlx::Error> { 9 | let mostrui_dir = get_settings_path(); 10 | let mostrui_db_path = format!("{}/mostrui.db", mostrui_dir); 11 | 12 | if !Path::exists(Path::new(&mostrui_db_path)) { 13 | if let Err(res) = File::create(&mostrui_db_path) { 14 | println!("Error in creating db file: {}", res) 15 | } 16 | } 17 | 18 | let db_url = format!("sqlite://{}", mostrui_db_path); 19 | let pool = SqlitePool::connect(&db_url).await?; 20 | 21 | // We create the database file with orders table if the file doesn't exists 22 | if !Path::new(&mostrui_db_path).exists() { 23 | sqlx::query( 24 | r#" 25 | CREATE TABLE IF NOT EXISTS orders ( 26 | id TEXT PRIMARY KEY, 27 | kind TEXT, 28 | status TEXT, 29 | amount INTEGER NOT NULL, 30 | fiat_code TEXT NOT NULL, 31 | min_amount INTEGER, 32 | max_amount INTEGER, 33 | fiat_amount INTEGER NOT NULL, 34 | payment_method TEXT NOT NULL, 35 | premium INTEGER NOT NULL, 36 | master_buyer_pubkey TEXT, 37 | master_seller_pubkey TEXT, 38 | buyer_invoice TEXT, 39 | created_at INTEGER, 40 | expires_at INTEGER, 41 | buyer_token INTEGER, 42 | seller_token INTEGER 43 | ); 44 | "#, 45 | ) 46 | .execute(&pool) 47 | .await?; 48 | } 49 | 50 | Ok(pool) 51 | } 52 | 53 | #[derive(Debug, Default, Clone)] 54 | pub struct Order { 55 | pub id: Option, 56 | pub kind: Option, 57 | pub status: Option, 58 | pub amount: i64, 59 | pub fiat_code: String, 60 | pub min_amount: Option, 61 | pub max_amount: Option, 62 | pub fiat_amount: i64, 63 | pub payment_method: String, 64 | pub premium: i64, 65 | pub master_buyer_pubkey: Option, 66 | pub master_seller_pubkey: Option, 67 | pub buyer_invoice: Option, 68 | pub created_at: Option, 69 | pub expires_at: Option, 70 | pub buyer_token: Option, 71 | pub seller_token: Option, 72 | } 73 | 74 | impl Order { 75 | // Setters encadenables 76 | pub fn set_kind(&mut self, kind: String) -> &mut Self { 77 | self.kind = Some(kind); 78 | self 79 | } 80 | 81 | pub fn set_status(&mut self, status: String) -> &mut Self { 82 | self.status = Some(status); 83 | self 84 | } 85 | 86 | pub fn set_amount(&mut self, amount: i64) -> &mut Self { 87 | self.amount = amount; 88 | self 89 | } 90 | 91 | pub fn set_fiat_code(&mut self, fiat_code: String) -> &mut Self { 92 | self.fiat_code = fiat_code; 93 | self 94 | } 95 | 96 | pub fn set_min_amount(&mut self, min_amount: i64) -> &mut Self { 97 | self.min_amount = Some(min_amount); 98 | self 99 | } 100 | 101 | pub fn set_max_amount(&mut self, max_amount: i64) -> &mut Self { 102 | self.max_amount = Some(max_amount); 103 | self 104 | } 105 | 106 | pub fn set_fiat_amount(&mut self, fiat_amount: i64) -> &mut Self { 107 | self.fiat_amount = fiat_amount; 108 | self 109 | } 110 | 111 | pub fn set_payment_method(&mut self, payment_method: String) -> &mut Self { 112 | self.payment_method = payment_method; 113 | self 114 | } 115 | 116 | pub fn set_premium(&mut self, premium: i64) -> &mut Self { 117 | self.premium = premium; 118 | self 119 | } 120 | 121 | // Applying changes to the database 122 | pub async fn save(&self, pool: &SqlitePool) -> Result<(), Box> { 123 | // Validation if an identity document is present 124 | if let Some(ref id) = self.id { 125 | sqlx::query( 126 | r#" 127 | UPDATE orders 128 | SET kind = ?, status = ?, amount = ?, fiat_code = ?, min_amount = ?, max_amount = ?, 129 | fiat_amount = ?, payment_method = ?, premium = ?, master_buyer_pubkey = ?, 130 | master_seller_pubkey = ?, buyer_invoice = ?, created_at = ?, expires_at = ?, 131 | buyer_token = ?, seller_token = ? 132 | WHERE id = ? 133 | "#, 134 | ) 135 | .bind(&self.kind) 136 | .bind(&self.status) 137 | .bind(self.amount) 138 | .bind(&self.fiat_code) 139 | .bind(self.min_amount) 140 | .bind(self.max_amount) 141 | .bind(self.fiat_amount) 142 | .bind(&self.payment_method) 143 | .bind(self.premium) 144 | .bind(&self.master_buyer_pubkey) 145 | .bind(&self.master_seller_pubkey) 146 | .bind(&self.buyer_invoice) 147 | .bind(self.created_at) 148 | .bind(self.expires_at) 149 | .bind(self.buyer_token) 150 | .bind(self.seller_token) 151 | .bind(id) 152 | .execute(pool) 153 | .await?; 154 | 155 | println!("Order with id {} updated in the database.", id); 156 | } else { 157 | println!("Order must have an ID to be updated."); 158 | } 159 | 160 | Ok(()) 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | pub mod db; 2 | pub mod nip59; 3 | pub mod settings; 4 | pub mod util; 5 | 6 | use crate::db::connect; 7 | use crate::nip59::{gift_wrap, unwrap_gift_wrap}; 8 | use crate::settings::{get_settings_path, init_global_settings, Settings}; 9 | use crate::util::order_from_tags; 10 | use chrono::{DateTime, Local, TimeZone}; 11 | use mostro_core::message::{Action, Content, Message}; 12 | use mostro_core::order::{Kind as OrderKind, SmallOrder as Order, Status}; 13 | use mostro_core::NOSTR_REPLACEABLE_EVENT_KIND; 14 | use nostr_sdk::prelude::*; 15 | use nostr_sdk::Kind::ParameterizedReplaceable; 16 | use ratatui::layout::Flex; 17 | use ratatui::style::Color; 18 | use ratatui::widgets::{Clear, Paragraph, Wrap}; 19 | use ratatui::{ 20 | buffer::Buffer, 21 | crossterm::event::{Event, EventStream, KeyCode, KeyEventKind}, 22 | layout::{Constraint, Layout, Rect}, 23 | style::palette::tailwind::{BLUE, SLATE}, 24 | style::{Style, Stylize}, 25 | text::Line, 26 | widgets::{ 27 | Block, Cell, HighlightSpacing, Row, StatefulWidget, Table, TableState, Tabs, Widget, 28 | }, 29 | DefaultTerminal, Frame, 30 | }; 31 | use std::cmp::Ordering; 32 | use std::path::PathBuf; 33 | use std::str::FromStr; 34 | use std::sync::OnceLock; 35 | use std::{ 36 | sync::{Arc, RwLock}, 37 | time::Duration, 38 | }; 39 | use tui_input::backend::crossterm::EventHandler; 40 | use tui_input::Input; 41 | mod widgets; 42 | use widgets::settings_widget::SettingsWidget; 43 | 44 | static SETTINGS: OnceLock = OnceLock::new(); 45 | 46 | // TODO: generate keys for each order (maker or taker) 47 | // pubkey 000001273664dafe71d01c4541b726864bc430471f106eb48afc988ef6443a15 48 | const MY_PRIVATE_KEY: &str = "e02e5a36e3439b2df5172976bb58398ab2507306471c903c3820e1bcd57cd10b"; 49 | 50 | #[tokio::main] 51 | async fn main() -> Result<()> { 52 | let settings_path = get_settings_path(); 53 | let settings_file_path = PathBuf::from(settings_path); 54 | 55 | // Create config global var 56 | init_global_settings(Settings::new(settings_file_path)?); 57 | let terminal = ratatui::init(); 58 | let author = PublicKey::from_str(Settings::get().mostro_pubkey.as_str())?; 59 | let app = App::new(author); 60 | let _db = connect().await?; 61 | 62 | let client = Client::new(&app.my_keys); 63 | let relays = Settings::get().relays.clone(); 64 | for relay in relays { 65 | client.add_relay(relay).await?; 66 | } 67 | client.connect().await; 68 | 69 | let since = chrono::Utc::now() - chrono::Duration::days(1); 70 | let timestamp = since.timestamp(); 71 | let since = Timestamp::from_secs(timestamp as u64); 72 | // Here subscribe to get orders 73 | let orders_sub_id = SubscriptionId::new("orders-sub-id"); 74 | let filter = Filter::new() 75 | .author(author) 76 | .kind(ParameterizedReplaceable(NOSTR_REPLACEABLE_EVENT_KIND)) 77 | .custom_tag(SingleLetterTag::lowercase(Alphabet::Y), vec!["mostro"]) 78 | .custom_tag(SingleLetterTag::lowercase(Alphabet::Z), vec!["order"]) 79 | .since(since); 80 | client 81 | .subscribe_with_id(orders_sub_id, vec![filter], None) 82 | .await?; 83 | 84 | // Here subscribe to get messages 85 | let messages_sub_id = SubscriptionId::new("messages-sub-id"); 86 | let filter = Filter::new() 87 | .pubkey(app.my_keys.public_key()) 88 | .kinds([Kind::GiftWrap, Kind::PrivateDirectMessage]) 89 | .since(since); 90 | client 91 | .subscribe_with_id(messages_sub_id, vec![filter], None) 92 | .await?; 93 | let app_result = app.run(terminal, client).await; 94 | ratatui::restore(); 95 | 96 | app_result 97 | } 98 | 99 | #[derive(Debug)] 100 | struct App { 101 | my_keys: Keys, 102 | mostro_pubkey: PublicKey, 103 | should_quit: bool, 104 | show_order: bool, 105 | selected_tab: usize, 106 | orders: OrderListWidget, 107 | messages: MostroListWidget, 108 | show_amount_input: bool, 109 | show_invoice_input: bool, 110 | amount_input: Input, 111 | } 112 | 113 | impl App { 114 | const FRAMES_PER_SECOND: f32 = 60.0; 115 | 116 | pub fn new(mostro_pubkey: PublicKey) -> Self { 117 | let amount_input = Input::default(); 118 | 119 | Self { 120 | my_keys: Keys::parse(MY_PRIVATE_KEY).unwrap(), 121 | mostro_pubkey, 122 | should_quit: false, 123 | show_order: false, 124 | selected_tab: 0, 125 | orders: OrderListWidget::default(), 126 | messages: MostroListWidget::default(), 127 | show_amount_input: false, 128 | show_invoice_input: false, 129 | amount_input, 130 | } 131 | } 132 | 133 | // TODO: Implement https://mostro.network/protocol/key_management.html 134 | //pub fn generate_new_keys(&mut self) { 135 | // self.my_keys = Keys::generate(); 136 | //} 137 | 138 | pub async fn run(mut self, mut terminal: DefaultTerminal, client: Client) -> Result<()> { 139 | self.orders.run(client.clone()); 140 | self.messages.run(client.clone(), self.my_keys.clone()); 141 | 142 | let period = Duration::from_secs_f32(1.0 / Self::FRAMES_PER_SECOND); 143 | let mut interval = tokio::time::interval(period); 144 | let mut events = EventStream::new(); 145 | 146 | while !self.should_quit { 147 | tokio::select! { 148 | _ = interval.tick() => { terminal.draw(|frame| self.draw(frame))?; }, 149 | Some(Ok(event)) = events.next() => self.handle_event(&event, client.clone()).await, 150 | } 151 | } 152 | Ok(()) 153 | } 154 | 155 | fn draw(&mut self, frame: &mut Frame) { 156 | let vertical = Layout::vertical([Constraint::Length(3), Constraint::Fill(1)]); 157 | let [tabs_area, body_area] = vertical.areas(frame.area()); 158 | 159 | // Defining tabs labels 160 | let tab_titles = ["Orders", "My Trades", "Messages", "Settings"] 161 | .iter() 162 | .map(|t| Line::from(*t).bold()) 163 | .collect::>(); 164 | let color = Color::from_str("#304F00").unwrap(); 165 | 166 | let tabs = Tabs::new(tab_titles) 167 | .block(Block::bordered().title(" Mostro ")) 168 | .bg(color) 169 | .select(self.selected_tab) 170 | .highlight_style(Style::new().fg(BLUE.c400)); 171 | 172 | frame.render_widget(tabs, tabs_area); 173 | 174 | match self.selected_tab { 175 | 0 => self.render_orders_tab(frame, body_area), 176 | 1 => self.render_text_tab(frame, body_area, "My Trades"), 177 | 2 => self.render_messages_tab(frame, body_area), 178 | 3 => self.render_settings_tab(frame, body_area), 179 | _ => {} 180 | } 181 | 182 | if self.show_invoice_input { 183 | let popup_area = popup_area(frame.area(), 50, 20); 184 | let block = Block::bordered().title("Invoice input").bg(Color::Black); 185 | let lines = vec![ 186 | Line::raw("🧌 You took this selling order, please use a fiat payment processor that allows you to send the money immediately and in which there is no risk of freezing funds."), 187 | Line::raw("If, for any reason, your payment processor puts the payment on pause and the funds do not arrive in less than 22 hours, the sats will return to the seller, putting the buyer at risk and I cannot force the seller to send the sats again."), 188 | Line::raw("If you agree with the above, enter a lightning invoice."), 189 | ]; 190 | let paragraph = Paragraph::new(lines).block(block).wrap(Wrap { trim: true }); 191 | let input_paragraph = Paragraph::new(vec![Line::from(self.amount_input.value())]) 192 | .block(Block::default().borders(ratatui::widgets::Borders::ALL)) 193 | .wrap(Wrap { trim: true }); 194 | frame.render_widget(Clear, popup_area); 195 | frame.render_widget(paragraph, popup_area); 196 | 197 | // Render input 198 | frame.render_widget( 199 | input_paragraph, 200 | Rect::new(popup_area.x, popup_area.y + 4, popup_area.width, 3), 201 | ); 202 | } 203 | 204 | if self.show_amount_input { 205 | let popup_area = popup_area(frame.area(), 55, 25); 206 | let color: Color = Color::from_str("#14161C").unwrap(); 207 | let block = Block::bordered() 208 | .title("Amount input".to_string()) 209 | .bg(color) 210 | .title_style(Style::new().fg(Color::White)) 211 | .title_bottom(format!("ESC to close, ENTER to send fiat amount")); 212 | let selected = self.orders.state.read().unwrap().table_state.selected(); 213 | let state = self.orders.state.read().unwrap(); 214 | let order = match selected { 215 | Some(i) => state.orders.get(i).unwrap(), 216 | None => return, 217 | }; 218 | let lines = vec![ 219 | Line::raw("This is a range order."), 220 | Line::raw(format!( 221 | "Please enter an amount between {} {}.", 222 | order.fiat_amount(), 223 | order.fiat_code 224 | )), 225 | ]; 226 | 227 | let paragraph = Paragraph::new(lines) 228 | .block(block) 229 | .cyan() 230 | .wrap(Wrap { trim: true }); 231 | let input_paragraph = Paragraph::new(vec![Line::from(self.amount_input.value())]) 232 | .block(Block::default().borders(ratatui::widgets::Borders::ALL)) 233 | .wrap(Wrap { trim: true }); 234 | frame.render_widget(Clear, popup_area); 235 | frame.render_widget(paragraph, popup_area); 236 | 237 | // Render input 238 | frame.render_widget( 239 | input_paragraph, 240 | Rect::new(popup_area.x, popup_area.y + 5, popup_area.width, 3), 241 | ); 242 | } 243 | 244 | if self.show_order { 245 | let popup_area = popup_area(frame.area(), 50, 60); 246 | let selected = self.orders.state.read().unwrap().table_state.selected(); 247 | let state = self.orders.state.read().unwrap(); 248 | let order = match selected { 249 | Some(i) => state.orders.get(i).unwrap(), 250 | None => return, 251 | }; 252 | let action = match order.kind { 253 | Some(OrderKind::Buy) => "Sell", 254 | Some(OrderKind::Sell) => "Buy", 255 | _ => "Trade", 256 | }; 257 | let order_type = match order.kind { 258 | Some(OrderKind::Buy) => "Buying", 259 | Some(OrderKind::Sell) => "Selling", 260 | _ => "Trading", 261 | }; 262 | let color: Color = Color::from_str("#14161C").unwrap(); 263 | let block = Block::bordered() 264 | .title("Order details".to_string()) 265 | .bg(color) 266 | .title_style(Style::new().fg(Color::White)) 267 | .title_bottom(format!("ESC to close, ENTER to {}", action)); 268 | let sats_amount = order.sats_amount(); 269 | let premium = match order.premium.cmp(&0) { 270 | Ordering::Equal => "No premium or discount".to_string(), 271 | Ordering::Less => format!("a {}% discount", order.premium), 272 | Ordering::Greater => format!("a {}% premium", order.premium), 273 | }; 274 | let fiat_amount = order.fiat_amount(); 275 | let created_at: DateTime = 276 | Local.timestamp_opt(order.created_at.unwrap(), 0).unwrap(); 277 | let lines = vec![ 278 | Line::raw(format!( 279 | "Someone is {} sats for {} {} at {} with {}.", 280 | order_type, fiat_amount, order.fiat_code, sats_amount, premium 281 | )), 282 | Line::raw(""), 283 | Line::raw(format!("The payment method is {}.", order.payment_method)), 284 | Line::raw(""), 285 | Line::raw(format!("Id: {}", order.id.unwrap())), 286 | Line::raw(""), 287 | Line::raw(format!("Created at: {}", created_at)), 288 | ]; 289 | let paragraph = Paragraph::new(lines) 290 | .block(block) 291 | .cyan() 292 | .wrap(Wrap { trim: true }); 293 | 294 | frame.render_widget(Clear, popup_area); 295 | frame.render_widget(paragraph, popup_area); 296 | } 297 | } 298 | 299 | fn render_orders_tab(&self, frame: &mut Frame, area: Rect) { 300 | frame.render_widget(&self.orders, area); 301 | } 302 | 303 | fn render_messages_tab(&self, frame: &mut Frame, area: Rect) { 304 | frame.render_widget(&self.messages, area); 305 | } 306 | 307 | fn render_text_tab(&self, frame: &mut Frame, area: Rect, text: &str) { 308 | let text_line = Line::from(text).centered(); 309 | frame.render_widget(text_line, area); 310 | } 311 | 312 | fn render_settings_tab(&self, frame: &mut Frame, area: Rect) { 313 | let settings_widget = 314 | SettingsWidget::new(self.mostro_pubkey, self.my_keys.secret_key().clone()); 315 | frame.render_widget(settings_widget, area); 316 | } 317 | 318 | async fn take_order(&mut self, order: Order, action: Action, client: &Client) -> Result<()> { 319 | if self.show_amount_input { 320 | match self.amount_input.value().parse::() { 321 | Ok(value) => { 322 | if value >= order.min_amount.unwrap_or(10) 323 | && value <= order.max_amount.unwrap_or(500) 324 | { 325 | self.show_amount_input = false; 326 | self.show_order = false; 327 | 328 | // TODO: Implement https://mostro.network/protocol/key_management.html 329 | let order_id = match order.id { 330 | Some(id) => id, 331 | None => { 332 | println!("Order ID is missing"); 333 | return Err("Order ID is missing".into()); 334 | } 335 | }; 336 | let message = Message::new_order( 337 | None, 338 | Some(order_id), 339 | action, 340 | Some(Content::Amount(value)), 341 | ) 342 | .as_json() 343 | .map_err(|e| format!("Error serializing message to JSON: {}", e))?; 344 | 345 | println!( 346 | "Taking the order {} for {} {} with payment method {}", 347 | order.id.unwrap(), 348 | value, 349 | order.fiat_code, 350 | order.payment_method 351 | ); 352 | 353 | let event = gift_wrap(&self.my_keys, self.mostro_pubkey, message, None, 0) 354 | .map_err(|e| format!("Error creating event: {}", e))?; 355 | 356 | let msg = ClientMessage::event(event); 357 | client.send_msg_to(Settings::get().relays, msg).await?; 358 | } else { 359 | self.show_amount_input = false; 360 | println!("Value {} is out of the order range", value); 361 | } 362 | } 363 | Err(_) => { 364 | self.show_amount_input = false; 365 | println!("Invalid amount input. Please enter a valid number."); 366 | } 367 | } 368 | } else if self.show_order { 369 | if order.max_amount.is_some() { 370 | self.show_amount_input = true; 371 | self.show_order = false; 372 | } else { 373 | // TODO: Implement https://mostro.network/protocol/key_management.html 374 | let order_id = match order.id { 375 | Some(id) => id, 376 | None => { 377 | println!("Order ID is missing"); 378 | return Err("Order ID is missing".into()); 379 | } 380 | }; 381 | let message = Message::new_order(None, Some(order_id), action, None) 382 | .as_json() 383 | .map_err(|e| format!("Error serializing message to JSON: {}", e))?; 384 | 385 | println!( 386 | "Taking the order {} for {} {}, with payment method {}", 387 | order.id.unwrap(), 388 | order.fiat_amount, 389 | order.fiat_code, 390 | order.payment_method 391 | ); 392 | 393 | let event = gift_wrap(&self.my_keys, self.mostro_pubkey, message, None, 0) 394 | .map_err(|e| format!("Error creating event: {}", e))?; 395 | 396 | let msg = ClientMessage::event(event); 397 | client.send_msg_to(Settings::get().relays, msg).await?; 398 | self.show_order = false; 399 | } 400 | } else { 401 | self.show_order = true; 402 | } 403 | 404 | Ok(()) 405 | } 406 | 407 | async fn handle_event(&mut self, event: &Event, client: Client) { 408 | if let Event::Key(key) = event { 409 | if key.kind == KeyEventKind::Press { 410 | match key.code { 411 | KeyCode::Char('q') => self.should_quit = true, 412 | KeyCode::Char('j') | KeyCode::Down => { 413 | if self.selected_tab == 2 { 414 | self.messages.scroll_down(); 415 | } else { 416 | self.orders.scroll_down(); 417 | } 418 | } 419 | KeyCode::Char('k') | KeyCode::Up => { 420 | if self.selected_tab == 2 { 421 | self.messages.scroll_up(); 422 | } else { 423 | self.orders.scroll_up(); 424 | } 425 | } 426 | KeyCode::Left => { 427 | if self.selected_tab > 0 { 428 | self.selected_tab -= 1; 429 | } 430 | } 431 | KeyCode::Right => { 432 | if self.selected_tab < 3 { 433 | self.selected_tab += 1; 434 | self.show_order = false; 435 | self.show_amount_input = false; 436 | } 437 | } 438 | KeyCode::Enter => { 439 | if self.selected_tab == 0 440 | || self.show_order 441 | || self.show_amount_input 442 | || self.show_invoice_input 443 | { 444 | let order = { 445 | let state = self.orders.state.read().unwrap(); 446 | let selected = state.table_state.selected(); 447 | selected.and_then(|i| state.orders.get(i).cloned()) 448 | }; 449 | 450 | if let Some(order) = order { 451 | if let Some(kind) = order.kind { 452 | match kind { 453 | OrderKind::Sell => { 454 | if let Err(e) = self 455 | .take_order(order, Action::TakeSell, &client) 456 | .await 457 | { 458 | println!("Error handling order: {}", e); 459 | } 460 | } 461 | OrderKind::Buy => { 462 | if let Err(e) = self 463 | .take_order(order, Action::TakeBuy, &client) 464 | .await 465 | { 466 | println!("Error handling order: {}", e); 467 | } 468 | } 469 | } 470 | } 471 | } 472 | } 473 | } 474 | KeyCode::Esc => { 475 | self.show_order = false; 476 | self.show_amount_input = false; 477 | } 478 | _ => { 479 | if self.show_amount_input { 480 | self.amount_input.handle_event(&Event::Key(*key)); // Handle keyboard events in textarea 481 | } 482 | } 483 | } 484 | } 485 | } 486 | } 487 | } 488 | 489 | #[derive(Debug, Clone, Default)] 490 | struct MostroListWidget { 491 | state: Arc>, 492 | } 493 | 494 | #[derive(Debug, Default)] 495 | struct MostroListState { 496 | messages: Vec, 497 | loading_state: LoadingState, 498 | table_state: TableState, 499 | } 500 | 501 | #[derive(Debug)] 502 | struct DM { 503 | id: String, 504 | kind: Kind, 505 | sender: PublicKey, 506 | content: String, 507 | created_at: u64, 508 | } 509 | 510 | impl MostroListWidget { 511 | /// Start fetching the orders in the background. 512 | /// 513 | /// This method spawns a background task that fetches the orders from the Nostr relay. 514 | fn run(&self, client: Client, my_keys: Keys) { 515 | let this = self.clone(); 516 | tokio::spawn(this.fetch_dms(client, my_keys)); 517 | } 518 | 519 | async fn fetch_dms(self, client: Client, my_keys: Keys) { 520 | self.set_loading_state(LoadingState::Loading); 521 | 522 | client 523 | .handle_notifications(move |notification| { 524 | let this = self.clone(); 525 | let my_keys = my_keys.clone(); 526 | async move { 527 | if let RelayPoolNotification::Event { 528 | subscription_id, 529 | event, 530 | .. 531 | } = notification 532 | { 533 | if subscription_id == SubscriptionId::new("messages-sub-id") 534 | && event.kind == Kind::GiftWrap 535 | || event.kind == Kind::PrivateDirectMessage 536 | { 537 | this.handle_message_event(*event, my_keys)?; 538 | } 539 | } 540 | Ok(false) 541 | } 542 | }) 543 | .await 544 | .unwrap(); 545 | } 546 | 547 | fn set_loading_state(&self, state: LoadingState) { 548 | self.state.write().unwrap().loading_state = state; 549 | } 550 | 551 | fn scroll_down(&self) { 552 | self.state.write().unwrap().table_state.scroll_down_by(1); 553 | } 554 | 555 | fn scroll_up(&self) { 556 | self.state.write().unwrap().table_state.scroll_up_by(1); 557 | } 558 | 559 | fn handle_message_event(&self, event: nostr_sdk::Event, my_keys: Keys) -> Result<()> { 560 | match event.kind { 561 | Kind::GiftWrap => { 562 | let unwrapped_gift = match unwrap_gift_wrap(Some(&my_keys), None, None, &event) { 563 | Ok(u) => u, 564 | Err(_) => { 565 | return Err("Error unwrapping gift".into()); 566 | } 567 | }; 568 | let dm = DM { 569 | id: event.id.to_string(), 570 | kind: event.kind, 571 | sender: unwrapped_gift.sender, 572 | content: unwrapped_gift.rumor.content.clone(), 573 | created_at: unwrapped_gift.rumor.created_at.as_u64(), 574 | }; 575 | let mut state = self.state.write().unwrap(); 576 | state.messages.retain(|m| m.id != dm.id); 577 | 578 | state.messages.push(dm); 579 | state.loading_state = LoadingState::Loaded; 580 | 581 | if !state.messages.is_empty() { 582 | state.table_state.select(Some(0)); 583 | } 584 | // Handle possible messages from mostro 585 | let message = Message::from_json(&unwrapped_gift.rumor.content).unwrap(); 586 | match message.get_inner_message_kind().action { 587 | Action::AddInvoice => { 588 | // TODO: find a way of get a mutable reference to app 589 | // app.show_invoice_input = true; 590 | } 591 | Action::NewOrder => { 592 | todo!("New order created message"); 593 | } 594 | Action::CantDo => { 595 | println!("CantDo message"); 596 | } 597 | Action::Rate => { 598 | println!("Rate message"); 599 | } 600 | _ => {} 601 | } 602 | } 603 | Kind::PrivateDirectMessage => todo!("Handle PrivateDirectMessage"), 604 | _ => {} 605 | } 606 | 607 | Ok(()) 608 | } 609 | } 610 | 611 | impl Widget for &MostroListWidget { 612 | fn render(self, area: Rect, buf: &mut Buffer) { 613 | let mut state = self.state.write().unwrap(); 614 | 615 | // A block with a right-aligned title with the loading state on the right 616 | let loading_state = Line::from(format!("{:?}", state.loading_state)).right_aligned(); 617 | let color: Color = Color::from_str("#1D212C").unwrap(); 618 | let block = Block::bordered() 619 | .title(" DMs ") 620 | .title(loading_state) 621 | .bg(color) 622 | .title_bottom("j/k to scroll, ENTER to select order, q to quit"); 623 | // A table with the list of orders 624 | let rows = state.messages.iter().map(|dm| { 625 | let sender = if dm.sender 626 | == PublicKey::from_str(Settings::get().mostro_pubkey.as_str()).unwrap() 627 | { 628 | "Mostro".to_string() 629 | } else { 630 | dm.sender.to_string() 631 | }; 632 | let content = if dm.kind == Kind::GiftWrap { 633 | let message = Message::from_json(&dm.content).unwrap(); 634 | message.get_inner_message_kind().action.to_string() 635 | } else { 636 | dm.content.clone() 637 | }; 638 | let created_at = Local.timestamp_opt(dm.created_at as i64, 0).unwrap(); 639 | Row::new(vec![sender, content, created_at.to_string()]) 640 | }); 641 | let widths = [ 642 | Constraint::Fill(1), 643 | Constraint::Fill(1), 644 | Constraint::Fill(1), 645 | ]; 646 | let color = Color::from_str("#304F00").unwrap(); 647 | let header_style = Style::default().fg(SLATE.c200).bg(color); 648 | let selected_style = Style::default().fg(BLUE.c400); 649 | let header = ["Sender", "Content", "Created At"] 650 | .into_iter() 651 | .map(Cell::from) 652 | .collect::() 653 | .style(header_style) 654 | .height(1); 655 | let table = Table::new(rows, widths) 656 | .header(header) 657 | .block(block) 658 | .highlight_spacing(HighlightSpacing::Always) 659 | .highlight_symbol(">>") 660 | .row_highlight_style(selected_style); 661 | 662 | StatefulWidget::render(table, area, buf, &mut state.table_state); 663 | } 664 | } 665 | 666 | #[derive(Debug, Clone, Default)] 667 | struct OrderListWidget { 668 | state: Arc>, 669 | } 670 | 671 | #[derive(Debug, Default)] 672 | struct OrderListState { 673 | orders: Vec, 674 | loading_state: LoadingState, 675 | table_state: TableState, 676 | } 677 | 678 | #[derive(Debug, Clone, Default, PartialEq, Eq)] 679 | enum LoadingState { 680 | #[default] 681 | Idle, 682 | Loading, 683 | Loaded, 684 | } 685 | 686 | impl OrderListWidget { 687 | /// Start fetching the orders in the background. 688 | /// 689 | /// This method spawns a background task that fetches the orders from the Nostr relay. 690 | fn run(&self, client: Client) { 691 | let this = self.clone(); 692 | tokio::spawn(this.fetch_orders(client)); 693 | } 694 | 695 | async fn fetch_orders(self, client: Client) { 696 | self.set_loading_state(LoadingState::Loading); 697 | 698 | client 699 | .handle_notifications(move |notification| { 700 | let this = self.clone(); 701 | async move { 702 | if let RelayPoolNotification::Event { 703 | subscription_id, 704 | event, 705 | .. 706 | } = notification 707 | { 708 | if subscription_id == SubscriptionId::new("orders-sub-id") { 709 | this.handle_order_event(*event)?; 710 | } 711 | } 712 | Ok(false) 713 | } 714 | }) 715 | .await 716 | .unwrap(); 717 | } 718 | 719 | fn set_loading_state(&self, state: LoadingState) { 720 | self.state.write().unwrap().loading_state = state; 721 | } 722 | 723 | fn scroll_down(&self) { 724 | self.state.write().unwrap().table_state.scroll_down_by(1); 725 | } 726 | 727 | fn scroll_up(&self) { 728 | self.state.write().unwrap().table_state.scroll_up_by(1); 729 | } 730 | 731 | fn handle_order_event(&self, event: nostr_sdk::Event) -> Result<()> { 732 | let order = order_from_tags(event)?; 733 | let mut state = self.state.write().unwrap(); 734 | state.orders.retain(|o| o.id != order.id); 735 | 736 | if order.status == Some(Status::Pending) { 737 | state.orders.push(order); 738 | } 739 | 740 | state.loading_state = LoadingState::Loaded; 741 | if !state.orders.is_empty() { 742 | state.table_state.select(Some(0)); 743 | } 744 | 745 | Ok(()) 746 | } 747 | } 748 | 749 | impl Widget for &OrderListWidget { 750 | fn render(self, area: Rect, buf: &mut Buffer) { 751 | let mut state = self.state.write().unwrap(); 752 | 753 | // A block with a right-aligned title with the loading state on the right 754 | let loading_state = Line::from(format!("{:?}", state.loading_state)).right_aligned(); 755 | let color: Color = Color::from_str("#1D212C").unwrap(); 756 | let block = Block::bordered() 757 | .title(" Orders ") 758 | .title(loading_state) 759 | .bg(color) 760 | .title_bottom("j/k to scroll, ENTER to select order, q to quit"); 761 | 762 | // A table with the list of orders 763 | let rows = state.orders.iter().map(|order| { 764 | let amount = order.sats_amount(); 765 | let fiat_amount = order.fiat_amount(); 766 | Row::new(vec![ 767 | order.kind.unwrap().to_string(), 768 | order.fiat_code.clone(), 769 | amount, 770 | fiat_amount, 771 | order.payment_method.clone(), 772 | order.premium.to_string(), 773 | ]) 774 | }); 775 | let widths = [ 776 | Constraint::Length(4), 777 | Constraint::Length(4), 778 | Constraint::Length(12), 779 | Constraint::Length(15), 780 | Constraint::Fill(1), 781 | Constraint::Length(3), 782 | ]; 783 | let color = Color::from_str("#304F00").unwrap(); 784 | let header_style = Style::default().fg(SLATE.c200).bg(color); 785 | let selected_style = Style::default().fg(BLUE.c400); 786 | let header = [ 787 | "Kind", 788 | "Code", 789 | "Amount", 790 | "Fiat Amount", 791 | "Payment Method", 792 | "+/-", 793 | ] 794 | .into_iter() 795 | .map(Cell::from) 796 | .collect::() 797 | .style(header_style) 798 | .height(1); 799 | let table = Table::new(rows, widths) 800 | .header(header) 801 | .block(block) 802 | .highlight_spacing(HighlightSpacing::Always) 803 | .highlight_symbol(">>") 804 | .row_highlight_style(selected_style); 805 | 806 | StatefulWidget::render(table, area, buf, &mut state.table_state); 807 | } 808 | } 809 | 810 | fn popup_area(area: Rect, percent_x: u16, percent_y: u16) -> Rect { 811 | let vertical = Layout::vertical([Constraint::Percentage(percent_y)]).flex(Flex::Center); 812 | let horizontal = Layout::horizontal([Constraint::Percentage(percent_x)]).flex(Flex::Center); 813 | let [area] = vertical.areas(area); 814 | let [area] = horizontal.areas(area); 815 | area 816 | } -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "aead" 22 | version = "0.5.2" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" 25 | dependencies = [ 26 | "crypto-common", 27 | "generic-array", 28 | ] 29 | 30 | [[package]] 31 | name = "aes" 32 | version = "0.8.4" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" 35 | dependencies = [ 36 | "cfg-if", 37 | "cipher", 38 | "cpufeatures", 39 | ] 40 | 41 | [[package]] 42 | name = "ahash" 43 | version = "0.8.11" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 46 | dependencies = [ 47 | "cfg-if", 48 | "once_cell", 49 | "version_check", 50 | "zerocopy", 51 | ] 52 | 53 | [[package]] 54 | name = "allocator-api2" 55 | version = "0.2.18" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" 58 | 59 | [[package]] 60 | name = "android-tzdata" 61 | version = "0.1.1" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 64 | 65 | [[package]] 66 | name = "android_system_properties" 67 | version = "0.1.5" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 70 | dependencies = [ 71 | "libc", 72 | ] 73 | 74 | [[package]] 75 | name = "anyhow" 76 | version = "1.0.89" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" 79 | 80 | [[package]] 81 | name = "arrayvec" 82 | version = "0.7.6" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 85 | 86 | [[package]] 87 | name = "async-trait" 88 | version = "0.1.83" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" 91 | dependencies = [ 92 | "proc-macro2", 93 | "quote", 94 | "syn", 95 | ] 96 | 97 | [[package]] 98 | name = "async-utility" 99 | version = "0.2.0" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "a349201d80b4aa18d17a34a182bdd7f8ddf845e9e57d2ea130a12e10ef1e3a47" 102 | dependencies = [ 103 | "futures-util", 104 | "gloo-timers", 105 | "tokio", 106 | "wasm-bindgen-futures", 107 | ] 108 | 109 | [[package]] 110 | name = "async-wsocket" 111 | version = "0.9.0" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "5c0984bead67f20366bc8dd46018dfbe189b67eeefb0e5b86b9eade18d7c3c3b" 114 | dependencies = [ 115 | "async-utility", 116 | "futures", 117 | "futures-util", 118 | "js-sys", 119 | "thiserror", 120 | "tokio", 121 | "tokio-rustls", 122 | "tokio-socks", 123 | "tokio-tungstenite", 124 | "url", 125 | "wasm-bindgen", 126 | "web-sys", 127 | ] 128 | 129 | [[package]] 130 | name = "async-wsocket" 131 | version = "0.10.0" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "a107e3bdbe61e8e1e1341c57241b4b2d50501127b44bd2eff13b4635ab42d35a" 134 | dependencies = [ 135 | "async-utility", 136 | "futures", 137 | "futures-util", 138 | "js-sys", 139 | "thiserror", 140 | "tokio", 141 | "tokio-rustls", 142 | "tokio-socks", 143 | "tokio-tungstenite", 144 | "url", 145 | "wasm-bindgen", 146 | "web-sys", 147 | ] 148 | 149 | [[package]] 150 | name = "atoi" 151 | version = "2.0.0" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" 154 | dependencies = [ 155 | "num-traits", 156 | ] 157 | 158 | [[package]] 159 | name = "atomic-destructor" 160 | version = "0.2.0" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "7d919cb60ba95c87ba42777e9e246c4e8d658057299b437b7512531ce0a09a23" 163 | dependencies = [ 164 | "tracing", 165 | ] 166 | 167 | [[package]] 168 | name = "autocfg" 169 | version = "1.4.0" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 172 | 173 | [[package]] 174 | name = "backtrace" 175 | version = "0.3.74" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 178 | dependencies = [ 179 | "addr2line", 180 | "cfg-if", 181 | "libc", 182 | "miniz_oxide", 183 | "object", 184 | "rustc-demangle", 185 | "windows-targets 0.52.6", 186 | ] 187 | 188 | [[package]] 189 | name = "base58ck" 190 | version = "0.1.0" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" 193 | dependencies = [ 194 | "bitcoin-internals", 195 | "bitcoin_hashes 0.14.0", 196 | ] 197 | 198 | [[package]] 199 | name = "base64" 200 | version = "0.21.7" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 203 | 204 | [[package]] 205 | name = "base64" 206 | version = "0.22.1" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 209 | 210 | [[package]] 211 | name = "base64ct" 212 | version = "1.6.0" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" 215 | 216 | [[package]] 217 | name = "bech32" 218 | version = "0.11.0" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" 221 | 222 | [[package]] 223 | name = "bip39" 224 | version = "2.0.0" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" 227 | dependencies = [ 228 | "bitcoin_hashes 0.11.0", 229 | "serde", 230 | "unicode-normalization", 231 | ] 232 | 233 | [[package]] 234 | name = "bitcoin" 235 | version = "0.32.2" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "ea507acc1cd80fc084ace38544bbcf7ced7c2aa65b653b102de0ce718df668f6" 238 | dependencies = [ 239 | "base58ck", 240 | "bech32", 241 | "bitcoin-internals", 242 | "bitcoin-io", 243 | "bitcoin-units", 244 | "bitcoin_hashes 0.14.0", 245 | "hex-conservative", 246 | "hex_lit", 247 | "secp256k1", 248 | "serde", 249 | ] 250 | 251 | [[package]] 252 | name = "bitcoin-internals" 253 | version = "0.3.0" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" 256 | dependencies = [ 257 | "serde", 258 | ] 259 | 260 | [[package]] 261 | name = "bitcoin-io" 262 | version = "0.1.2" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" 265 | 266 | [[package]] 267 | name = "bitcoin-units" 268 | version = "0.1.2" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" 271 | dependencies = [ 272 | "bitcoin-internals", 273 | "serde", 274 | ] 275 | 276 | [[package]] 277 | name = "bitcoin_hashes" 278 | version = "0.11.0" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" 281 | 282 | [[package]] 283 | name = "bitcoin_hashes" 284 | version = "0.14.0" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" 287 | dependencies = [ 288 | "bitcoin-io", 289 | "hex-conservative", 290 | "serde", 291 | ] 292 | 293 | [[package]] 294 | name = "bitflags" 295 | version = "2.6.0" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 298 | dependencies = [ 299 | "serde", 300 | ] 301 | 302 | [[package]] 303 | name = "block-buffer" 304 | version = "0.10.4" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 307 | dependencies = [ 308 | "generic-array", 309 | ] 310 | 311 | [[package]] 312 | name = "block-padding" 313 | version = "0.3.3" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" 316 | dependencies = [ 317 | "generic-array", 318 | ] 319 | 320 | [[package]] 321 | name = "bumpalo" 322 | version = "3.16.0" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 325 | 326 | [[package]] 327 | name = "byteorder" 328 | version = "1.5.0" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 331 | 332 | [[package]] 333 | name = "bytes" 334 | version = "1.7.2" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" 337 | 338 | [[package]] 339 | name = "cassowary" 340 | version = "0.3.0" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" 343 | 344 | [[package]] 345 | name = "castaway" 346 | version = "0.2.3" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" 349 | dependencies = [ 350 | "rustversion", 351 | ] 352 | 353 | [[package]] 354 | name = "cbc" 355 | version = "0.1.2" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" 358 | dependencies = [ 359 | "cipher", 360 | ] 361 | 362 | [[package]] 363 | name = "cc" 364 | version = "1.1.22" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" 367 | dependencies = [ 368 | "shlex", 369 | ] 370 | 371 | [[package]] 372 | name = "cfg-if" 373 | version = "1.0.0" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 376 | 377 | [[package]] 378 | name = "chacha20" 379 | version = "0.9.1" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" 382 | dependencies = [ 383 | "cfg-if", 384 | "cipher", 385 | "cpufeatures", 386 | ] 387 | 388 | [[package]] 389 | name = "chacha20poly1305" 390 | version = "0.10.1" 391 | source = "registry+https://github.com/rust-lang/crates.io-index" 392 | checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" 393 | dependencies = [ 394 | "aead", 395 | "chacha20", 396 | "cipher", 397 | "poly1305", 398 | "zeroize", 399 | ] 400 | 401 | [[package]] 402 | name = "chrono" 403 | version = "0.4.38" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" 406 | dependencies = [ 407 | "android-tzdata", 408 | "iana-time-zone", 409 | "js-sys", 410 | "num-traits", 411 | "wasm-bindgen", 412 | "windows-targets 0.52.6", 413 | ] 414 | 415 | [[package]] 416 | name = "cipher" 417 | version = "0.4.4" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" 420 | dependencies = [ 421 | "crypto-common", 422 | "inout", 423 | "zeroize", 424 | ] 425 | 426 | [[package]] 427 | name = "compact_str" 428 | version = "0.8.0" 429 | source = "registry+https://github.com/rust-lang/crates.io-index" 430 | checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644" 431 | dependencies = [ 432 | "castaway", 433 | "cfg-if", 434 | "itoa", 435 | "rustversion", 436 | "ryu", 437 | "static_assertions", 438 | ] 439 | 440 | [[package]] 441 | name = "concurrent-queue" 442 | version = "2.5.0" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" 445 | dependencies = [ 446 | "crossbeam-utils", 447 | ] 448 | 449 | [[package]] 450 | name = "config" 451 | version = "0.14.0" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "7328b20597b53c2454f0b1919720c25c7339051c02b72b7e05409e00b14132be" 454 | dependencies = [ 455 | "async-trait", 456 | "convert_case", 457 | "json5", 458 | "lazy_static", 459 | "nom", 460 | "pathdiff", 461 | "ron", 462 | "rust-ini", 463 | "serde", 464 | "serde_json", 465 | "toml", 466 | "yaml-rust", 467 | ] 468 | 469 | [[package]] 470 | name = "const-oid" 471 | version = "0.9.6" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" 474 | 475 | [[package]] 476 | name = "const-random" 477 | version = "0.1.18" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" 480 | dependencies = [ 481 | "const-random-macro", 482 | ] 483 | 484 | [[package]] 485 | name = "const-random-macro" 486 | version = "0.1.16" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 489 | dependencies = [ 490 | "getrandom", 491 | "once_cell", 492 | "tiny-keccak", 493 | ] 494 | 495 | [[package]] 496 | name = "convert_case" 497 | version = "0.6.0" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" 500 | dependencies = [ 501 | "unicode-segmentation", 502 | ] 503 | 504 | [[package]] 505 | name = "core-foundation" 506 | version = "0.9.4" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 509 | dependencies = [ 510 | "core-foundation-sys", 511 | "libc", 512 | ] 513 | 514 | [[package]] 515 | name = "core-foundation-sys" 516 | version = "0.8.7" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 519 | 520 | [[package]] 521 | name = "cpufeatures" 522 | version = "0.2.14" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" 525 | dependencies = [ 526 | "libc", 527 | ] 528 | 529 | [[package]] 530 | name = "crc" 531 | version = "3.2.1" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" 534 | dependencies = [ 535 | "crc-catalog", 536 | ] 537 | 538 | [[package]] 539 | name = "crc-catalog" 540 | version = "2.4.0" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" 543 | 544 | [[package]] 545 | name = "crossbeam-queue" 546 | version = "0.3.11" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" 549 | dependencies = [ 550 | "crossbeam-utils", 551 | ] 552 | 553 | [[package]] 554 | name = "crossbeam-utils" 555 | version = "0.8.20" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 558 | 559 | [[package]] 560 | name = "crossterm" 561 | version = "0.28.1" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" 564 | dependencies = [ 565 | "bitflags", 566 | "crossterm_winapi", 567 | "futures-core", 568 | "mio", 569 | "parking_lot", 570 | "rustix", 571 | "signal-hook", 572 | "signal-hook-mio", 573 | "winapi", 574 | ] 575 | 576 | [[package]] 577 | name = "crossterm_winapi" 578 | version = "0.9.1" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" 581 | dependencies = [ 582 | "winapi", 583 | ] 584 | 585 | [[package]] 586 | name = "crunchy" 587 | version = "0.2.2" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 590 | 591 | [[package]] 592 | name = "crypto-common" 593 | version = "0.1.6" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 596 | dependencies = [ 597 | "generic-array", 598 | "rand_core", 599 | "typenum", 600 | ] 601 | 602 | [[package]] 603 | name = "data-encoding" 604 | version = "2.6.0" 605 | source = "registry+https://github.com/rust-lang/crates.io-index" 606 | checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" 607 | 608 | [[package]] 609 | name = "der" 610 | version = "0.7.9" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" 613 | dependencies = [ 614 | "const-oid", 615 | "pem-rfc7468", 616 | "zeroize", 617 | ] 618 | 619 | [[package]] 620 | name = "digest" 621 | version = "0.10.7" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 624 | dependencies = [ 625 | "block-buffer", 626 | "const-oid", 627 | "crypto-common", 628 | "subtle", 629 | ] 630 | 631 | [[package]] 632 | name = "dlv-list" 633 | version = "0.5.2" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" 636 | dependencies = [ 637 | "const-random", 638 | ] 639 | 640 | [[package]] 641 | name = "dotenvy" 642 | version = "0.15.7" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" 645 | 646 | [[package]] 647 | name = "either" 648 | version = "1.13.0" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 651 | dependencies = [ 652 | "serde", 653 | ] 654 | 655 | [[package]] 656 | name = "equivalent" 657 | version = "1.0.1" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 660 | 661 | [[package]] 662 | name = "errno" 663 | version = "0.3.9" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 666 | dependencies = [ 667 | "libc", 668 | "windows-sys 0.52.0", 669 | ] 670 | 671 | [[package]] 672 | name = "etcetera" 673 | version = "0.8.0" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" 676 | dependencies = [ 677 | "cfg-if", 678 | "home", 679 | "windows-sys 0.48.0", 680 | ] 681 | 682 | [[package]] 683 | name = "event-listener" 684 | version = "5.3.1" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" 687 | dependencies = [ 688 | "concurrent-queue", 689 | "parking", 690 | "pin-project-lite", 691 | ] 692 | 693 | [[package]] 694 | name = "fastrand" 695 | version = "2.1.1" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" 698 | 699 | [[package]] 700 | name = "flume" 701 | version = "0.11.1" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" 704 | dependencies = [ 705 | "futures-core", 706 | "futures-sink", 707 | "spin", 708 | ] 709 | 710 | [[package]] 711 | name = "fnv" 712 | version = "1.0.7" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 715 | 716 | [[package]] 717 | name = "foreign-types" 718 | version = "0.3.2" 719 | source = "registry+https://github.com/rust-lang/crates.io-index" 720 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 721 | dependencies = [ 722 | "foreign-types-shared", 723 | ] 724 | 725 | [[package]] 726 | name = "foreign-types-shared" 727 | version = "0.1.1" 728 | source = "registry+https://github.com/rust-lang/crates.io-index" 729 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 730 | 731 | [[package]] 732 | name = "form_urlencoded" 733 | version = "1.2.1" 734 | source = "registry+https://github.com/rust-lang/crates.io-index" 735 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 736 | dependencies = [ 737 | "percent-encoding", 738 | ] 739 | 740 | [[package]] 741 | name = "futures" 742 | version = "0.3.30" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" 745 | dependencies = [ 746 | "futures-channel", 747 | "futures-core", 748 | "futures-io", 749 | "futures-sink", 750 | "futures-task", 751 | "futures-util", 752 | ] 753 | 754 | [[package]] 755 | name = "futures-channel" 756 | version = "0.3.30" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 759 | dependencies = [ 760 | "futures-core", 761 | "futures-sink", 762 | ] 763 | 764 | [[package]] 765 | name = "futures-core" 766 | version = "0.3.30" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 769 | 770 | [[package]] 771 | name = "futures-executor" 772 | version = "0.3.30" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" 775 | dependencies = [ 776 | "futures-core", 777 | "futures-task", 778 | "futures-util", 779 | ] 780 | 781 | [[package]] 782 | name = "futures-intrusive" 783 | version = "0.5.0" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" 786 | dependencies = [ 787 | "futures-core", 788 | "lock_api", 789 | "parking_lot", 790 | ] 791 | 792 | [[package]] 793 | name = "futures-io" 794 | version = "0.3.30" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 797 | 798 | [[package]] 799 | name = "futures-sink" 800 | version = "0.3.30" 801 | source = "registry+https://github.com/rust-lang/crates.io-index" 802 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 803 | 804 | [[package]] 805 | name = "futures-task" 806 | version = "0.3.30" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 809 | 810 | [[package]] 811 | name = "futures-util" 812 | version = "0.3.30" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 815 | dependencies = [ 816 | "futures-channel", 817 | "futures-core", 818 | "futures-io", 819 | "futures-sink", 820 | "futures-task", 821 | "memchr", 822 | "pin-project-lite", 823 | "pin-utils", 824 | "slab", 825 | ] 826 | 827 | [[package]] 828 | name = "generic-array" 829 | version = "0.14.7" 830 | source = "registry+https://github.com/rust-lang/crates.io-index" 831 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 832 | dependencies = [ 833 | "typenum", 834 | "version_check", 835 | ] 836 | 837 | [[package]] 838 | name = "getrandom" 839 | version = "0.2.15" 840 | source = "registry+https://github.com/rust-lang/crates.io-index" 841 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 842 | dependencies = [ 843 | "cfg-if", 844 | "js-sys", 845 | "libc", 846 | "wasi", 847 | "wasm-bindgen", 848 | ] 849 | 850 | [[package]] 851 | name = "gimli" 852 | version = "0.31.0" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" 855 | 856 | [[package]] 857 | name = "gloo-timers" 858 | version = "0.2.6" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" 861 | dependencies = [ 862 | "futures-channel", 863 | "futures-core", 864 | "js-sys", 865 | "wasm-bindgen", 866 | ] 867 | 868 | [[package]] 869 | name = "hashbrown" 870 | version = "0.13.2" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" 873 | 874 | [[package]] 875 | name = "hashbrown" 876 | version = "0.14.5" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 879 | dependencies = [ 880 | "ahash", 881 | "allocator-api2", 882 | ] 883 | 884 | [[package]] 885 | name = "hashlink" 886 | version = "0.9.1" 887 | source = "registry+https://github.com/rust-lang/crates.io-index" 888 | checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" 889 | dependencies = [ 890 | "hashbrown 0.14.5", 891 | ] 892 | 893 | [[package]] 894 | name = "heck" 895 | version = "0.5.0" 896 | source = "registry+https://github.com/rust-lang/crates.io-index" 897 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 898 | 899 | [[package]] 900 | name = "hermit-abi" 901 | version = "0.3.9" 902 | source = "registry+https://github.com/rust-lang/crates.io-index" 903 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 904 | 905 | [[package]] 906 | name = "hex" 907 | version = "0.4.3" 908 | source = "registry+https://github.com/rust-lang/crates.io-index" 909 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 910 | 911 | [[package]] 912 | name = "hex-conservative" 913 | version = "0.2.1" 914 | source = "registry+https://github.com/rust-lang/crates.io-index" 915 | checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" 916 | dependencies = [ 917 | "arrayvec", 918 | ] 919 | 920 | [[package]] 921 | name = "hex_lit" 922 | version = "0.1.1" 923 | source = "registry+https://github.com/rust-lang/crates.io-index" 924 | checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" 925 | 926 | [[package]] 927 | name = "hkdf" 928 | version = "0.12.4" 929 | source = "registry+https://github.com/rust-lang/crates.io-index" 930 | checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" 931 | dependencies = [ 932 | "hmac", 933 | ] 934 | 935 | [[package]] 936 | name = "hmac" 937 | version = "0.12.1" 938 | source = "registry+https://github.com/rust-lang/crates.io-index" 939 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 940 | dependencies = [ 941 | "digest", 942 | ] 943 | 944 | [[package]] 945 | name = "home" 946 | version = "0.5.9" 947 | source = "registry+https://github.com/rust-lang/crates.io-index" 948 | checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" 949 | dependencies = [ 950 | "windows-sys 0.52.0", 951 | ] 952 | 953 | [[package]] 954 | name = "http" 955 | version = "1.1.0" 956 | source = "registry+https://github.com/rust-lang/crates.io-index" 957 | checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" 958 | dependencies = [ 959 | "bytes", 960 | "fnv", 961 | "itoa", 962 | ] 963 | 964 | [[package]] 965 | name = "http-body" 966 | version = "1.0.1" 967 | source = "registry+https://github.com/rust-lang/crates.io-index" 968 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 969 | dependencies = [ 970 | "bytes", 971 | "http", 972 | ] 973 | 974 | [[package]] 975 | name = "http-body-util" 976 | version = "0.1.2" 977 | source = "registry+https://github.com/rust-lang/crates.io-index" 978 | checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" 979 | dependencies = [ 980 | "bytes", 981 | "futures-util", 982 | "http", 983 | "http-body", 984 | "pin-project-lite", 985 | ] 986 | 987 | [[package]] 988 | name = "httparse" 989 | version = "1.9.4" 990 | source = "registry+https://github.com/rust-lang/crates.io-index" 991 | checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" 992 | 993 | [[package]] 994 | name = "hyper" 995 | version = "1.4.1" 996 | source = "registry+https://github.com/rust-lang/crates.io-index" 997 | checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" 998 | dependencies = [ 999 | "bytes", 1000 | "futures-channel", 1001 | "futures-util", 1002 | "http", 1003 | "http-body", 1004 | "httparse", 1005 | "itoa", 1006 | "pin-project-lite", 1007 | "smallvec", 1008 | "tokio", 1009 | "want", 1010 | ] 1011 | 1012 | [[package]] 1013 | name = "hyper-rustls" 1014 | version = "0.27.3" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" 1017 | dependencies = [ 1018 | "futures-util", 1019 | "http", 1020 | "hyper", 1021 | "hyper-util", 1022 | "rustls", 1023 | "rustls-pki-types", 1024 | "tokio", 1025 | "tokio-rustls", 1026 | "tower-service", 1027 | "webpki-roots", 1028 | ] 1029 | 1030 | [[package]] 1031 | name = "hyper-util" 1032 | version = "0.1.9" 1033 | source = "registry+https://github.com/rust-lang/crates.io-index" 1034 | checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" 1035 | dependencies = [ 1036 | "bytes", 1037 | "futures-channel", 1038 | "futures-util", 1039 | "http", 1040 | "http-body", 1041 | "hyper", 1042 | "pin-project-lite", 1043 | "socket2", 1044 | "tokio", 1045 | "tower-service", 1046 | "tracing", 1047 | ] 1048 | 1049 | [[package]] 1050 | name = "iana-time-zone" 1051 | version = "0.1.61" 1052 | source = "registry+https://github.com/rust-lang/crates.io-index" 1053 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 1054 | dependencies = [ 1055 | "android_system_properties", 1056 | "core-foundation-sys", 1057 | "iana-time-zone-haiku", 1058 | "js-sys", 1059 | "wasm-bindgen", 1060 | "windows-core", 1061 | ] 1062 | 1063 | [[package]] 1064 | name = "iana-time-zone-haiku" 1065 | version = "0.1.2" 1066 | source = "registry+https://github.com/rust-lang/crates.io-index" 1067 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 1068 | dependencies = [ 1069 | "cc", 1070 | ] 1071 | 1072 | [[package]] 1073 | name = "idna" 1074 | version = "0.5.0" 1075 | source = "registry+https://github.com/rust-lang/crates.io-index" 1076 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" 1077 | dependencies = [ 1078 | "unicode-bidi", 1079 | "unicode-normalization", 1080 | ] 1081 | 1082 | [[package]] 1083 | name = "indexmap" 1084 | version = "2.5.0" 1085 | source = "registry+https://github.com/rust-lang/crates.io-index" 1086 | checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" 1087 | dependencies = [ 1088 | "equivalent", 1089 | "hashbrown 0.14.5", 1090 | ] 1091 | 1092 | [[package]] 1093 | name = "indoc" 1094 | version = "2.0.5" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" 1097 | 1098 | [[package]] 1099 | name = "inout" 1100 | version = "0.1.3" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" 1103 | dependencies = [ 1104 | "block-padding", 1105 | "generic-array", 1106 | ] 1107 | 1108 | [[package]] 1109 | name = "instability" 1110 | version = "0.3.2" 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" 1112 | checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" 1113 | dependencies = [ 1114 | "quote", 1115 | "syn", 1116 | ] 1117 | 1118 | [[package]] 1119 | name = "instant" 1120 | version = "0.1.13" 1121 | source = "registry+https://github.com/rust-lang/crates.io-index" 1122 | checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" 1123 | dependencies = [ 1124 | "cfg-if", 1125 | "js-sys", 1126 | "wasm-bindgen", 1127 | "web-sys", 1128 | ] 1129 | 1130 | [[package]] 1131 | name = "ipnet" 1132 | version = "2.10.0" 1133 | source = "registry+https://github.com/rust-lang/crates.io-index" 1134 | checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" 1135 | 1136 | [[package]] 1137 | name = "itertools" 1138 | version = "0.13.0" 1139 | source = "registry+https://github.com/rust-lang/crates.io-index" 1140 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 1141 | dependencies = [ 1142 | "either", 1143 | ] 1144 | 1145 | [[package]] 1146 | name = "itoa" 1147 | version = "1.0.11" 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" 1149 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 1150 | 1151 | [[package]] 1152 | name = "js-sys" 1153 | version = "0.3.70" 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" 1155 | checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" 1156 | dependencies = [ 1157 | "wasm-bindgen", 1158 | ] 1159 | 1160 | [[package]] 1161 | name = "json5" 1162 | version = "0.4.1" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" 1165 | dependencies = [ 1166 | "pest", 1167 | "pest_derive", 1168 | "serde", 1169 | ] 1170 | 1171 | [[package]] 1172 | name = "lazy_static" 1173 | version = "1.5.0" 1174 | source = "registry+https://github.com/rust-lang/crates.io-index" 1175 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1176 | dependencies = [ 1177 | "spin", 1178 | ] 1179 | 1180 | [[package]] 1181 | name = "libc" 1182 | version = "0.2.159" 1183 | source = "registry+https://github.com/rust-lang/crates.io-index" 1184 | checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" 1185 | 1186 | [[package]] 1187 | name = "libm" 1188 | version = "0.2.8" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" 1191 | 1192 | [[package]] 1193 | name = "libsqlite3-sys" 1194 | version = "0.30.1" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" 1197 | dependencies = [ 1198 | "cc", 1199 | "pkg-config", 1200 | "vcpkg", 1201 | ] 1202 | 1203 | [[package]] 1204 | name = "linked-hash-map" 1205 | version = "0.5.6" 1206 | source = "registry+https://github.com/rust-lang/crates.io-index" 1207 | checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" 1208 | 1209 | [[package]] 1210 | name = "linux-raw-sys" 1211 | version = "0.4.14" 1212 | source = "registry+https://github.com/rust-lang/crates.io-index" 1213 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 1214 | 1215 | [[package]] 1216 | name = "lnurl-pay" 1217 | version = "0.6.0" 1218 | source = "registry+https://github.com/rust-lang/crates.io-index" 1219 | checksum = "536e7c782167a2d48346ca0b2677fad19eaef20f19a4ab868e4d5b96ca879def" 1220 | dependencies = [ 1221 | "bech32", 1222 | "reqwest", 1223 | "serde", 1224 | "serde_json", 1225 | ] 1226 | 1227 | [[package]] 1228 | name = "lock_api" 1229 | version = "0.4.12" 1230 | source = "registry+https://github.com/rust-lang/crates.io-index" 1231 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 1232 | dependencies = [ 1233 | "autocfg", 1234 | "scopeguard", 1235 | ] 1236 | 1237 | [[package]] 1238 | name = "log" 1239 | version = "0.4.22" 1240 | source = "registry+https://github.com/rust-lang/crates.io-index" 1241 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 1242 | 1243 | [[package]] 1244 | name = "lru" 1245 | version = "0.12.4" 1246 | source = "registry+https://github.com/rust-lang/crates.io-index" 1247 | checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" 1248 | dependencies = [ 1249 | "hashbrown 0.14.5", 1250 | ] 1251 | 1252 | [[package]] 1253 | name = "md-5" 1254 | version = "0.10.6" 1255 | source = "registry+https://github.com/rust-lang/crates.io-index" 1256 | checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" 1257 | dependencies = [ 1258 | "cfg-if", 1259 | "digest", 1260 | ] 1261 | 1262 | [[package]] 1263 | name = "memchr" 1264 | version = "2.7.4" 1265 | source = "registry+https://github.com/rust-lang/crates.io-index" 1266 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1267 | 1268 | [[package]] 1269 | name = "mime" 1270 | version = "0.3.17" 1271 | source = "registry+https://github.com/rust-lang/crates.io-index" 1272 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1273 | 1274 | [[package]] 1275 | name = "minimal-lexical" 1276 | version = "0.2.1" 1277 | source = "registry+https://github.com/rust-lang/crates.io-index" 1278 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 1279 | 1280 | [[package]] 1281 | name = "miniz_oxide" 1282 | version = "0.8.0" 1283 | source = "registry+https://github.com/rust-lang/crates.io-index" 1284 | checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" 1285 | dependencies = [ 1286 | "adler2", 1287 | ] 1288 | 1289 | [[package]] 1290 | name = "mio" 1291 | version = "1.0.2" 1292 | source = "registry+https://github.com/rust-lang/crates.io-index" 1293 | checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" 1294 | dependencies = [ 1295 | "hermit-abi", 1296 | "libc", 1297 | "log", 1298 | "wasi", 1299 | "windows-sys 0.52.0", 1300 | ] 1301 | 1302 | [[package]] 1303 | name = "mostro-core" 1304 | version = "0.6.11" 1305 | source = "registry+https://github.com/rust-lang/crates.io-index" 1306 | checksum = "3416a4220576cecb437ff5f22df995d296e022ab85ed541c385ba7bfc97d14bc" 1307 | dependencies = [ 1308 | "anyhow", 1309 | "chrono", 1310 | "nostr-sdk 0.36.0", 1311 | "serde", 1312 | "serde_json", 1313 | "uuid", 1314 | "wasm-bindgen", 1315 | ] 1316 | 1317 | [[package]] 1318 | name = "mostrui" 1319 | version = "0.1.0" 1320 | dependencies = [ 1321 | "chrono", 1322 | "config", 1323 | "crossterm", 1324 | "mostro-core", 1325 | "nostr-sdk 0.35.0", 1326 | "ratatui 0.29.0", 1327 | "serde", 1328 | "sqlx", 1329 | "tokio", 1330 | "tui-input", 1331 | "uuid", 1332 | ] 1333 | 1334 | [[package]] 1335 | name = "native-tls" 1336 | version = "0.2.12" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" 1339 | dependencies = [ 1340 | "libc", 1341 | "log", 1342 | "openssl", 1343 | "openssl-probe", 1344 | "openssl-sys", 1345 | "schannel", 1346 | "security-framework", 1347 | "security-framework-sys", 1348 | "tempfile", 1349 | ] 1350 | 1351 | [[package]] 1352 | name = "negentropy" 1353 | version = "0.3.1" 1354 | source = "registry+https://github.com/rust-lang/crates.io-index" 1355 | checksum = "e664971378a3987224f7a0e10059782035e89899ae403718ee07de85bec42afe" 1356 | 1357 | [[package]] 1358 | name = "negentropy" 1359 | version = "0.4.3" 1360 | source = "registry+https://github.com/rust-lang/crates.io-index" 1361 | checksum = "43a88da9dd148bbcdce323dd6ac47d369b4769d4a3b78c6c52389b9269f77932" 1362 | 1363 | [[package]] 1364 | name = "nom" 1365 | version = "7.1.3" 1366 | source = "registry+https://github.com/rust-lang/crates.io-index" 1367 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 1368 | dependencies = [ 1369 | "memchr", 1370 | "minimal-lexical", 1371 | ] 1372 | 1373 | [[package]] 1374 | name = "nostr" 1375 | version = "0.35.0" 1376 | source = "registry+https://github.com/rust-lang/crates.io-index" 1377 | checksum = "56db234b2e07901e372f34e9463f91590579cd8e6dbd34ed2ccc7e461e4ba639" 1378 | dependencies = [ 1379 | "aes", 1380 | "base64 0.22.1", 1381 | "bech32", 1382 | "bip39", 1383 | "bitcoin", 1384 | "cbc", 1385 | "chacha20", 1386 | "chacha20poly1305", 1387 | "getrandom", 1388 | "instant", 1389 | "js-sys", 1390 | "negentropy 0.3.1", 1391 | "negentropy 0.4.3", 1392 | "once_cell", 1393 | "reqwest", 1394 | "scrypt", 1395 | "serde", 1396 | "serde_json", 1397 | "unicode-normalization", 1398 | "url", 1399 | "wasm-bindgen", 1400 | "wasm-bindgen-futures", 1401 | "web-sys", 1402 | ] 1403 | 1404 | [[package]] 1405 | name = "nostr" 1406 | version = "0.36.0" 1407 | source = "registry+https://github.com/rust-lang/crates.io-index" 1408 | checksum = "14ad56c1d9a59f4edc46b17bc64a217b38b99baefddc0080f85ad98a0855336d" 1409 | dependencies = [ 1410 | "aes", 1411 | "async-trait", 1412 | "base64 0.22.1", 1413 | "bech32", 1414 | "bip39", 1415 | "bitcoin", 1416 | "cbc", 1417 | "chacha20", 1418 | "chacha20poly1305", 1419 | "getrandom", 1420 | "instant", 1421 | "js-sys", 1422 | "negentropy 0.3.1", 1423 | "negentropy 0.4.3", 1424 | "once_cell", 1425 | "reqwest", 1426 | "scrypt", 1427 | "serde", 1428 | "serde_json", 1429 | "unicode-normalization", 1430 | "url", 1431 | "wasm-bindgen", 1432 | "wasm-bindgen-futures", 1433 | "web-sys", 1434 | ] 1435 | 1436 | [[package]] 1437 | name = "nostr-database" 1438 | version = "0.35.0" 1439 | source = "registry+https://github.com/rust-lang/crates.io-index" 1440 | checksum = "50de8cc5e77e7dafa7e2e0d0d67187ef19e191dcd1a68efffd3e05152d91b3c3" 1441 | dependencies = [ 1442 | "async-trait", 1443 | "lru", 1444 | "nostr 0.35.0", 1445 | "thiserror", 1446 | "tokio", 1447 | "tracing", 1448 | ] 1449 | 1450 | [[package]] 1451 | name = "nostr-database" 1452 | version = "0.36.0" 1453 | source = "registry+https://github.com/rust-lang/crates.io-index" 1454 | checksum = "1859abebf78d7d9e945b20c8faaf710c9db905adeb148035b803ae45792dbebe" 1455 | dependencies = [ 1456 | "async-trait", 1457 | "lru", 1458 | "nostr 0.36.0", 1459 | "thiserror", 1460 | "tokio", 1461 | "tracing", 1462 | ] 1463 | 1464 | [[package]] 1465 | name = "nostr-relay-pool" 1466 | version = "0.35.0" 1467 | source = "registry+https://github.com/rust-lang/crates.io-index" 1468 | checksum = "800b9ca169902977366f8243ec645b1fa4a128ab621331796d4a26bd7bc22a88" 1469 | dependencies = [ 1470 | "async-utility", 1471 | "async-wsocket 0.9.0", 1472 | "atomic-destructor", 1473 | "negentropy 0.3.1", 1474 | "negentropy 0.4.3", 1475 | "nostr 0.35.0", 1476 | "nostr-database 0.35.0", 1477 | "thiserror", 1478 | "tokio", 1479 | "tokio-stream", 1480 | "tracing", 1481 | ] 1482 | 1483 | [[package]] 1484 | name = "nostr-relay-pool" 1485 | version = "0.36.0" 1486 | source = "registry+https://github.com/rust-lang/crates.io-index" 1487 | checksum = "e39cfcb30cab86b30ca9acba89f5ccb25a4142a5dc5fcfbf3edf34b204ddd7c7" 1488 | dependencies = [ 1489 | "async-utility", 1490 | "async-wsocket 0.10.0", 1491 | "atomic-destructor", 1492 | "negentropy 0.3.1", 1493 | "negentropy 0.4.3", 1494 | "nostr 0.36.0", 1495 | "nostr-database 0.36.0", 1496 | "thiserror", 1497 | "tokio", 1498 | "tokio-stream", 1499 | "tracing", 1500 | ] 1501 | 1502 | [[package]] 1503 | name = "nostr-sdk" 1504 | version = "0.35.0" 1505 | source = "registry+https://github.com/rust-lang/crates.io-index" 1506 | checksum = "d93036bf4c1e35145ca2cd6ee4cb7bb9c74f41cbca9cc4caff1e87b5e192f253" 1507 | dependencies = [ 1508 | "async-utility", 1509 | "atomic-destructor", 1510 | "lnurl-pay", 1511 | "nostr 0.35.0", 1512 | "nostr-database 0.35.0", 1513 | "nostr-relay-pool 0.35.0", 1514 | "nostr-signer", 1515 | "nostr-zapper 0.35.0", 1516 | "nwc 0.35.0", 1517 | "thiserror", 1518 | "tokio", 1519 | "tracing", 1520 | ] 1521 | 1522 | [[package]] 1523 | name = "nostr-sdk" 1524 | version = "0.36.0" 1525 | source = "registry+https://github.com/rust-lang/crates.io-index" 1526 | checksum = "e4739ed15ff81a0e474d79b38c3eb481ff5f968c1865f38ba46852daf6f6495e" 1527 | dependencies = [ 1528 | "async-utility", 1529 | "atomic-destructor", 1530 | "lnurl-pay", 1531 | "nostr 0.36.0", 1532 | "nostr-database 0.36.0", 1533 | "nostr-relay-pool 0.36.0", 1534 | "nostr-zapper 0.36.0", 1535 | "nwc 0.36.0", 1536 | "thiserror", 1537 | "tokio", 1538 | "tracing", 1539 | ] 1540 | 1541 | [[package]] 1542 | name = "nostr-signer" 1543 | version = "0.35.0" 1544 | source = "registry+https://github.com/rust-lang/crates.io-index" 1545 | checksum = "c1e132975a677a1c97a7695ef1161291dc06517a588b6e17e3aa05d3fb4056a0" 1546 | dependencies = [ 1547 | "async-utility", 1548 | "nostr 0.35.0", 1549 | "nostr-relay-pool 0.35.0", 1550 | "thiserror", 1551 | "tokio", 1552 | "tracing", 1553 | ] 1554 | 1555 | [[package]] 1556 | name = "nostr-zapper" 1557 | version = "0.35.0" 1558 | source = "registry+https://github.com/rust-lang/crates.io-index" 1559 | checksum = "b60e7a3ecc9881ca418e772a6fc4410920653a9f0bf9457b6ddd732d2a3f64f1" 1560 | dependencies = [ 1561 | "async-trait", 1562 | "nostr 0.35.0", 1563 | "thiserror", 1564 | ] 1565 | 1566 | [[package]] 1567 | name = "nostr-zapper" 1568 | version = "0.36.0" 1569 | source = "registry+https://github.com/rust-lang/crates.io-index" 1570 | checksum = "9d9709ecf8050bbe4ecf0e5efda2f25b690bb1761fc504e05654621ba9e568a8" 1571 | dependencies = [ 1572 | "async-trait", 1573 | "nostr 0.36.0", 1574 | "thiserror", 1575 | ] 1576 | 1577 | [[package]] 1578 | name = "num-bigint-dig" 1579 | version = "0.8.4" 1580 | source = "registry+https://github.com/rust-lang/crates.io-index" 1581 | checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" 1582 | dependencies = [ 1583 | "byteorder", 1584 | "lazy_static", 1585 | "libm", 1586 | "num-integer", 1587 | "num-iter", 1588 | "num-traits", 1589 | "rand", 1590 | "smallvec", 1591 | "zeroize", 1592 | ] 1593 | 1594 | [[package]] 1595 | name = "num-integer" 1596 | version = "0.1.46" 1597 | source = "registry+https://github.com/rust-lang/crates.io-index" 1598 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 1599 | dependencies = [ 1600 | "num-traits", 1601 | ] 1602 | 1603 | [[package]] 1604 | name = "num-iter" 1605 | version = "0.1.45" 1606 | source = "registry+https://github.com/rust-lang/crates.io-index" 1607 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 1608 | dependencies = [ 1609 | "autocfg", 1610 | "num-integer", 1611 | "num-traits", 1612 | ] 1613 | 1614 | [[package]] 1615 | name = "num-traits" 1616 | version = "0.2.19" 1617 | source = "registry+https://github.com/rust-lang/crates.io-index" 1618 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1619 | dependencies = [ 1620 | "autocfg", 1621 | "libm", 1622 | ] 1623 | 1624 | [[package]] 1625 | name = "nwc" 1626 | version = "0.35.0" 1627 | source = "registry+https://github.com/rust-lang/crates.io-index" 1628 | checksum = "2e962f52732a6d91c1e76d4de3f1daa186e77a849e98e5abe53ca7fe9796d04e" 1629 | dependencies = [ 1630 | "async-utility", 1631 | "nostr 0.35.0", 1632 | "nostr-relay-pool 0.35.0", 1633 | "nostr-zapper 0.35.0", 1634 | "thiserror", 1635 | "tracing", 1636 | ] 1637 | 1638 | [[package]] 1639 | name = "nwc" 1640 | version = "0.36.0" 1641 | source = "registry+https://github.com/rust-lang/crates.io-index" 1642 | checksum = "1b5f98bcaf232b3ec48e018792ca7bc2b90e7520d001a07b8218a9e76a03fda2" 1643 | dependencies = [ 1644 | "async-trait", 1645 | "async-utility", 1646 | "nostr 0.36.0", 1647 | "nostr-relay-pool 0.36.0", 1648 | "nostr-zapper 0.36.0", 1649 | "thiserror", 1650 | "tracing", 1651 | ] 1652 | 1653 | [[package]] 1654 | name = "object" 1655 | version = "0.36.4" 1656 | source = "registry+https://github.com/rust-lang/crates.io-index" 1657 | checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" 1658 | dependencies = [ 1659 | "memchr", 1660 | ] 1661 | 1662 | [[package]] 1663 | name = "once_cell" 1664 | version = "1.20.2" 1665 | source = "registry+https://github.com/rust-lang/crates.io-index" 1666 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 1667 | 1668 | [[package]] 1669 | name = "opaque-debug" 1670 | version = "0.3.1" 1671 | source = "registry+https://github.com/rust-lang/crates.io-index" 1672 | checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" 1673 | 1674 | [[package]] 1675 | name = "openssl" 1676 | version = "0.10.71" 1677 | source = "registry+https://github.com/rust-lang/crates.io-index" 1678 | checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" 1679 | dependencies = [ 1680 | "bitflags", 1681 | "cfg-if", 1682 | "foreign-types", 1683 | "libc", 1684 | "once_cell", 1685 | "openssl-macros", 1686 | "openssl-sys", 1687 | ] 1688 | 1689 | [[package]] 1690 | name = "openssl-macros" 1691 | version = "0.1.1" 1692 | source = "registry+https://github.com/rust-lang/crates.io-index" 1693 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1694 | dependencies = [ 1695 | "proc-macro2", 1696 | "quote", 1697 | "syn", 1698 | ] 1699 | 1700 | [[package]] 1701 | name = "openssl-probe" 1702 | version = "0.1.5" 1703 | source = "registry+https://github.com/rust-lang/crates.io-index" 1704 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 1705 | 1706 | [[package]] 1707 | name = "openssl-sys" 1708 | version = "0.9.106" 1709 | source = "registry+https://github.com/rust-lang/crates.io-index" 1710 | checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" 1711 | dependencies = [ 1712 | "cc", 1713 | "libc", 1714 | "pkg-config", 1715 | "vcpkg", 1716 | ] 1717 | 1718 | [[package]] 1719 | name = "ordered-multimap" 1720 | version = "0.6.0" 1721 | source = "registry+https://github.com/rust-lang/crates.io-index" 1722 | checksum = "4ed8acf08e98e744e5384c8bc63ceb0364e68a6854187221c18df61c4797690e" 1723 | dependencies = [ 1724 | "dlv-list", 1725 | "hashbrown 0.13.2", 1726 | ] 1727 | 1728 | [[package]] 1729 | name = "parking" 1730 | version = "2.2.1" 1731 | source = "registry+https://github.com/rust-lang/crates.io-index" 1732 | checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" 1733 | 1734 | [[package]] 1735 | name = "parking_lot" 1736 | version = "0.12.3" 1737 | source = "registry+https://github.com/rust-lang/crates.io-index" 1738 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 1739 | dependencies = [ 1740 | "lock_api", 1741 | "parking_lot_core", 1742 | ] 1743 | 1744 | [[package]] 1745 | name = "parking_lot_core" 1746 | version = "0.9.10" 1747 | source = "registry+https://github.com/rust-lang/crates.io-index" 1748 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 1749 | dependencies = [ 1750 | "cfg-if", 1751 | "libc", 1752 | "redox_syscall", 1753 | "smallvec", 1754 | "windows-targets 0.52.6", 1755 | ] 1756 | 1757 | [[package]] 1758 | name = "password-hash" 1759 | version = "0.5.0" 1760 | source = "registry+https://github.com/rust-lang/crates.io-index" 1761 | checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" 1762 | dependencies = [ 1763 | "base64ct", 1764 | "rand_core", 1765 | "subtle", 1766 | ] 1767 | 1768 | [[package]] 1769 | name = "paste" 1770 | version = "1.0.15" 1771 | source = "registry+https://github.com/rust-lang/crates.io-index" 1772 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 1773 | 1774 | [[package]] 1775 | name = "pathdiff" 1776 | version = "0.2.2" 1777 | source = "registry+https://github.com/rust-lang/crates.io-index" 1778 | checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" 1779 | 1780 | [[package]] 1781 | name = "pbkdf2" 1782 | version = "0.12.2" 1783 | source = "registry+https://github.com/rust-lang/crates.io-index" 1784 | checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" 1785 | dependencies = [ 1786 | "digest", 1787 | "hmac", 1788 | ] 1789 | 1790 | [[package]] 1791 | name = "pem-rfc7468" 1792 | version = "0.7.0" 1793 | source = "registry+https://github.com/rust-lang/crates.io-index" 1794 | checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" 1795 | dependencies = [ 1796 | "base64ct", 1797 | ] 1798 | 1799 | [[package]] 1800 | name = "percent-encoding" 1801 | version = "2.3.1" 1802 | source = "registry+https://github.com/rust-lang/crates.io-index" 1803 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1804 | 1805 | [[package]] 1806 | name = "pest" 1807 | version = "2.7.14" 1808 | source = "registry+https://github.com/rust-lang/crates.io-index" 1809 | checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" 1810 | dependencies = [ 1811 | "memchr", 1812 | "thiserror", 1813 | "ucd-trie", 1814 | ] 1815 | 1816 | [[package]] 1817 | name = "pest_derive" 1818 | version = "2.7.14" 1819 | source = "registry+https://github.com/rust-lang/crates.io-index" 1820 | checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" 1821 | dependencies = [ 1822 | "pest", 1823 | "pest_generator", 1824 | ] 1825 | 1826 | [[package]] 1827 | name = "pest_generator" 1828 | version = "2.7.14" 1829 | source = "registry+https://github.com/rust-lang/crates.io-index" 1830 | checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" 1831 | dependencies = [ 1832 | "pest", 1833 | "pest_meta", 1834 | "proc-macro2", 1835 | "quote", 1836 | "syn", 1837 | ] 1838 | 1839 | [[package]] 1840 | name = "pest_meta" 1841 | version = "2.7.14" 1842 | source = "registry+https://github.com/rust-lang/crates.io-index" 1843 | checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" 1844 | dependencies = [ 1845 | "once_cell", 1846 | "pest", 1847 | "sha2", 1848 | ] 1849 | 1850 | [[package]] 1851 | name = "pin-project-lite" 1852 | version = "0.2.14" 1853 | source = "registry+https://github.com/rust-lang/crates.io-index" 1854 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 1855 | 1856 | [[package]] 1857 | name = "pin-utils" 1858 | version = "0.1.0" 1859 | source = "registry+https://github.com/rust-lang/crates.io-index" 1860 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1861 | 1862 | [[package]] 1863 | name = "pkcs1" 1864 | version = "0.7.5" 1865 | source = "registry+https://github.com/rust-lang/crates.io-index" 1866 | checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" 1867 | dependencies = [ 1868 | "der", 1869 | "pkcs8", 1870 | "spki", 1871 | ] 1872 | 1873 | [[package]] 1874 | name = "pkcs8" 1875 | version = "0.10.2" 1876 | source = "registry+https://github.com/rust-lang/crates.io-index" 1877 | checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 1878 | dependencies = [ 1879 | "der", 1880 | "spki", 1881 | ] 1882 | 1883 | [[package]] 1884 | name = "pkg-config" 1885 | version = "0.3.31" 1886 | source = "registry+https://github.com/rust-lang/crates.io-index" 1887 | checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" 1888 | 1889 | [[package]] 1890 | name = "poly1305" 1891 | version = "0.8.0" 1892 | source = "registry+https://github.com/rust-lang/crates.io-index" 1893 | checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" 1894 | dependencies = [ 1895 | "cpufeatures", 1896 | "opaque-debug", 1897 | "universal-hash", 1898 | ] 1899 | 1900 | [[package]] 1901 | name = "ppv-lite86" 1902 | version = "0.2.20" 1903 | source = "registry+https://github.com/rust-lang/crates.io-index" 1904 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 1905 | dependencies = [ 1906 | "zerocopy", 1907 | ] 1908 | 1909 | [[package]] 1910 | name = "proc-macro2" 1911 | version = "1.0.86" 1912 | source = "registry+https://github.com/rust-lang/crates.io-index" 1913 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 1914 | dependencies = [ 1915 | "unicode-ident", 1916 | ] 1917 | 1918 | [[package]] 1919 | name = "quinn" 1920 | version = "0.11.5" 1921 | source = "registry+https://github.com/rust-lang/crates.io-index" 1922 | checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" 1923 | dependencies = [ 1924 | "bytes", 1925 | "pin-project-lite", 1926 | "quinn-proto", 1927 | "quinn-udp", 1928 | "rustc-hash", 1929 | "rustls", 1930 | "socket2", 1931 | "thiserror", 1932 | "tokio", 1933 | "tracing", 1934 | ] 1935 | 1936 | [[package]] 1937 | name = "quinn-proto" 1938 | version = "0.11.8" 1939 | source = "registry+https://github.com/rust-lang/crates.io-index" 1940 | checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" 1941 | dependencies = [ 1942 | "bytes", 1943 | "rand", 1944 | "ring", 1945 | "rustc-hash", 1946 | "rustls", 1947 | "slab", 1948 | "thiserror", 1949 | "tinyvec", 1950 | "tracing", 1951 | ] 1952 | 1953 | [[package]] 1954 | name = "quinn-udp" 1955 | version = "0.5.5" 1956 | source = "registry+https://github.com/rust-lang/crates.io-index" 1957 | checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" 1958 | dependencies = [ 1959 | "libc", 1960 | "once_cell", 1961 | "socket2", 1962 | "tracing", 1963 | "windows-sys 0.59.0", 1964 | ] 1965 | 1966 | [[package]] 1967 | name = "quote" 1968 | version = "1.0.37" 1969 | source = "registry+https://github.com/rust-lang/crates.io-index" 1970 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 1971 | dependencies = [ 1972 | "proc-macro2", 1973 | ] 1974 | 1975 | [[package]] 1976 | name = "rand" 1977 | version = "0.8.5" 1978 | source = "registry+https://github.com/rust-lang/crates.io-index" 1979 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1980 | dependencies = [ 1981 | "libc", 1982 | "rand_chacha", 1983 | "rand_core", 1984 | ] 1985 | 1986 | [[package]] 1987 | name = "rand_chacha" 1988 | version = "0.3.1" 1989 | source = "registry+https://github.com/rust-lang/crates.io-index" 1990 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1991 | dependencies = [ 1992 | "ppv-lite86", 1993 | "rand_core", 1994 | ] 1995 | 1996 | [[package]] 1997 | name = "rand_core" 1998 | version = "0.6.4" 1999 | source = "registry+https://github.com/rust-lang/crates.io-index" 2000 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 2001 | dependencies = [ 2002 | "getrandom", 2003 | ] 2004 | 2005 | [[package]] 2006 | name = "ratatui" 2007 | version = "0.28.1" 2008 | source = "registry+https://github.com/rust-lang/crates.io-index" 2009 | checksum = "fdef7f9be5c0122f890d58bdf4d964349ba6a6161f705907526d891efabba57d" 2010 | dependencies = [ 2011 | "bitflags", 2012 | "cassowary", 2013 | "compact_str", 2014 | "crossterm", 2015 | "instability", 2016 | "itertools", 2017 | "lru", 2018 | "paste", 2019 | "strum", 2020 | "strum_macros", 2021 | "unicode-segmentation", 2022 | "unicode-truncate", 2023 | "unicode-width 0.1.14", 2024 | ] 2025 | 2026 | [[package]] 2027 | name = "ratatui" 2028 | version = "0.29.0" 2029 | source = "registry+https://github.com/rust-lang/crates.io-index" 2030 | checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" 2031 | dependencies = [ 2032 | "bitflags", 2033 | "cassowary", 2034 | "compact_str", 2035 | "crossterm", 2036 | "indoc", 2037 | "instability", 2038 | "itertools", 2039 | "lru", 2040 | "paste", 2041 | "strum", 2042 | "unicode-segmentation", 2043 | "unicode-truncate", 2044 | "unicode-width 0.2.0", 2045 | ] 2046 | 2047 | [[package]] 2048 | name = "redox_syscall" 2049 | version = "0.5.6" 2050 | source = "registry+https://github.com/rust-lang/crates.io-index" 2051 | checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b" 2052 | dependencies = [ 2053 | "bitflags", 2054 | ] 2055 | 2056 | [[package]] 2057 | name = "reqwest" 2058 | version = "0.12.7" 2059 | source = "registry+https://github.com/rust-lang/crates.io-index" 2060 | checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" 2061 | dependencies = [ 2062 | "base64 0.22.1", 2063 | "bytes", 2064 | "futures-core", 2065 | "futures-util", 2066 | "http", 2067 | "http-body", 2068 | "http-body-util", 2069 | "hyper", 2070 | "hyper-rustls", 2071 | "hyper-util", 2072 | "ipnet", 2073 | "js-sys", 2074 | "log", 2075 | "mime", 2076 | "once_cell", 2077 | "percent-encoding", 2078 | "pin-project-lite", 2079 | "quinn", 2080 | "rustls", 2081 | "rustls-pemfile", 2082 | "rustls-pki-types", 2083 | "serde", 2084 | "serde_json", 2085 | "serde_urlencoded", 2086 | "sync_wrapper", 2087 | "tokio", 2088 | "tokio-rustls", 2089 | "tokio-socks", 2090 | "tower-service", 2091 | "url", 2092 | "wasm-bindgen", 2093 | "wasm-bindgen-futures", 2094 | "web-sys", 2095 | "webpki-roots", 2096 | "windows-registry", 2097 | ] 2098 | 2099 | [[package]] 2100 | name = "ring" 2101 | version = "0.17.8" 2102 | source = "registry+https://github.com/rust-lang/crates.io-index" 2103 | checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" 2104 | dependencies = [ 2105 | "cc", 2106 | "cfg-if", 2107 | "getrandom", 2108 | "libc", 2109 | "spin", 2110 | "untrusted", 2111 | "windows-sys 0.52.0", 2112 | ] 2113 | 2114 | [[package]] 2115 | name = "ron" 2116 | version = "0.8.1" 2117 | source = "registry+https://github.com/rust-lang/crates.io-index" 2118 | checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" 2119 | dependencies = [ 2120 | "base64 0.21.7", 2121 | "bitflags", 2122 | "serde", 2123 | "serde_derive", 2124 | ] 2125 | 2126 | [[package]] 2127 | name = "rsa" 2128 | version = "0.9.6" 2129 | source = "registry+https://github.com/rust-lang/crates.io-index" 2130 | checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" 2131 | dependencies = [ 2132 | "const-oid", 2133 | "digest", 2134 | "num-bigint-dig", 2135 | "num-integer", 2136 | "num-traits", 2137 | "pkcs1", 2138 | "pkcs8", 2139 | "rand_core", 2140 | "signature", 2141 | "spki", 2142 | "subtle", 2143 | "zeroize", 2144 | ] 2145 | 2146 | [[package]] 2147 | name = "rust-ini" 2148 | version = "0.19.0" 2149 | source = "registry+https://github.com/rust-lang/crates.io-index" 2150 | checksum = "7e2a3bcec1f113553ef1c88aae6c020a369d03d55b58de9869a0908930385091" 2151 | dependencies = [ 2152 | "cfg-if", 2153 | "ordered-multimap", 2154 | ] 2155 | 2156 | [[package]] 2157 | name = "rustc-demangle" 2158 | version = "0.1.24" 2159 | source = "registry+https://github.com/rust-lang/crates.io-index" 2160 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 2161 | 2162 | [[package]] 2163 | name = "rustc-hash" 2164 | version = "2.0.0" 2165 | source = "registry+https://github.com/rust-lang/crates.io-index" 2166 | checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" 2167 | 2168 | [[package]] 2169 | name = "rustix" 2170 | version = "0.38.37" 2171 | source = "registry+https://github.com/rust-lang/crates.io-index" 2172 | checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" 2173 | dependencies = [ 2174 | "bitflags", 2175 | "errno", 2176 | "libc", 2177 | "linux-raw-sys", 2178 | "windows-sys 0.52.0", 2179 | ] 2180 | 2181 | [[package]] 2182 | name = "rustls" 2183 | version = "0.23.13" 2184 | source = "registry+https://github.com/rust-lang/crates.io-index" 2185 | checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" 2186 | dependencies = [ 2187 | "once_cell", 2188 | "ring", 2189 | "rustls-pki-types", 2190 | "rustls-webpki", 2191 | "subtle", 2192 | "zeroize", 2193 | ] 2194 | 2195 | [[package]] 2196 | name = "rustls-pemfile" 2197 | version = "2.1.3" 2198 | source = "registry+https://github.com/rust-lang/crates.io-index" 2199 | checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" 2200 | dependencies = [ 2201 | "base64 0.22.1", 2202 | "rustls-pki-types", 2203 | ] 2204 | 2205 | [[package]] 2206 | name = "rustls-pki-types" 2207 | version = "1.8.0" 2208 | source = "registry+https://github.com/rust-lang/crates.io-index" 2209 | checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" 2210 | 2211 | [[package]] 2212 | name = "rustls-webpki" 2213 | version = "0.102.8" 2214 | source = "registry+https://github.com/rust-lang/crates.io-index" 2215 | checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" 2216 | dependencies = [ 2217 | "ring", 2218 | "rustls-pki-types", 2219 | "untrusted", 2220 | ] 2221 | 2222 | [[package]] 2223 | name = "rustversion" 2224 | version = "1.0.17" 2225 | source = "registry+https://github.com/rust-lang/crates.io-index" 2226 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" 2227 | 2228 | [[package]] 2229 | name = "ryu" 2230 | version = "1.0.18" 2231 | source = "registry+https://github.com/rust-lang/crates.io-index" 2232 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 2233 | 2234 | [[package]] 2235 | name = "salsa20" 2236 | version = "0.10.2" 2237 | source = "registry+https://github.com/rust-lang/crates.io-index" 2238 | checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" 2239 | dependencies = [ 2240 | "cipher", 2241 | ] 2242 | 2243 | [[package]] 2244 | name = "schannel" 2245 | version = "0.1.26" 2246 | source = "registry+https://github.com/rust-lang/crates.io-index" 2247 | checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" 2248 | dependencies = [ 2249 | "windows-sys 0.59.0", 2250 | ] 2251 | 2252 | [[package]] 2253 | name = "scopeguard" 2254 | version = "1.2.0" 2255 | source = "registry+https://github.com/rust-lang/crates.io-index" 2256 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 2257 | 2258 | [[package]] 2259 | name = "scrypt" 2260 | version = "0.11.0" 2261 | source = "registry+https://github.com/rust-lang/crates.io-index" 2262 | checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" 2263 | dependencies = [ 2264 | "password-hash", 2265 | "pbkdf2", 2266 | "salsa20", 2267 | "sha2", 2268 | ] 2269 | 2270 | [[package]] 2271 | name = "secp256k1" 2272 | version = "0.29.1" 2273 | source = "registry+https://github.com/rust-lang/crates.io-index" 2274 | checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" 2275 | dependencies = [ 2276 | "bitcoin_hashes 0.14.0", 2277 | "rand", 2278 | "secp256k1-sys", 2279 | "serde", 2280 | ] 2281 | 2282 | [[package]] 2283 | name = "secp256k1-sys" 2284 | version = "0.10.1" 2285 | source = "registry+https://github.com/rust-lang/crates.io-index" 2286 | checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" 2287 | dependencies = [ 2288 | "cc", 2289 | ] 2290 | 2291 | [[package]] 2292 | name = "security-framework" 2293 | version = "2.11.1" 2294 | source = "registry+https://github.com/rust-lang/crates.io-index" 2295 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 2296 | dependencies = [ 2297 | "bitflags", 2298 | "core-foundation", 2299 | "core-foundation-sys", 2300 | "libc", 2301 | "security-framework-sys", 2302 | ] 2303 | 2304 | [[package]] 2305 | name = "security-framework-sys" 2306 | version = "2.12.0" 2307 | source = "registry+https://github.com/rust-lang/crates.io-index" 2308 | checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" 2309 | dependencies = [ 2310 | "core-foundation-sys", 2311 | "libc", 2312 | ] 2313 | 2314 | [[package]] 2315 | name = "serde" 2316 | version = "1.0.213" 2317 | source = "registry+https://github.com/rust-lang/crates.io-index" 2318 | checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" 2319 | dependencies = [ 2320 | "serde_derive", 2321 | ] 2322 | 2323 | [[package]] 2324 | name = "serde_derive" 2325 | version = "1.0.213" 2326 | source = "registry+https://github.com/rust-lang/crates.io-index" 2327 | checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" 2328 | dependencies = [ 2329 | "proc-macro2", 2330 | "quote", 2331 | "syn", 2332 | ] 2333 | 2334 | [[package]] 2335 | name = "serde_json" 2336 | version = "1.0.128" 2337 | source = "registry+https://github.com/rust-lang/crates.io-index" 2338 | checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" 2339 | dependencies = [ 2340 | "indexmap", 2341 | "itoa", 2342 | "memchr", 2343 | "ryu", 2344 | "serde", 2345 | ] 2346 | 2347 | [[package]] 2348 | name = "serde_spanned" 2349 | version = "0.6.8" 2350 | source = "registry+https://github.com/rust-lang/crates.io-index" 2351 | checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" 2352 | dependencies = [ 2353 | "serde", 2354 | ] 2355 | 2356 | [[package]] 2357 | name = "serde_urlencoded" 2358 | version = "0.7.1" 2359 | source = "registry+https://github.com/rust-lang/crates.io-index" 2360 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 2361 | dependencies = [ 2362 | "form_urlencoded", 2363 | "itoa", 2364 | "ryu", 2365 | "serde", 2366 | ] 2367 | 2368 | [[package]] 2369 | name = "sha1" 2370 | version = "0.10.6" 2371 | source = "registry+https://github.com/rust-lang/crates.io-index" 2372 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 2373 | dependencies = [ 2374 | "cfg-if", 2375 | "cpufeatures", 2376 | "digest", 2377 | ] 2378 | 2379 | [[package]] 2380 | name = "sha2" 2381 | version = "0.10.8" 2382 | source = "registry+https://github.com/rust-lang/crates.io-index" 2383 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 2384 | dependencies = [ 2385 | "cfg-if", 2386 | "cpufeatures", 2387 | "digest", 2388 | ] 2389 | 2390 | [[package]] 2391 | name = "shlex" 2392 | version = "1.3.0" 2393 | source = "registry+https://github.com/rust-lang/crates.io-index" 2394 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 2395 | 2396 | [[package]] 2397 | name = "signal-hook" 2398 | version = "0.3.17" 2399 | source = "registry+https://github.com/rust-lang/crates.io-index" 2400 | checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" 2401 | dependencies = [ 2402 | "libc", 2403 | "signal-hook-registry", 2404 | ] 2405 | 2406 | [[package]] 2407 | name = "signal-hook-mio" 2408 | version = "0.2.4" 2409 | source = "registry+https://github.com/rust-lang/crates.io-index" 2410 | checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" 2411 | dependencies = [ 2412 | "libc", 2413 | "mio", 2414 | "signal-hook", 2415 | ] 2416 | 2417 | [[package]] 2418 | name = "signal-hook-registry" 2419 | version = "1.4.2" 2420 | source = "registry+https://github.com/rust-lang/crates.io-index" 2421 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 2422 | dependencies = [ 2423 | "libc", 2424 | ] 2425 | 2426 | [[package]] 2427 | name = "signature" 2428 | version = "2.2.0" 2429 | source = "registry+https://github.com/rust-lang/crates.io-index" 2430 | checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" 2431 | dependencies = [ 2432 | "digest", 2433 | "rand_core", 2434 | ] 2435 | 2436 | [[package]] 2437 | name = "slab" 2438 | version = "0.4.9" 2439 | source = "registry+https://github.com/rust-lang/crates.io-index" 2440 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 2441 | dependencies = [ 2442 | "autocfg", 2443 | ] 2444 | 2445 | [[package]] 2446 | name = "smallvec" 2447 | version = "1.13.2" 2448 | source = "registry+https://github.com/rust-lang/crates.io-index" 2449 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 2450 | dependencies = [ 2451 | "serde", 2452 | ] 2453 | 2454 | [[package]] 2455 | name = "socket2" 2456 | version = "0.5.7" 2457 | source = "registry+https://github.com/rust-lang/crates.io-index" 2458 | checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" 2459 | dependencies = [ 2460 | "libc", 2461 | "windows-sys 0.52.0", 2462 | ] 2463 | 2464 | [[package]] 2465 | name = "spin" 2466 | version = "0.9.8" 2467 | source = "registry+https://github.com/rust-lang/crates.io-index" 2468 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 2469 | dependencies = [ 2470 | "lock_api", 2471 | ] 2472 | 2473 | [[package]] 2474 | name = "spki" 2475 | version = "0.7.3" 2476 | source = "registry+https://github.com/rust-lang/crates.io-index" 2477 | checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" 2478 | dependencies = [ 2479 | "base64ct", 2480 | "der", 2481 | ] 2482 | 2483 | [[package]] 2484 | name = "sqlformat" 2485 | version = "0.2.6" 2486 | source = "registry+https://github.com/rust-lang/crates.io-index" 2487 | checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" 2488 | dependencies = [ 2489 | "nom", 2490 | "unicode_categories", 2491 | ] 2492 | 2493 | [[package]] 2494 | name = "sqlx" 2495 | version = "0.8.2" 2496 | source = "registry+https://github.com/rust-lang/crates.io-index" 2497 | checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e" 2498 | dependencies = [ 2499 | "sqlx-core", 2500 | "sqlx-macros", 2501 | "sqlx-mysql", 2502 | "sqlx-postgres", 2503 | "sqlx-sqlite", 2504 | ] 2505 | 2506 | [[package]] 2507 | name = "sqlx-core" 2508 | version = "0.8.2" 2509 | source = "registry+https://github.com/rust-lang/crates.io-index" 2510 | checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" 2511 | dependencies = [ 2512 | "atoi", 2513 | "byteorder", 2514 | "bytes", 2515 | "crc", 2516 | "crossbeam-queue", 2517 | "either", 2518 | "event-listener", 2519 | "futures-channel", 2520 | "futures-core", 2521 | "futures-intrusive", 2522 | "futures-io", 2523 | "futures-util", 2524 | "hashbrown 0.14.5", 2525 | "hashlink", 2526 | "hex", 2527 | "indexmap", 2528 | "log", 2529 | "memchr", 2530 | "native-tls", 2531 | "once_cell", 2532 | "paste", 2533 | "percent-encoding", 2534 | "serde", 2535 | "serde_json", 2536 | "sha2", 2537 | "smallvec", 2538 | "sqlformat", 2539 | "thiserror", 2540 | "tokio", 2541 | "tokio-stream", 2542 | "tracing", 2543 | "url", 2544 | ] 2545 | 2546 | [[package]] 2547 | name = "sqlx-macros" 2548 | version = "0.8.2" 2549 | source = "registry+https://github.com/rust-lang/crates.io-index" 2550 | checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" 2551 | dependencies = [ 2552 | "proc-macro2", 2553 | "quote", 2554 | "sqlx-core", 2555 | "sqlx-macros-core", 2556 | "syn", 2557 | ] 2558 | 2559 | [[package]] 2560 | name = "sqlx-macros-core" 2561 | version = "0.8.2" 2562 | source = "registry+https://github.com/rust-lang/crates.io-index" 2563 | checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" 2564 | dependencies = [ 2565 | "dotenvy", 2566 | "either", 2567 | "heck", 2568 | "hex", 2569 | "once_cell", 2570 | "proc-macro2", 2571 | "quote", 2572 | "serde", 2573 | "serde_json", 2574 | "sha2", 2575 | "sqlx-core", 2576 | "sqlx-mysql", 2577 | "sqlx-postgres", 2578 | "sqlx-sqlite", 2579 | "syn", 2580 | "tempfile", 2581 | "tokio", 2582 | "url", 2583 | ] 2584 | 2585 | [[package]] 2586 | name = "sqlx-mysql" 2587 | version = "0.8.2" 2588 | source = "registry+https://github.com/rust-lang/crates.io-index" 2589 | checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a" 2590 | dependencies = [ 2591 | "atoi", 2592 | "base64 0.22.1", 2593 | "bitflags", 2594 | "byteorder", 2595 | "bytes", 2596 | "crc", 2597 | "digest", 2598 | "dotenvy", 2599 | "either", 2600 | "futures-channel", 2601 | "futures-core", 2602 | "futures-io", 2603 | "futures-util", 2604 | "generic-array", 2605 | "hex", 2606 | "hkdf", 2607 | "hmac", 2608 | "itoa", 2609 | "log", 2610 | "md-5", 2611 | "memchr", 2612 | "once_cell", 2613 | "percent-encoding", 2614 | "rand", 2615 | "rsa", 2616 | "serde", 2617 | "sha1", 2618 | "sha2", 2619 | "smallvec", 2620 | "sqlx-core", 2621 | "stringprep", 2622 | "thiserror", 2623 | "tracing", 2624 | "whoami", 2625 | ] 2626 | 2627 | [[package]] 2628 | name = "sqlx-postgres" 2629 | version = "0.8.2" 2630 | source = "registry+https://github.com/rust-lang/crates.io-index" 2631 | checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8" 2632 | dependencies = [ 2633 | "atoi", 2634 | "base64 0.22.1", 2635 | "bitflags", 2636 | "byteorder", 2637 | "crc", 2638 | "dotenvy", 2639 | "etcetera", 2640 | "futures-channel", 2641 | "futures-core", 2642 | "futures-io", 2643 | "futures-util", 2644 | "hex", 2645 | "hkdf", 2646 | "hmac", 2647 | "home", 2648 | "itoa", 2649 | "log", 2650 | "md-5", 2651 | "memchr", 2652 | "once_cell", 2653 | "rand", 2654 | "serde", 2655 | "serde_json", 2656 | "sha2", 2657 | "smallvec", 2658 | "sqlx-core", 2659 | "stringprep", 2660 | "thiserror", 2661 | "tracing", 2662 | "whoami", 2663 | ] 2664 | 2665 | [[package]] 2666 | name = "sqlx-sqlite" 2667 | version = "0.8.2" 2668 | source = "registry+https://github.com/rust-lang/crates.io-index" 2669 | checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" 2670 | dependencies = [ 2671 | "atoi", 2672 | "flume", 2673 | "futures-channel", 2674 | "futures-core", 2675 | "futures-executor", 2676 | "futures-intrusive", 2677 | "futures-util", 2678 | "libsqlite3-sys", 2679 | "log", 2680 | "percent-encoding", 2681 | "serde", 2682 | "serde_urlencoded", 2683 | "sqlx-core", 2684 | "tracing", 2685 | "url", 2686 | ] 2687 | 2688 | [[package]] 2689 | name = "static_assertions" 2690 | version = "1.1.0" 2691 | source = "registry+https://github.com/rust-lang/crates.io-index" 2692 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 2693 | 2694 | [[package]] 2695 | name = "stringprep" 2696 | version = "0.1.5" 2697 | source = "registry+https://github.com/rust-lang/crates.io-index" 2698 | checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" 2699 | dependencies = [ 2700 | "unicode-bidi", 2701 | "unicode-normalization", 2702 | "unicode-properties", 2703 | ] 2704 | 2705 | [[package]] 2706 | name = "strum" 2707 | version = "0.26.3" 2708 | source = "registry+https://github.com/rust-lang/crates.io-index" 2709 | checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" 2710 | dependencies = [ 2711 | "strum_macros", 2712 | ] 2713 | 2714 | [[package]] 2715 | name = "strum_macros" 2716 | version = "0.26.4" 2717 | source = "registry+https://github.com/rust-lang/crates.io-index" 2718 | checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" 2719 | dependencies = [ 2720 | "heck", 2721 | "proc-macro2", 2722 | "quote", 2723 | "rustversion", 2724 | "syn", 2725 | ] 2726 | 2727 | [[package]] 2728 | name = "subtle" 2729 | version = "2.6.1" 2730 | source = "registry+https://github.com/rust-lang/crates.io-index" 2731 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 2732 | 2733 | [[package]] 2734 | name = "syn" 2735 | version = "2.0.83" 2736 | source = "registry+https://github.com/rust-lang/crates.io-index" 2737 | checksum = "01680f5d178a369f817f43f3d399650272873a8e7588a7872f7e90edc71d60a3" 2738 | dependencies = [ 2739 | "proc-macro2", 2740 | "quote", 2741 | "unicode-ident", 2742 | ] 2743 | 2744 | [[package]] 2745 | name = "sync_wrapper" 2746 | version = "1.0.1" 2747 | source = "registry+https://github.com/rust-lang/crates.io-index" 2748 | checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" 2749 | dependencies = [ 2750 | "futures-core", 2751 | ] 2752 | 2753 | [[package]] 2754 | name = "tempfile" 2755 | version = "3.13.0" 2756 | source = "registry+https://github.com/rust-lang/crates.io-index" 2757 | checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" 2758 | dependencies = [ 2759 | "cfg-if", 2760 | "fastrand", 2761 | "once_cell", 2762 | "rustix", 2763 | "windows-sys 0.59.0", 2764 | ] 2765 | 2766 | [[package]] 2767 | name = "thiserror" 2768 | version = "1.0.64" 2769 | source = "registry+https://github.com/rust-lang/crates.io-index" 2770 | checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" 2771 | dependencies = [ 2772 | "thiserror-impl", 2773 | ] 2774 | 2775 | [[package]] 2776 | name = "thiserror-impl" 2777 | version = "1.0.64" 2778 | source = "registry+https://github.com/rust-lang/crates.io-index" 2779 | checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" 2780 | dependencies = [ 2781 | "proc-macro2", 2782 | "quote", 2783 | "syn", 2784 | ] 2785 | 2786 | [[package]] 2787 | name = "tiny-keccak" 2788 | version = "2.0.2" 2789 | source = "registry+https://github.com/rust-lang/crates.io-index" 2790 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 2791 | dependencies = [ 2792 | "crunchy", 2793 | ] 2794 | 2795 | [[package]] 2796 | name = "tinyvec" 2797 | version = "1.8.0" 2798 | source = "registry+https://github.com/rust-lang/crates.io-index" 2799 | checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" 2800 | dependencies = [ 2801 | "tinyvec_macros", 2802 | ] 2803 | 2804 | [[package]] 2805 | name = "tinyvec_macros" 2806 | version = "0.1.1" 2807 | source = "registry+https://github.com/rust-lang/crates.io-index" 2808 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 2809 | 2810 | [[package]] 2811 | name = "tokio" 2812 | version = "1.40.0" 2813 | source = "registry+https://github.com/rust-lang/crates.io-index" 2814 | checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" 2815 | dependencies = [ 2816 | "backtrace", 2817 | "bytes", 2818 | "libc", 2819 | "mio", 2820 | "parking_lot", 2821 | "pin-project-lite", 2822 | "signal-hook-registry", 2823 | "socket2", 2824 | "tokio-macros", 2825 | "windows-sys 0.52.0", 2826 | ] 2827 | 2828 | [[package]] 2829 | name = "tokio-macros" 2830 | version = "2.4.0" 2831 | source = "registry+https://github.com/rust-lang/crates.io-index" 2832 | checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" 2833 | dependencies = [ 2834 | "proc-macro2", 2835 | "quote", 2836 | "syn", 2837 | ] 2838 | 2839 | [[package]] 2840 | name = "tokio-rustls" 2841 | version = "0.26.0" 2842 | source = "registry+https://github.com/rust-lang/crates.io-index" 2843 | checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" 2844 | dependencies = [ 2845 | "rustls", 2846 | "rustls-pki-types", 2847 | "tokio", 2848 | ] 2849 | 2850 | [[package]] 2851 | name = "tokio-socks" 2852 | version = "0.5.2" 2853 | source = "registry+https://github.com/rust-lang/crates.io-index" 2854 | checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" 2855 | dependencies = [ 2856 | "either", 2857 | "futures-util", 2858 | "thiserror", 2859 | "tokio", 2860 | ] 2861 | 2862 | [[package]] 2863 | name = "tokio-stream" 2864 | version = "0.1.16" 2865 | source = "registry+https://github.com/rust-lang/crates.io-index" 2866 | checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" 2867 | dependencies = [ 2868 | "futures-core", 2869 | "pin-project-lite", 2870 | "tokio", 2871 | ] 2872 | 2873 | [[package]] 2874 | name = "tokio-tungstenite" 2875 | version = "0.24.0" 2876 | source = "registry+https://github.com/rust-lang/crates.io-index" 2877 | checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" 2878 | dependencies = [ 2879 | "futures-util", 2880 | "log", 2881 | "rustls", 2882 | "rustls-pki-types", 2883 | "tokio", 2884 | "tokio-rustls", 2885 | "tungstenite", 2886 | "webpki-roots", 2887 | ] 2888 | 2889 | [[package]] 2890 | name = "toml" 2891 | version = "0.8.19" 2892 | source = "registry+https://github.com/rust-lang/crates.io-index" 2893 | checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" 2894 | dependencies = [ 2895 | "serde", 2896 | "serde_spanned", 2897 | "toml_datetime", 2898 | "toml_edit", 2899 | ] 2900 | 2901 | [[package]] 2902 | name = "toml_datetime" 2903 | version = "0.6.8" 2904 | source = "registry+https://github.com/rust-lang/crates.io-index" 2905 | checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" 2906 | dependencies = [ 2907 | "serde", 2908 | ] 2909 | 2910 | [[package]] 2911 | name = "toml_edit" 2912 | version = "0.22.22" 2913 | source = "registry+https://github.com/rust-lang/crates.io-index" 2914 | checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" 2915 | dependencies = [ 2916 | "indexmap", 2917 | "serde", 2918 | "serde_spanned", 2919 | "toml_datetime", 2920 | "winnow", 2921 | ] 2922 | 2923 | [[package]] 2924 | name = "tower-service" 2925 | version = "0.3.3" 2926 | source = "registry+https://github.com/rust-lang/crates.io-index" 2927 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 2928 | 2929 | [[package]] 2930 | name = "tracing" 2931 | version = "0.1.40" 2932 | source = "registry+https://github.com/rust-lang/crates.io-index" 2933 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 2934 | dependencies = [ 2935 | "log", 2936 | "pin-project-lite", 2937 | "tracing-attributes", 2938 | "tracing-core", 2939 | ] 2940 | 2941 | [[package]] 2942 | name = "tracing-attributes" 2943 | version = "0.1.27" 2944 | source = "registry+https://github.com/rust-lang/crates.io-index" 2945 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 2946 | dependencies = [ 2947 | "proc-macro2", 2948 | "quote", 2949 | "syn", 2950 | ] 2951 | 2952 | [[package]] 2953 | name = "tracing-core" 2954 | version = "0.1.32" 2955 | source = "registry+https://github.com/rust-lang/crates.io-index" 2956 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 2957 | dependencies = [ 2958 | "once_cell", 2959 | ] 2960 | 2961 | [[package]] 2962 | name = "try-lock" 2963 | version = "0.2.5" 2964 | source = "registry+https://github.com/rust-lang/crates.io-index" 2965 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 2966 | 2967 | [[package]] 2968 | name = "tui-input" 2969 | version = "0.10.1" 2970 | source = "registry+https://github.com/rust-lang/crates.io-index" 2971 | checksum = "bd137780d743c103a391e06fe952487f914b299a4fe2c3626677f6a6339a7c6b" 2972 | dependencies = [ 2973 | "ratatui 0.28.1", 2974 | "unicode-width 0.1.14", 2975 | ] 2976 | 2977 | [[package]] 2978 | name = "tungstenite" 2979 | version = "0.24.0" 2980 | source = "registry+https://github.com/rust-lang/crates.io-index" 2981 | checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" 2982 | dependencies = [ 2983 | "byteorder", 2984 | "bytes", 2985 | "data-encoding", 2986 | "http", 2987 | "httparse", 2988 | "log", 2989 | "rand", 2990 | "rustls", 2991 | "rustls-pki-types", 2992 | "sha1", 2993 | "thiserror", 2994 | "utf-8", 2995 | ] 2996 | 2997 | [[package]] 2998 | name = "typenum" 2999 | version = "1.17.0" 3000 | source = "registry+https://github.com/rust-lang/crates.io-index" 3001 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 3002 | 3003 | [[package]] 3004 | name = "ucd-trie" 3005 | version = "0.1.7" 3006 | source = "registry+https://github.com/rust-lang/crates.io-index" 3007 | checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" 3008 | 3009 | [[package]] 3010 | name = "unicode-bidi" 3011 | version = "0.3.15" 3012 | source = "registry+https://github.com/rust-lang/crates.io-index" 3013 | checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" 3014 | 3015 | [[package]] 3016 | name = "unicode-ident" 3017 | version = "1.0.13" 3018 | source = "registry+https://github.com/rust-lang/crates.io-index" 3019 | checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" 3020 | 3021 | [[package]] 3022 | name = "unicode-normalization" 3023 | version = "0.1.22" 3024 | source = "registry+https://github.com/rust-lang/crates.io-index" 3025 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 3026 | dependencies = [ 3027 | "tinyvec", 3028 | ] 3029 | 3030 | [[package]] 3031 | name = "unicode-properties" 3032 | version = "0.1.3" 3033 | source = "registry+https://github.com/rust-lang/crates.io-index" 3034 | checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" 3035 | 3036 | [[package]] 3037 | name = "unicode-segmentation" 3038 | version = "1.12.0" 3039 | source = "registry+https://github.com/rust-lang/crates.io-index" 3040 | checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" 3041 | 3042 | [[package]] 3043 | name = "unicode-truncate" 3044 | version = "1.1.0" 3045 | source = "registry+https://github.com/rust-lang/crates.io-index" 3046 | checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" 3047 | dependencies = [ 3048 | "itertools", 3049 | "unicode-segmentation", 3050 | "unicode-width 0.1.14", 3051 | ] 3052 | 3053 | [[package]] 3054 | name = "unicode-width" 3055 | version = "0.1.14" 3056 | source = "registry+https://github.com/rust-lang/crates.io-index" 3057 | checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" 3058 | 3059 | [[package]] 3060 | name = "unicode-width" 3061 | version = "0.2.0" 3062 | source = "registry+https://github.com/rust-lang/crates.io-index" 3063 | checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" 3064 | 3065 | [[package]] 3066 | name = "unicode_categories" 3067 | version = "0.1.1" 3068 | source = "registry+https://github.com/rust-lang/crates.io-index" 3069 | checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" 3070 | 3071 | [[package]] 3072 | name = "universal-hash" 3073 | version = "0.5.1" 3074 | source = "registry+https://github.com/rust-lang/crates.io-index" 3075 | checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" 3076 | dependencies = [ 3077 | "crypto-common", 3078 | "subtle", 3079 | ] 3080 | 3081 | [[package]] 3082 | name = "untrusted" 3083 | version = "0.9.0" 3084 | source = "registry+https://github.com/rust-lang/crates.io-index" 3085 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 3086 | 3087 | [[package]] 3088 | name = "url" 3089 | version = "2.5.2" 3090 | source = "registry+https://github.com/rust-lang/crates.io-index" 3091 | checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" 3092 | dependencies = [ 3093 | "form_urlencoded", 3094 | "idna", 3095 | "percent-encoding", 3096 | "serde", 3097 | ] 3098 | 3099 | [[package]] 3100 | name = "utf-8" 3101 | version = "0.7.6" 3102 | source = "registry+https://github.com/rust-lang/crates.io-index" 3103 | checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 3104 | 3105 | [[package]] 3106 | name = "uuid" 3107 | version = "1.10.0" 3108 | source = "registry+https://github.com/rust-lang/crates.io-index" 3109 | checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" 3110 | dependencies = [ 3111 | "getrandom", 3112 | "rand", 3113 | "serde", 3114 | "uuid-macro-internal", 3115 | "wasm-bindgen", 3116 | ] 3117 | 3118 | [[package]] 3119 | name = "uuid-macro-internal" 3120 | version = "1.10.0" 3121 | source = "registry+https://github.com/rust-lang/crates.io-index" 3122 | checksum = "ee1cd046f83ea2c4e920d6ee9f7c3537ef928d75dce5d84a87c2c5d6b3999a3a" 3123 | dependencies = [ 3124 | "proc-macro2", 3125 | "quote", 3126 | "syn", 3127 | ] 3128 | 3129 | [[package]] 3130 | name = "vcpkg" 3131 | version = "0.2.15" 3132 | source = "registry+https://github.com/rust-lang/crates.io-index" 3133 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 3134 | 3135 | [[package]] 3136 | name = "version_check" 3137 | version = "0.9.5" 3138 | source = "registry+https://github.com/rust-lang/crates.io-index" 3139 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 3140 | 3141 | [[package]] 3142 | name = "want" 3143 | version = "0.3.1" 3144 | source = "registry+https://github.com/rust-lang/crates.io-index" 3145 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 3146 | dependencies = [ 3147 | "try-lock", 3148 | ] 3149 | 3150 | [[package]] 3151 | name = "wasi" 3152 | version = "0.11.0+wasi-snapshot-preview1" 3153 | source = "registry+https://github.com/rust-lang/crates.io-index" 3154 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 3155 | 3156 | [[package]] 3157 | name = "wasite" 3158 | version = "0.1.0" 3159 | source = "registry+https://github.com/rust-lang/crates.io-index" 3160 | checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" 3161 | 3162 | [[package]] 3163 | name = "wasm-bindgen" 3164 | version = "0.2.93" 3165 | source = "registry+https://github.com/rust-lang/crates.io-index" 3166 | checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" 3167 | dependencies = [ 3168 | "cfg-if", 3169 | "once_cell", 3170 | "wasm-bindgen-macro", 3171 | ] 3172 | 3173 | [[package]] 3174 | name = "wasm-bindgen-backend" 3175 | version = "0.2.93" 3176 | source = "registry+https://github.com/rust-lang/crates.io-index" 3177 | checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" 3178 | dependencies = [ 3179 | "bumpalo", 3180 | "log", 3181 | "once_cell", 3182 | "proc-macro2", 3183 | "quote", 3184 | "syn", 3185 | "wasm-bindgen-shared", 3186 | ] 3187 | 3188 | [[package]] 3189 | name = "wasm-bindgen-futures" 3190 | version = "0.4.43" 3191 | source = "registry+https://github.com/rust-lang/crates.io-index" 3192 | checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" 3193 | dependencies = [ 3194 | "cfg-if", 3195 | "js-sys", 3196 | "wasm-bindgen", 3197 | "web-sys", 3198 | ] 3199 | 3200 | [[package]] 3201 | name = "wasm-bindgen-macro" 3202 | version = "0.2.93" 3203 | source = "registry+https://github.com/rust-lang/crates.io-index" 3204 | checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" 3205 | dependencies = [ 3206 | "quote", 3207 | "wasm-bindgen-macro-support", 3208 | ] 3209 | 3210 | [[package]] 3211 | name = "wasm-bindgen-macro-support" 3212 | version = "0.2.93" 3213 | source = "registry+https://github.com/rust-lang/crates.io-index" 3214 | checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" 3215 | dependencies = [ 3216 | "proc-macro2", 3217 | "quote", 3218 | "syn", 3219 | "wasm-bindgen-backend", 3220 | "wasm-bindgen-shared", 3221 | ] 3222 | 3223 | [[package]] 3224 | name = "wasm-bindgen-shared" 3225 | version = "0.2.93" 3226 | source = "registry+https://github.com/rust-lang/crates.io-index" 3227 | checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" 3228 | 3229 | [[package]] 3230 | name = "web-sys" 3231 | version = "0.3.70" 3232 | source = "registry+https://github.com/rust-lang/crates.io-index" 3233 | checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" 3234 | dependencies = [ 3235 | "js-sys", 3236 | "wasm-bindgen", 3237 | ] 3238 | 3239 | [[package]] 3240 | name = "webpki-roots" 3241 | version = "0.26.6" 3242 | source = "registry+https://github.com/rust-lang/crates.io-index" 3243 | checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" 3244 | dependencies = [ 3245 | "rustls-pki-types", 3246 | ] 3247 | 3248 | [[package]] 3249 | name = "whoami" 3250 | version = "1.5.2" 3251 | source = "registry+https://github.com/rust-lang/crates.io-index" 3252 | checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" 3253 | dependencies = [ 3254 | "redox_syscall", 3255 | "wasite", 3256 | ] 3257 | 3258 | [[package]] 3259 | name = "winapi" 3260 | version = "0.3.9" 3261 | source = "registry+https://github.com/rust-lang/crates.io-index" 3262 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 3263 | dependencies = [ 3264 | "winapi-i686-pc-windows-gnu", 3265 | "winapi-x86_64-pc-windows-gnu", 3266 | ] 3267 | 3268 | [[package]] 3269 | name = "winapi-i686-pc-windows-gnu" 3270 | version = "0.4.0" 3271 | source = "registry+https://github.com/rust-lang/crates.io-index" 3272 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 3273 | 3274 | [[package]] 3275 | name = "winapi-x86_64-pc-windows-gnu" 3276 | version = "0.4.0" 3277 | source = "registry+https://github.com/rust-lang/crates.io-index" 3278 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 3279 | 3280 | [[package]] 3281 | name = "windows-core" 3282 | version = "0.52.0" 3283 | source = "registry+https://github.com/rust-lang/crates.io-index" 3284 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 3285 | dependencies = [ 3286 | "windows-targets 0.52.6", 3287 | ] 3288 | 3289 | [[package]] 3290 | name = "windows-registry" 3291 | version = "0.2.0" 3292 | source = "registry+https://github.com/rust-lang/crates.io-index" 3293 | checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" 3294 | dependencies = [ 3295 | "windows-result", 3296 | "windows-strings", 3297 | "windows-targets 0.52.6", 3298 | ] 3299 | 3300 | [[package]] 3301 | name = "windows-result" 3302 | version = "0.2.0" 3303 | source = "registry+https://github.com/rust-lang/crates.io-index" 3304 | checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" 3305 | dependencies = [ 3306 | "windows-targets 0.52.6", 3307 | ] 3308 | 3309 | [[package]] 3310 | name = "windows-strings" 3311 | version = "0.1.0" 3312 | source = "registry+https://github.com/rust-lang/crates.io-index" 3313 | checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" 3314 | dependencies = [ 3315 | "windows-result", 3316 | "windows-targets 0.52.6", 3317 | ] 3318 | 3319 | [[package]] 3320 | name = "windows-sys" 3321 | version = "0.48.0" 3322 | source = "registry+https://github.com/rust-lang/crates.io-index" 3323 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 3324 | dependencies = [ 3325 | "windows-targets 0.48.5", 3326 | ] 3327 | 3328 | [[package]] 3329 | name = "windows-sys" 3330 | version = "0.52.0" 3331 | source = "registry+https://github.com/rust-lang/crates.io-index" 3332 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 3333 | dependencies = [ 3334 | "windows-targets 0.52.6", 3335 | ] 3336 | 3337 | [[package]] 3338 | name = "windows-sys" 3339 | version = "0.59.0" 3340 | source = "registry+https://github.com/rust-lang/crates.io-index" 3341 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 3342 | dependencies = [ 3343 | "windows-targets 0.52.6", 3344 | ] 3345 | 3346 | [[package]] 3347 | name = "windows-targets" 3348 | version = "0.48.5" 3349 | source = "registry+https://github.com/rust-lang/crates.io-index" 3350 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 3351 | dependencies = [ 3352 | "windows_aarch64_gnullvm 0.48.5", 3353 | "windows_aarch64_msvc 0.48.5", 3354 | "windows_i686_gnu 0.48.5", 3355 | "windows_i686_msvc 0.48.5", 3356 | "windows_x86_64_gnu 0.48.5", 3357 | "windows_x86_64_gnullvm 0.48.5", 3358 | "windows_x86_64_msvc 0.48.5", 3359 | ] 3360 | 3361 | [[package]] 3362 | name = "windows-targets" 3363 | version = "0.52.6" 3364 | source = "registry+https://github.com/rust-lang/crates.io-index" 3365 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 3366 | dependencies = [ 3367 | "windows_aarch64_gnullvm 0.52.6", 3368 | "windows_aarch64_msvc 0.52.6", 3369 | "windows_i686_gnu 0.52.6", 3370 | "windows_i686_gnullvm", 3371 | "windows_i686_msvc 0.52.6", 3372 | "windows_x86_64_gnu 0.52.6", 3373 | "windows_x86_64_gnullvm 0.52.6", 3374 | "windows_x86_64_msvc 0.52.6", 3375 | ] 3376 | 3377 | [[package]] 3378 | name = "windows_aarch64_gnullvm" 3379 | version = "0.48.5" 3380 | source = "registry+https://github.com/rust-lang/crates.io-index" 3381 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 3382 | 3383 | [[package]] 3384 | name = "windows_aarch64_gnullvm" 3385 | version = "0.52.6" 3386 | source = "registry+https://github.com/rust-lang/crates.io-index" 3387 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 3388 | 3389 | [[package]] 3390 | name = "windows_aarch64_msvc" 3391 | version = "0.48.5" 3392 | source = "registry+https://github.com/rust-lang/crates.io-index" 3393 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 3394 | 3395 | [[package]] 3396 | name = "windows_aarch64_msvc" 3397 | version = "0.52.6" 3398 | source = "registry+https://github.com/rust-lang/crates.io-index" 3399 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 3400 | 3401 | [[package]] 3402 | name = "windows_i686_gnu" 3403 | version = "0.48.5" 3404 | source = "registry+https://github.com/rust-lang/crates.io-index" 3405 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 3406 | 3407 | [[package]] 3408 | name = "windows_i686_gnu" 3409 | version = "0.52.6" 3410 | source = "registry+https://github.com/rust-lang/crates.io-index" 3411 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 3412 | 3413 | [[package]] 3414 | name = "windows_i686_gnullvm" 3415 | version = "0.52.6" 3416 | source = "registry+https://github.com/rust-lang/crates.io-index" 3417 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 3418 | 3419 | [[package]] 3420 | name = "windows_i686_msvc" 3421 | version = "0.48.5" 3422 | source = "registry+https://github.com/rust-lang/crates.io-index" 3423 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 3424 | 3425 | [[package]] 3426 | name = "windows_i686_msvc" 3427 | version = "0.52.6" 3428 | source = "registry+https://github.com/rust-lang/crates.io-index" 3429 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 3430 | 3431 | [[package]] 3432 | name = "windows_x86_64_gnu" 3433 | version = "0.48.5" 3434 | source = "registry+https://github.com/rust-lang/crates.io-index" 3435 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 3436 | 3437 | [[package]] 3438 | name = "windows_x86_64_gnu" 3439 | version = "0.52.6" 3440 | source = "registry+https://github.com/rust-lang/crates.io-index" 3441 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 3442 | 3443 | [[package]] 3444 | name = "windows_x86_64_gnullvm" 3445 | version = "0.48.5" 3446 | source = "registry+https://github.com/rust-lang/crates.io-index" 3447 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 3448 | 3449 | [[package]] 3450 | name = "windows_x86_64_gnullvm" 3451 | version = "0.52.6" 3452 | source = "registry+https://github.com/rust-lang/crates.io-index" 3453 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 3454 | 3455 | [[package]] 3456 | name = "windows_x86_64_msvc" 3457 | version = "0.48.5" 3458 | source = "registry+https://github.com/rust-lang/crates.io-index" 3459 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 3460 | 3461 | [[package]] 3462 | name = "windows_x86_64_msvc" 3463 | version = "0.52.6" 3464 | source = "registry+https://github.com/rust-lang/crates.io-index" 3465 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 3466 | 3467 | [[package]] 3468 | name = "winnow" 3469 | version = "0.6.20" 3470 | source = "registry+https://github.com/rust-lang/crates.io-index" 3471 | checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" 3472 | dependencies = [ 3473 | "memchr", 3474 | ] 3475 | 3476 | [[package]] 3477 | name = "yaml-rust" 3478 | version = "0.4.5" 3479 | source = "registry+https://github.com/rust-lang/crates.io-index" 3480 | checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" 3481 | dependencies = [ 3482 | "linked-hash-map", 3483 | ] 3484 | 3485 | [[package]] 3486 | name = "zerocopy" 3487 | version = "0.7.35" 3488 | source = "registry+https://github.com/rust-lang/crates.io-index" 3489 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 3490 | dependencies = [ 3491 | "byteorder", 3492 | "zerocopy-derive", 3493 | ] 3494 | 3495 | [[package]] 3496 | name = "zerocopy-derive" 3497 | version = "0.7.35" 3498 | source = "registry+https://github.com/rust-lang/crates.io-index" 3499 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 3500 | dependencies = [ 3501 | "proc-macro2", 3502 | "quote", 3503 | "syn", 3504 | ] 3505 | 3506 | [[package]] 3507 | name = "zeroize" 3508 | version = "1.8.1" 3509 | source = "registry+https://github.com/rust-lang/crates.io-index" 3510 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 3511 | --------------------------------------------------------------------------------