Skip to content

Commit

Permalink
Properly set gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
benthecarman committed Mar 22, 2024
1 parent 662d0ca commit 86979f6
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 11 deletions.
16 changes: 8 additions & 8 deletions src/lnurlp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ pub async fn lnurl_callback(

let invoice_index = user.invoice_index;

let gateway = state
.mm
.get_gateway(&federation_id)
.await
.ok_or(anyhow!("Not gateway configured for federation"))?;

let (op_id, pr, preimage) = ln
.create_bolt11_invoice_for_user_tweaked(
Amount::from_msats(params.amount),
Expand All @@ -103,7 +109,7 @@ pub async fn lnurl_callback(
user.pubkey().public_key(Parity::Odd), // todo is this parity correct / easy to work with?
invoice_index as u64,
(),
None, // todo set gateway properly
Some(gateway),
)
.await?;

Expand Down Expand Up @@ -136,13 +142,7 @@ pub async fn lnurl_callback(
.await
.expect("subscribing to a just created operation can't fail");

spawn_invoice_subscription(
state.clone(),
created_invoice,
user.clone(),
subscription,
)
.await;
spawn_invoice_subscription(state.clone(), created_invoice, user.clone(), subscription).await;

let verify_url = format!("{}/lnurlp/{}/verify/{}", state.domain, user.name, op_id);

Expand Down
77 changes: 74 additions & 3 deletions src/mint.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use async_trait::async_trait;
use fedimint_client::ClientHandleArc;
use fedimint_core::{api::InviteCode, config::FederationId};
use fedimint_ln_client::LightningClientModule;
use fedimint_ln_common::LightningGateway;
use log::error;
use std::collections::HashMap;
use std::{path::PathBuf, sync::Arc};
use tokio::sync::RwLock;

Expand All @@ -14,11 +18,14 @@ pub(crate) trait MultiMintWrapperTrait {
async fn check_has_federation(&self, id: FederationId) -> bool;
async fn get_federation_client(&self, id: FederationId) -> Option<ClientHandleArc>;
async fn register_new_federation(&self, invite_code: InviteCode) -> anyhow::Result<()>;
async fn get_gateway(&self, id: &FederationId) -> Option<LightningGateway>;
}

#[derive(Clone)]
struct MultiMintWrapper {
fm: Arc<RwLock<MultiMint>>,
/// Our preferred lightning gateway for each federation
gateways: Arc<RwLock<HashMap<FederationId, LightningGateway>>>,
}

#[async_trait]
Expand All @@ -32,20 +39,84 @@ impl MultiMintWrapperTrait for MultiMintWrapper {
}

async fn register_new_federation(&self, invite_code: InviteCode) -> anyhow::Result<()> {
self.fm
let id = self
.fm
.write()
.await
.register_new(invite_code, None)
.await?;

let client = self
.get_federation_client(id)
.await
.expect("just registered");

if let Some(gateway) = select_gateway(&client).await {
self.gateways.write().await.insert(id, gateway);
} else {
error!("No suitable gateway found for federation {id}");
}

Ok(())
}

async fn get_gateway(&self, id: &FederationId) -> Option<LightningGateway> {
let lock = self.gateways.read().await;
lock.get(id).cloned()
}
}

pub(crate) async fn setup_multimint(
db_path: PathBuf,
) -> anyhow::Result<Arc<dyn MultiMintWrapperTrait + Send + Sync>> {
let fm = Arc::new(RwLock::new(MultiMint::new(db_path).await?));
let mmw = MultiMintWrapper { fm };
let mm = MultiMint::new(db_path).await?;

let clients = mm.clients.lock().await;
let mut gateways = HashMap::with_capacity(clients.len());

// select gateway for each federation
for (id, client) in clients.iter() {
match select_gateway(client).await {
Some(gateway) => {
gateways.insert(*id, gateway);
}
None => {
error!("No suitable gateway found for federation {id}");
}
}
}
drop(clients);

let mmw = MultiMintWrapper {
fm: Arc::new(RwLock::new(mm)),
gateways: Arc::new(RwLock::new(HashMap::new())),
};

Ok(Arc::new(mmw))
}

pub(crate) async fn select_gateway(client: &ClientHandleArc) -> Option<LightningGateway> {
let ln = client.get_first_module::<LightningClientModule>();
let mut gateway_id = None;
for gateway in ln.list_gateways().await {
// first try to find a vetted gateway
if gateway.vetted {
gateway_id = Some(gateway.info.gateway_id);
break; // if vetted gateway found, use it
}

// if no vetted gateway found, try to find a gateway with reasonable fees
let fees = gateway.info.fees;
if fees.base_msat >= 1_000 && fees.proportional_millionths >= 100 {
gateway_id = Some(gateway.info.gateway_id);
}
}

if let Some(gateway_id) = gateway_id {
if let Some(gateway) = ln.select_gateway(&gateway_id).await {
return Some(gateway);
}
}

None
}

0 comments on commit 86979f6

Please sign in to comment.