-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #532 from thesimplekid/refactor_itests
Refactor itests
- Loading branch information
Showing
10 changed files
with
334 additions
and
440 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use std::sync::Arc; | ||
|
||
use anyhow::Result; | ||
use axum::Router; | ||
use cdk::mint::Mint; | ||
use tokio::sync::Notify; | ||
use tower_http::cors::CorsLayer; | ||
|
||
pub async fn start_mint(addr: &str, port: u16, mint: Mint) -> Result<()> { | ||
let mint_arc = Arc::new(mint); | ||
|
||
let v1_service = cdk_axum::create_mint_router(Arc::clone(&mint_arc)) | ||
.await | ||
.unwrap(); | ||
|
||
let mint_service = Router::new() | ||
.merge(v1_service) | ||
.layer(CorsLayer::permissive()); | ||
|
||
let mint = Arc::clone(&mint_arc); | ||
|
||
let shutdown = Arc::new(Notify::new()); | ||
|
||
tokio::spawn({ | ||
let shutdown = Arc::clone(&shutdown); | ||
async move { mint.wait_for_paid_invoices(shutdown).await } | ||
}); | ||
|
||
println!("Staring Axum server"); | ||
axum::Server::bind(&format!("{}:{}", addr, port).as_str().parse().unwrap()) | ||
.serve(mint_service.into_make_service()) | ||
.await?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
use std::collections::{HashMap, HashSet}; | ||
use std::fmt::{Debug, Formatter}; | ||
use std::str::FromStr; | ||
use std::sync::Arc; | ||
|
||
use async_trait::async_trait; | ||
use bip39::Mnemonic; | ||
use cdk::amount::SplitTarget; | ||
use cdk::cdk_database::mint_memory::MintMemoryDatabase; | ||
use cdk::cdk_database::WalletMemoryDatabase; | ||
use cdk::mint::{FeeReserve, MintBuilder, MintMeltLimits}; | ||
use cdk::nuts::nut00::ProofsMethods; | ||
use cdk::nuts::{ | ||
CheckStateRequest, CheckStateResponse, CurrencyUnit, Id, KeySet, KeysetResponse, | ||
MeltBolt11Request, MeltQuoteBolt11Request, MeltQuoteBolt11Response, MintBolt11Request, | ||
MintBolt11Response, MintInfo, MintQuoteBolt11Request, MintQuoteBolt11Response, PaymentMethod, | ||
RestoreRequest, RestoreResponse, SwapRequest, SwapResponse, | ||
}; | ||
use cdk::util::unix_time; | ||
use cdk::wallet::client::MintConnector; | ||
use cdk::wallet::Wallet; | ||
use cdk::{Amount, Error, Mint}; | ||
use cdk_fake_wallet::FakeWallet; | ||
use tokio::sync::Notify; | ||
use uuid::Uuid; | ||
|
||
use crate::wait_for_mint_to_be_paid; | ||
|
||
pub struct DirectMintConnection { | ||
pub mint: Arc<Mint>, | ||
} | ||
|
||
impl DirectMintConnection { | ||
pub fn new(mint: Arc<Mint>) -> Self { | ||
Self { mint } | ||
} | ||
} | ||
|
||
impl Debug for DirectMintConnection { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||
write!( | ||
f, | ||
"DirectMintConnection {{ mint_info: {:?} }}", | ||
self.mint.config.mint_info() | ||
) | ||
} | ||
} | ||
|
||
/// Implements the generic [MintConnector] (i.e. use the interface that expects to communicate | ||
/// to a generic mint, where we don't know that quote ID's are [Uuid]s) for [DirectMintConnection], | ||
/// where we know we're dealing with a mint that uses [Uuid]s for quotes. | ||
/// Convert the requests and responses between the [String] and [Uuid] variants as necessary. | ||
#[async_trait] | ||
impl MintConnector for DirectMintConnection { | ||
async fn get_mint_keys(&self) -> Result<Vec<KeySet>, Error> { | ||
self.mint.pubkeys().await.map(|pks| pks.keysets) | ||
} | ||
|
||
async fn get_mint_keyset(&self, keyset_id: Id) -> Result<KeySet, Error> { | ||
self.mint | ||
.keyset(&keyset_id) | ||
.await | ||
.and_then(|res| res.ok_or(Error::UnknownKeySet)) | ||
} | ||
|
||
async fn get_mint_keysets(&self) -> Result<KeysetResponse, Error> { | ||
self.mint.keysets().await | ||
} | ||
|
||
async fn post_mint_quote( | ||
&self, | ||
request: MintQuoteBolt11Request, | ||
) -> Result<MintQuoteBolt11Response<String>, Error> { | ||
self.mint | ||
.get_mint_bolt11_quote(request) | ||
.await | ||
.map(Into::into) | ||
} | ||
|
||
async fn get_mint_quote_status( | ||
&self, | ||
quote_id: &str, | ||
) -> Result<MintQuoteBolt11Response<String>, Error> { | ||
let quote_id_uuid = Uuid::from_str(quote_id).unwrap(); | ||
self.mint | ||
.check_mint_quote("e_id_uuid) | ||
.await | ||
.map(Into::into) | ||
} | ||
|
||
async fn post_mint( | ||
&self, | ||
request: MintBolt11Request<String>, | ||
) -> Result<MintBolt11Response, Error> { | ||
let request_uuid = request.try_into().unwrap(); | ||
self.mint.process_mint_request(request_uuid).await | ||
} | ||
|
||
async fn post_melt_quote( | ||
&self, | ||
request: MeltQuoteBolt11Request, | ||
) -> Result<MeltQuoteBolt11Response<String>, Error> { | ||
self.mint | ||
.get_melt_bolt11_quote(&request) | ||
.await | ||
.map(Into::into) | ||
} | ||
|
||
async fn get_melt_quote_status( | ||
&self, | ||
quote_id: &str, | ||
) -> Result<MeltQuoteBolt11Response<String>, Error> { | ||
let quote_id_uuid = Uuid::from_str(quote_id).unwrap(); | ||
self.mint | ||
.check_melt_quote("e_id_uuid) | ||
.await | ||
.map(Into::into) | ||
} | ||
|
||
async fn post_melt( | ||
&self, | ||
request: MeltBolt11Request<String>, | ||
) -> Result<MeltQuoteBolt11Response<String>, Error> { | ||
let request_uuid = request.try_into().unwrap(); | ||
self.mint.melt_bolt11(&request_uuid).await.map(Into::into) | ||
} | ||
|
||
async fn post_swap(&self, swap_request: SwapRequest) -> Result<SwapResponse, Error> { | ||
self.mint.process_swap_request(swap_request).await | ||
} | ||
|
||
async fn get_mint_info(&self) -> Result<MintInfo, Error> { | ||
Ok(self.mint.mint_info().clone().time(unix_time())) | ||
} | ||
|
||
async fn post_check_state( | ||
&self, | ||
request: CheckStateRequest, | ||
) -> Result<CheckStateResponse, Error> { | ||
self.mint.check_state(&request).await | ||
} | ||
|
||
async fn post_restore(&self, request: RestoreRequest) -> Result<RestoreResponse, Error> { | ||
self.mint.restore(request).await | ||
} | ||
} | ||
|
||
pub async fn create_and_start_test_mint() -> anyhow::Result<Arc<Mint>> { | ||
let mut mint_builder = MintBuilder::new(); | ||
|
||
let database = MintMemoryDatabase::default(); | ||
|
||
mint_builder = mint_builder.with_localstore(Arc::new(database)); | ||
|
||
let fee_reserve = FeeReserve { | ||
min_fee_reserve: 1.into(), | ||
percent_fee_reserve: 1.0, | ||
}; | ||
|
||
let ln_fake_backend = Arc::new(FakeWallet::new( | ||
fee_reserve.clone(), | ||
HashMap::default(), | ||
HashSet::default(), | ||
0, | ||
)); | ||
|
||
mint_builder = mint_builder.add_ln_backend( | ||
CurrencyUnit::Sat, | ||
PaymentMethod::Bolt11, | ||
MintMeltLimits::default(), | ||
ln_fake_backend, | ||
); | ||
|
||
let mnemonic = Mnemonic::generate(12)?; | ||
|
||
mint_builder = mint_builder | ||
.with_name("pure test mint".to_string()) | ||
.with_mint_url("http://aa".to_string()) | ||
.with_description("pure test mint".to_string()) | ||
.with_quote_ttl(10000, 10000) | ||
.with_seed(mnemonic.to_seed_normalized("").to_vec()); | ||
|
||
let mint = mint_builder.build().await?; | ||
|
||
let mint_arc = Arc::new(mint); | ||
|
||
let mint_arc_clone = Arc::clone(&mint_arc); | ||
let shutdown = Arc::new(Notify::new()); | ||
tokio::spawn({ | ||
let shutdown = Arc::clone(&shutdown); | ||
async move { mint_arc_clone.wait_for_paid_invoices(shutdown).await } | ||
}); | ||
|
||
Ok(mint_arc) | ||
} | ||
|
||
pub fn create_test_wallet_for_mint(mint: Arc<Mint>) -> anyhow::Result<Arc<Wallet>> { | ||
let connector = DirectMintConnection::new(mint); | ||
|
||
let seed = Mnemonic::generate(12)?.to_seed_normalized(""); | ||
let mint_url = connector.mint.config.mint_url().to_string(); | ||
let unit = CurrencyUnit::Sat; | ||
let localstore = WalletMemoryDatabase::default(); | ||
let mut wallet = Wallet::new(&mint_url, unit, Arc::new(localstore), &seed, None)?; | ||
|
||
wallet.set_client(connector); | ||
|
||
Ok(Arc::new(wallet)) | ||
} | ||
|
||
/// Creates a mint quote for the given amount and checks its state in a loop. Returns when | ||
/// amount is minted. | ||
pub async fn fund_wallet(wallet: Arc<Wallet>, amount: u64) -> anyhow::Result<Amount> { | ||
let desired_amount = Amount::from(amount); | ||
let quote = wallet.mint_quote(desired_amount, None).await?; | ||
|
||
wait_for_mint_to_be_paid(&wallet, "e.id).await?; | ||
|
||
Ok(wallet | ||
.mint("e.id, SplitTarget::default(), None) | ||
.await? | ||
.total_amount()?) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.