Skip to content
This repository was archived by the owner on Feb 3, 2025. It is now read-only.

Commit 1f0207c

Browse files
committed
extractor to handle error responses
1 parent 7cc4cbe commit 1f0207c

File tree

7 files changed

+272
-98
lines changed

7 files changed

+272
-98
lines changed

Cargo.lock

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mutiny-core/src/lib.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -704,36 +704,6 @@ pub struct MutinyWalletConfig {
704704
skip_hodl_invoices: bool,
705705
}
706706

707-
impl MutinyWalletConfig {
708-
pub fn new(
709-
xprivkey: ExtendedPrivKey,
710-
network: Network,
711-
esplora: Option<String>,
712-
rgs: Option<String>,
713-
lsp: Option<String>,
714-
) -> MutinyWalletConfig {
715-
MutinyWalletConfig {
716-
xprivkey,
717-
#[cfg(target_arch = "wasm32")]
718-
websocket_proxy_addr: None,
719-
network,
720-
user_esplora_url: esplora,
721-
user_rgs_url: rgs,
722-
lsp_url: lsp,
723-
lsp_token: None,
724-
lsp_connection_string: None,
725-
auth_client: None,
726-
subscription_url: None,
727-
scorer_url: None,
728-
primal_url: None,
729-
do_not_connect_peers: false,
730-
skip_device_lock: false,
731-
safe_mode: false,
732-
skip_hodl_invoices: true,
733-
}
734-
}
735-
}
736-
737707
pub struct MutinyWalletBuilder<S: MutinyStorage> {
738708
xprivkey: ExtendedPrivKey,
739709
nostr_key_source: NostrKeySource,

mutiny-server/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mutiny-core = { path = "../mutiny-core" }
1010

1111
anyhow = "1.0.70"
1212
async-trait = "0.1.68"
13-
axum = "0.7.4"
13+
axum = { version = "0.7.4" , features = ["default", "macros"]}
1414
bitcoin = { version = "0.30.2" }
1515
clap = { version = "4.1.14", features = ["derive"] }
1616
lightning = { version = "0.0.121", default-features = false, features = ["max_level_trace", "grind_signatures", "std"] }
@@ -23,4 +23,4 @@ futures-util = { version = "0.3", default-features = false }
2323
sled = "0.34.7"
2424
tokio = { version = "1.36.0", features = ["full"] }
2525
reqwest = { version = "0.11", features = ["json"] }
26-
serde = { version = "1.0.196", features = ["derive"] }
26+
serde = { version = "1.0.196", features = ["derive"] }

mutiny-server/src/extractor.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use async_trait::async_trait;
2+
use axum::extract::{rejection::FormRejection, FromRequest, Request};
3+
use axum::http::StatusCode;
4+
use axum::Json;
5+
use serde_json::{json, Value};
6+
7+
pub struct Form<T>(pub T);
8+
9+
#[async_trait]
10+
impl<S, T> FromRequest<S> for Form<T>
11+
where
12+
axum::Form<T>: FromRequest<S, Rejection = FormRejection>,
13+
S: Send + Sync,
14+
{
15+
type Rejection = (StatusCode, Json<Value>);
16+
17+
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
18+
let (parts, body) = req.into_parts();
19+
20+
let request = Request::from_parts(parts, body);
21+
22+
match axum::Form::<T>::from_request(request, state).await {
23+
Ok(value) => Ok(Self(value.0)),
24+
Err(rejection) => {
25+
let err_payload = json!({
26+
"error": rejection.body_text()
27+
});
28+
29+
Err((StatusCode::BAD_REQUEST, Json(err_payload)))
30+
}
31+
}
32+
}
33+
}

mutiny-server/src/main.rs

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#![allow(incomplete_features)]
22

33
mod config;
4-
mod sled;
4+
mod extractor;
55
mod routes;
6+
mod sled;
67

78
use crate::config::Config;
89
use crate::sled::SledStorage;
@@ -13,7 +14,7 @@ use bitcoin::bip32::ExtendedPrivKey;
1314
use clap::Parser;
1415
use log::{debug, info};
1516
use mutiny_core::storage::MutinyStorage;
16-
use mutiny_core::{generate_seed, MutinyWalletBuilder, MutinyWalletConfig};
17+
use mutiny_core::{generate_seed, MutinyWalletBuilder, MutinyWalletConfigBuilder};
1718
use shutdown::Shutdown;
1819
use std::time::Duration;
1920

@@ -41,18 +42,22 @@ async fn main() -> anyhow::Result<()> {
4142
let seed = mnemonic.to_seed("");
4243
let xprivkey = ExtendedPrivKey::new_master(network, &seed).unwrap();
4344

44-
let wallet_config = MutinyWalletConfig::new(
45-
xprivkey,
46-
network,
47-
config.esplora_url,
48-
config.rgs_url,
49-
config.lsp_url,
50-
);
45+
let mut config_builder = MutinyWalletConfigBuilder::new(xprivkey).with_network(network);
46+
if let Some(url) = config.esplora_url {
47+
config_builder.with_user_esplora_url(url);
48+
}
49+
if let Some(url) = config.rgs_url {
50+
config_builder.with_user_rgs_url(url);
51+
}
52+
if let Some(url) = config.lsp_url {
53+
config_builder.with_lsp_url(url);
54+
}
55+
let wallet_config = config_builder.build();
5156

5257
debug!("Initializing wallet...");
53-
let wallet = MutinyWalletBuilder::new(xprivkey, storage).with_config(wallet_config).build().await?;
54-
55-
let listener = tokio::net::TcpListener::bind(format!("{}:{}", config.bind, config.port))
58+
let wallet = MutinyWalletBuilder::new(xprivkey, storage)
59+
.with_config(wallet_config)
60+
.build()
5661
.await?;
5762

5863
debug!("Wallet initialized!");
@@ -61,17 +66,23 @@ async fn main() -> anyhow::Result<()> {
6166
mutiny_wallet: wallet.clone(),
6267
};
6368

64-
let server_router = Router::new()
65-
.route("/newaddress", get(routes::new_address))
66-
.route("/sendtoaddress", post(routes::send_to_address))
67-
.route("/openchannel", post(routes::open_channel))
68-
.route("/invoice", post(routes::create_invoice))
69-
.route("/payinvoice", post(routes::pay_invoice))
70-
.route("/balance", get(routes::get_balance))
71-
.fallback(fallback)
72-
.layer(Extension(state.clone()));
69+
tokio::spawn(async move {
70+
let server_router = Router::new()
71+
.route("/newaddress", get(routes::new_address))
72+
.route("/sendtoaddress", post(routes::send_to_address))
73+
.route("/openchannel", post(routes::open_channel))
74+
.route("/createinvoice", post(routes::create_invoice))
75+
.route("/payinvoice", post(routes::pay_invoice))
76+
.route("/balance", get(routes::get_balance))
77+
.fallback(fallback)
78+
.layer(Extension(state.clone()));
79+
80+
let listener = tokio::net::TcpListener::bind(format!("{}:{}", config.bind, config.port))
81+
.await
82+
.expect("failed to parse bind/port");
7383

74-
axum::serve(listener, server_router).await.unwrap();
84+
axum::serve(listener, server_router).await.unwrap();
85+
});
7586

7687
// wait for shutdown hook
7788
shutdown.recv().await;

0 commit comments

Comments
 (0)