Skip to content

Commit

Permalink
feat: store quotes in db
Browse files Browse the repository at this point in the history
  • Loading branch information
ngutech21 committed Dec 4, 2023
1 parent 4cff653 commit 24c443d
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 11 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ typos-fix-all:
# format code, check typos and run tests
final-check:
cargo fmt --all
typos
just typos
cargo test
build-wasm
just build-wasm

#run coverage
coverage:
Expand Down Expand Up @@ -98,8 +98,7 @@ build-docker:


# build flutter web-app in flutter/build/web
build-web:
build-wasm
build-web: build-wasm
cd flutter && \
flutter clean && \
RUSTFLAGS="-C target-feature=+atomics,+bulk-memory,+mutable-globals" RUSTUP_TOOLCHAIN=nightly wasm-pack build -t no-modules -d $(pwd)/web/pkg --no-typescript --out-name native --dev native -- -Z build-std=std,panic_abort && \
Expand Down
1 change: 1 addition & 0 deletions moksha-mint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ url = "2.4.1"
dotenvy = "0.15.7"
envy = "0.4.2"
fedimint-tonic-lnd = { version = "0.1.3", features = ["lightningrpc"] }
uuid = { version = "1.6.1", features = ["serde", "v4"] }

[dev-dependencies]
tempfile = "3.8.1"
Expand Down
71 changes: 69 additions & 2 deletions moksha-mint/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use moksha_core::proof::Proofs;
use rocksdb::DB;
use serde::{de::DeserializeOwned, Serialize};

use crate::{error::MokshaMintError, model::Invoice};
use crate::{
error::MokshaMintError,
model::{Invoice, Quote},
};
#[cfg(test)]
use mockall::automock;

