Pārlūkot izejas kodu

feat: wait invoice is stream of request_lookup_id

thesimplekid 8 mēneši atpakaļ
vecāks
revīzija
8b775cb7f1

+ 2 - 6
crates/cdk-cln/src/lib.rs

@@ -56,7 +56,7 @@ impl MintLightning for Cln {
 
     async fn wait_any_invoice(
         &self,
-    ) -> Result<Pin<Box<dyn Stream<Item = Bolt11Invoice> + Send>>, Self::Err> {
+    ) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err> {
         let last_pay_index = self.get_last_pay_index().await?;
         let cln_client = cln_rpc::ClnRpc::new(&self.rpc_socket).await?;
 
@@ -86,11 +86,7 @@ impl MintLightning for Cln {
 
                     last_pay_idx = invoice.pay_index;
 
-                    if let Some(bolt11) = invoice.bolt11 {
-                        if let Ok(invoice) = Bolt11Invoice::from_str(&bolt11) {
-                            break Some((invoice, (cln_client, last_pay_idx)));
-                        }
-                    }
+                    break Some((invoice.label, (cln_client, last_pay_idx)));
                 }
             },
         )

+ 8 - 4
crates/cdk-mintd/src/main.rs

@@ -177,9 +177,9 @@ async fn main() -> anyhow::Result<()> {
         loop {
             match ln.wait_any_invoice().await {
                 Ok(mut stream) => {
-                    while let Some(invoice) = stream.next().await {
+                    while let Some(request_lookup_id) = stream.next().await {
                         if let Err(err) =
-                            handle_paid_invoice(Arc::clone(&mint), &invoice.to_string()).await
+                            handle_paid_invoice(Arc::clone(&mint), &request_lookup_id).await
                         {
                             tracing::warn!("{:?}", err);
                         }
@@ -201,8 +201,12 @@ async fn main() -> anyhow::Result<()> {
 }
 
 /// Update mint quote when called for a paid invoice
-async fn handle_paid_invoice(mint: Arc<Mint>, request: &str) -> Result<()> {
-    if let Ok(Some(mint_quote)) = mint.localstore.get_mint_quote_by_request(request).await {
+async fn handle_paid_invoice(mint: Arc<Mint>, request_lookup_id: &str) -> Result<()> {
+    if let Ok(Some(mint_quote)) = mint
+        .localstore
+        .get_mint_quote_by_request_lookup_id(request_lookup_id)
+        .await
+    {
         mint.localstore
             .update_mint_quote_state(&mint_quote.id, cdk::nuts::MintQuoteState::Paid)
             .await?;

+ 16 - 0
crates/cdk-redb/src/mint/mod.rs

@@ -331,6 +331,22 @@ impl MintDatabase for MintRedbDatabase {
         Ok(quote)
     }
 
+    async fn get_mint_quote_by_request_lookup_id(
+        &self,
+        request_lookup_id: &str,
+    ) -> Result<Option<MintQuote>, Self::Err> {
+        let quotes = self.get_mint_quotes().await?;
+
+        let quote = quotes
+            .into_iter()
+            .filter(|q| q.request_lookup_id.eq(request_lookup_id))
+            .collect::<Vec<MintQuote>>()
+            .first()
+            .cloned();
+
+        Ok(quote)
+    }
+
     async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err> {
         let db = self.db.lock().await;
         let read_txn = db.begin_read().map_err(Error::from)?;

+ 5 - 2
crates/cdk-sqlite/src/mint/migrations/20240703122347_request_lookup_id.sql

@@ -1,2 +1,5 @@
-ALTER TABLE mint_quote ADD request_lookup_id TEXT;
-ALTER TABLE melt_quote ADD request_lookup_id TEXT;
+ALTER TABLE mint_quote ADD request_lookup_id TEXT UNIQUE;
+ALTER TABLE melt_quote ADD request_lookup_id TEXT UNIQUE;
+
+CREATE INDEX IF NOT EXISTS mint_quote_request_lookup_id_index ON mint_quote(request_lookup_id);
+CREATE INDEX IF NOT EXISTS melt_quote_request_lookup_id_index ON melt_quote(request_lookup_id);

+ 26 - 0
crates/cdk-sqlite/src/mint/mod.rs

@@ -198,6 +198,32 @@ WHERE request=?;
 
         Ok(Some(sqlite_row_to_mint_quote(rec)?))
     }
+
+    async fn get_mint_quote_by_request_lookup_id(
+        &self,
+        request_lookup_id: &str,
+    ) -> Result<Option<MintQuote>, Self::Err> {
+        let rec = sqlx::query(
+            r#"
+SELECT *
+FROM mint_quote
+WHERE request_lookup_id=?;
+        "#,
+        )
+        .bind(request_lookup_id)
+        .fetch_one(&self.pool)
+        .await;
+
+        let rec = match rec {
+            Ok(rec) => rec,
+            Err(err) => match err {
+                sqlx::Error::RowNotFound => return Ok(None),
+                _ => return Err(Error::SQLX(err).into()),
+            },
+        };
+
+        Ok(Some(sqlite_row_to_mint_quote(rec)?))
+    }
     async fn update_mint_quote_state(
         &self,
         quote_id: &str,

+ 16 - 0
crates/cdk/src/cdk_database/mint_memory.rs

@@ -128,6 +128,22 @@ impl MintDatabase for MintMemoryDatabase {
 
         Ok(current_state)
     }
+
+    async fn get_mint_quote_by_request_lookup_id(
+        &self,
+        request: &str,
+    ) -> Result<Option<MintQuote>, Self::Err> {
+        let quotes = self.get_mint_quotes().await?;
+
+        let quote = quotes
+            .into_iter()
+            .filter(|q| q.request_lookup_id.eq(request))
+            .collect::<Vec<MintQuote>>()
+            .first()
+            .cloned();
+
+        Ok(quote)
+    }
     async fn get_mint_quote_by_request(
         &self,
         request: &str,

+ 5 - 0
crates/cdk/src/cdk_database/mod.rs

@@ -185,6 +185,11 @@ pub trait MintDatabase {
         &self,
         request: &str,
     ) -> Result<Option<MintMintQuote>, Self::Err>;
+    /// Get all [`MintMintQuote`]s
+    async fn get_mint_quote_by_request_lookup_id(
+        &self,
+        request_lookup_id: &str,
+    ) -> Result<Option<MintMintQuote>, Self::Err>;
     /// Get Mint Quotes
     async fn get_mint_quotes(&self) -> Result<Vec<MintMintQuote>, Self::Err>;
     /// Remove [`MintMintQuote`]

+ 2 - 1
crates/cdk/src/cdk_lightning/mod.rs

@@ -64,9 +64,10 @@ pub trait MintLightning {
     ) -> Result<PayInvoiceResponse, Self::Err>;
 
     /// Listen for invoices to be paid to the mint
+    /// Returns a stream of request_lookup_id once invoices are paid
     async fn wait_any_invoice(
         &self,
-    ) -> Result<Pin<Box<dyn Stream<Item = Bolt11Invoice> + Send>>, Self::Err>;
+    ) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err>;
 
     /// Check the status of an incoming payment
     async fn check_invoice_status(