Expand All @@ -18,6 +21,7 @@ pub struct RocksDB {
pub enum DbKeyPrefix {
UsedProofs = 0x01,
PendingInvoices = 0x02,
Quote = 0x03,
}

#[cfg_attr(test, automock)]
Expand All @@ -29,6 +33,11 @@ pub trait Database {
fn get_pending_invoices(&self) -> Result<HashMap<String, Invoice>, MokshaMintError>;
fn add_pending_invoice(&self, key: String, invoice: Invoice) -> Result<(), MokshaMintError>;
fn remove_pending_invoice(&self, key: String) -> Result<(), MokshaMintError>;

fn get_quotes(&self) -> Result<HashMap<String, Quote>, MokshaMintError>;
fn get_quote(&self, key: String) -> Result<Quote, MokshaMintError>;
fn add_quote(&self, key: String, quote: Quote) -> Result<(), MokshaMintError>;
fn remove_quote(&self, key: String) -> Result<(), MokshaMintError>;
}

impl RocksDB {
Expand Down Expand Up @@ -67,6 +76,7 @@ impl RocksDB {
}
}

// FIXME remove boilerplate code
impl Database for RocksDB {
fn add_used_proofs(&self, proofs: &Proofs) -> Result<(), MokshaMintError> {
let used_proofs = self.get_used_proofs()?;
Expand Down Expand Up @@ -126,6 +136,45 @@ impl Database for RocksDB {

Ok(())
}

fn get_quotes(&self) -> Result<HashMap<String, Quote>, MokshaMintError> {
self.get_serialized::<HashMap<String, Quote>>(DbKeyPrefix::Quote)
.map(|maybe_quotes| maybe_quotes.unwrap_or_default())
}

fn add_quote(&self, key: String, quote: Quote) -> Result<(), MokshaMintError> {
let quotes = self.get_quotes();

quotes.and_then(|mut quotes| {
quotes.insert(key, quote);
self.put_serialized(DbKeyPrefix::Quote, &quotes)
})?;

Ok(())
}

fn remove_quote(&self, key: String) -> Result<(), MokshaMintError> {
let invoices = self.get_quotes();

invoices.and_then(|mut quotes| {
quotes.remove(key.as_str());
self.put_serialized(DbKeyPrefix::Quote, &quotes)
})?;

Ok(())
}

fn get_quote(&self, key: String) -> Result<Quote, MokshaMintError> {
let invoices = self
.get_serialized::<HashMap<String, Quote>>(DbKeyPrefix::Quote)
.map(|maybe_quotes| maybe_quotes.unwrap_or_default());
invoices.and_then(|quotes| {
quotes
.get(&key)
.cloned()
.ok_or_else(|| MokshaMintError::InvalidQuote(key))
})
}
}

#[cfg(test)]
Expand All @@ -137,7 +186,10 @@ mod tests {
proof::{Proof, Proofs},
};

use crate::{database::Database, model::Invoice};
use crate::{
database::Database,
model::{Invoice, Quote},
};

#[test]
fn test_write_proofs() -> anyhow::Result<()> {
Expand Down Expand Up @@ -204,4 +256,19 @@ mod tests {
assert_eq!(invoice, lookup_invoice);
Ok(())
}

#[test]
fn test_read_write_quotes() -> anyhow::Result<()> {
let tmp = tempfile::tempdir()?;
let tmp_dir = tmp.path().to_str().expect("Could not create tmp dir");
let db = super::RocksDB::new(tmp_dir.to_owned());

let quote = Quote::new("12345678".to_owned());
let key = quote.quote_id.to_string();
db.add_quote(key.clone(), quote.clone())?;
let lookup_quote = db.get_quote(key.to_string())?;

assert_eq!(quote, lookup_quote);
Ok(())
}
}
3 changes: 3 additions & 0 deletions moksha-mint/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ pub enum MokshaMintError {

#[error("Lightning Error {0}")]
Lightning(#[from] LightningError),

#[error("Invalid quote {0}")]
InvalidQuote(String),
}

impl IntoResponse for MokshaMintError {
Expand Down
16 changes: 16 additions & 0 deletions moksha-mint/src/model.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Debug, Serialize, Deserialize)]
pub struct GetMintQuery {
Expand Down Expand Up @@ -45,3 +46,18 @@ pub struct CreateInvoiceParams {
pub webhook: Option<String>,
pub internal: Option<bool>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Quote {
pub quote_id: Uuid,
pub payment_request: String,
}

impl Quote {
pub fn new(payment_request: String) -> Self {
Self {
quote_id: Uuid::new_v4(),
payment_request,
}
}
}
21 changes: 16 additions & 5 deletions moksha-mint/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use axum::{routing::get, Json};
use moksha_core::keyset::{Keysets, V1Keysets};

use crate::mint::Mint;
use crate::model::{GetMintQuery, PostMintQuery};
use crate::model::{GetMintQuery, PostMintQuery, Quote};
use moksha_core::primitives::{
CheckFeesRequest, CheckFeesResponse, CurrencyUnit, KeyResponse, KeysResponse, MintInfoResponse,
PaymentRequest, PostMeltBolt11Request, PostMeltBolt11Response, PostMeltQuoteBolt11Request,
Expand Down Expand Up @@ -271,9 +271,14 @@ async fn post_mint_quote_bolt11(
Json(request): Json<PostMintQuoteBolt11Request>,
) -> Result<Json<PostMintQuoteBolt11Response>, MokshaMintError> {
// FIXME check currency unit
let (pr, hash) = mint.create_invoice(request.amount).await?;
let (pr, _hash) = mint.create_invoice(request.amount).await?;

let quote = Quote::new(pr.clone());
let quote_id = quote.quote_id.to_string();
mint.db.add_quote(quote_id.clone(), quote)?;

Ok(Json(PostMintQuoteBolt11Response {
quote: hash,
quote: quote_id,
request: pr,
}))
}
Expand All @@ -282,8 +287,14 @@ async fn post_mint_bolt11(
State(mint): State<Mint>,
Json(request): Json<PostMintBolt11Request>,
) -> Result<Json<PostMintBolt11Response>, MokshaMintError> {
// FIXME don't use hash as quote
let signatures = mint.mint_tokens(request.quote, &request.outputs).await?;
let quotes = &mint.db.get_quotes()?;
let quote = quotes
.get(request.quote.as_str())
.ok_or_else(|| crate::error::MokshaMintError::InvalidQuote(request.quote.clone()))?;

let signatures = mint
.mint_tokens(quote.payment_request.clone(), &request.outputs)
.await?;
Ok(Json(PostMintBolt11Response { signatures }))
}

Expand Down

0 comments on commit 24c443d

Please sign in to comment.