|
@@ -2,21 +2,22 @@ use std::sync::Arc;
|
|
|
|
|
|
use anyhow::{bail, Result};
|
|
use anyhow::{bail, Result};
|
|
use bip39::Mnemonic;
|
|
use bip39::Mnemonic;
|
|
|
|
+use cashu::Amount;
|
|
use cdk::amount::SplitTarget;
|
|
use cdk::amount::SplitTarget;
|
|
use cdk::nuts::nut00::ProofsMethods;
|
|
use cdk::nuts::nut00::ProofsMethods;
|
|
use cdk::nuts::{
|
|
use cdk::nuts::{
|
|
CurrencyUnit, MeltBolt11Request, MeltQuoteState, MintBolt11Request, PreMintSecrets, Proofs,
|
|
CurrencyUnit, MeltBolt11Request, MeltQuoteState, MintBolt11Request, PreMintSecrets, Proofs,
|
|
SecretKey, State, SwapRequest,
|
|
SecretKey, State, SwapRequest,
|
|
};
|
|
};
|
|
-use cdk::wallet::client::{HttpClient, MintConnector};
|
|
|
|
-use cdk::wallet::Wallet;
|
|
|
|
|
|
+use cdk::wallet::types::TransactionDirection;
|
|
|
|
+use cdk::wallet::{HttpClient, MintConnector, Wallet};
|
|
use cdk_fake_wallet::{create_fake_invoice, FakeInvoiceDescription};
|
|
use cdk_fake_wallet::{create_fake_invoice, FakeInvoiceDescription};
|
|
use cdk_integration_tests::{attempt_to_swap_pending, wait_for_mint_to_be_paid};
|
|
use cdk_integration_tests::{attempt_to_swap_pending, wait_for_mint_to_be_paid};
|
|
use cdk_sqlite::wallet::memory;
|
|
use cdk_sqlite::wallet::memory;
|
|
|
|
|
|
const MINT_URL: &str = "http://127.0.0.1:8086";
|
|
const MINT_URL: &str = "http://127.0.0.1:8086";
|
|
|
|
|
|
-// If both pay and check return pending input proofs should remain pending
|
|
|
|
|
|
+/// Tests that when both pay and check return pending status, input proofs should remain pending
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_tokens_pending() -> Result<()> {
|
|
async fn test_fake_tokens_pending() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -55,8 +56,8 @@ async fn test_fake_tokens_pending() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-// If the pay error fails and the check returns unknown or failed
|
|
|
|
-// The inputs proofs should be unset as spending
|
|
|
|
|
|
+/// Tests that if the pay error fails and the check returns unknown or failed,
|
|
|
|
+/// the input proofs should be unset as spending (returned to unspent state)
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_melt_payment_fail() -> Result<()> {
|
|
async fn test_fake_melt_payment_fail() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -118,8 +119,8 @@ async fn test_fake_melt_payment_fail() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-// When both the pay_invoice and check_invoice both fail
|
|
|
|
-// the proofs should remain as pending
|
|
|
|
|
|
+/// Tests that when both the pay_invoice and check_invoice both fail,
|
|
|
|
+/// the proofs should remain in pending state
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_melt_payment_fail_and_check() -> Result<()> {
|
|
async fn test_fake_melt_payment_fail_and_check() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -163,8 +164,8 @@ async fn test_fake_melt_payment_fail_and_check() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-// In the case that the ln backend returns a failed status but does not error
|
|
|
|
-// The mint should do a second check, then remove proofs from pending
|
|
|
|
|
|
+/// Tests that when the ln backend returns a failed status but does not error,
|
|
|
|
+/// the mint should do a second check, then remove proofs from pending state
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_melt_payment_return_fail_status() -> Result<()> {
|
|
async fn test_fake_melt_payment_return_fail_status() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -223,8 +224,8 @@ async fn test_fake_melt_payment_return_fail_status() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-// In the case that the ln backend returns a failed status but does not error
|
|
|
|
-// The mint should do a second check, then remove proofs from pending
|
|
|
|
|
|
+/// Tests that when the ln backend returns an error with unknown status,
|
|
|
|
+/// the mint should do a second check, then remove proofs from pending state
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_melt_payment_error_unknown() -> Result<()> {
|
|
async fn test_fake_melt_payment_error_unknown() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -283,9 +284,8 @@ async fn test_fake_melt_payment_error_unknown() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-// In the case that the ln backend returns an err
|
|
|
|
-// The mint should do a second check, that returns paid
|
|
|
|
-// Proofs should remain pending
|
|
|
|
|
|
+/// Tests that when the ln backend returns an error but the second check returns paid,
|
|
|
|
+/// proofs should remain in pending state
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_melt_payment_err_paid() -> Result<()> {
|
|
async fn test_fake_melt_payment_err_paid() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -324,6 +324,7 @@ async fn test_fake_melt_payment_err_paid() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Tests that change outputs in a melt quote are correctly handled
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_melt_change_in_quote() -> Result<()> {
|
|
async fn test_fake_melt_change_in_quote() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -342,6 +343,17 @@ async fn test_fake_melt_change_in_quote() -> Result<()> {
|
|
.mint(&mint_quote.id, SplitTarget::default(), None)
|
|
.mint(&mint_quote.id, SplitTarget::default(), None)
|
|
.await?;
|
|
.await?;
|
|
|
|
|
|
|
|
+ let transaction = wallet
|
|
|
|
+ .list_transactions(Some(TransactionDirection::Incoming))
|
|
|
|
+ .await?
|
|
|
|
+ .pop()
|
|
|
|
+ .expect("No transaction found");
|
|
|
|
+ assert_eq!(wallet.mint_url, transaction.mint_url);
|
|
|
|
+ assert_eq!(TransactionDirection::Incoming, transaction.direction);
|
|
|
|
+ assert_eq!(Amount::from(100), transaction.amount);
|
|
|
|
+ assert_eq!(Amount::from(0), transaction.fee);
|
|
|
|
+ assert_eq!(CurrencyUnit::Sat, transaction.unit);
|
|
|
|
+
|
|
let fake_description = FakeInvoiceDescription::default();
|
|
let fake_description = FakeInvoiceDescription::default();
|
|
|
|
|
|
let invoice = create_fake_invoice(9000, serde_json::to_string(&fake_description).unwrap());
|
|
let invoice = create_fake_invoice(9000, serde_json::to_string(&fake_description).unwrap());
|
|
@@ -354,13 +366,13 @@ async fn test_fake_melt_change_in_quote() -> Result<()> {
|
|
|
|
|
|
let premint_secrets = PreMintSecrets::random(keyset.id, 100.into(), &SplitTarget::default())?;
|
|
let premint_secrets = PreMintSecrets::random(keyset.id, 100.into(), &SplitTarget::default())?;
|
|
|
|
|
|
- let client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let client = HttpClient::new(MINT_URL.parse()?, None);
|
|
|
|
|
|
- let melt_request = MeltBolt11Request {
|
|
|
|
- quote: melt_quote.id.clone(),
|
|
|
|
- inputs: proofs.clone(),
|
|
|
|
- outputs: Some(premint_secrets.blinded_messages()),
|
|
|
|
- };
|
|
|
|
|
|
+ let melt_request = MeltBolt11Request::new(
|
|
|
|
+ melt_quote.id.clone(),
|
|
|
|
+ proofs.clone(),
|
|
|
|
+ Some(premint_secrets.blinded_messages()),
|
|
|
|
+ );
|
|
|
|
|
|
let melt_response = client.post_melt(melt_request).await?;
|
|
let melt_response = client.post_melt(melt_request).await?;
|
|
|
|
|
|
@@ -374,13 +386,15 @@ async fn test_fake_melt_change_in_quote() -> Result<()> {
|
|
check.sort_by(|a, b| a.amount.cmp(&b.amount));
|
|
check.sort_by(|a, b| a.amount.cmp(&b.amount));
|
|
|
|
|
|
assert_eq!(melt_change, check);
|
|
assert_eq!(melt_change, check);
|
|
|
|
+
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Tests that the correct database type is used based on environment variables
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_database_type() -> Result<()> {
|
|
async fn test_database_type() -> Result<()> {
|
|
// Get the database type and work dir from environment
|
|
// Get the database type and work dir from environment
|
|
- let db_type = std::env::var("MINT_DATABASE").expect("MINT_DATABASE env var should be set");
|
|
|
|
|
|
+ let db_type = std::env::var("CDK_MINTD_DATABASE").expect("MINT_DATABASE env var should be set");
|
|
let work_dir =
|
|
let work_dir =
|
|
std::env::var("CDK_MINTD_WORK_DIR").expect("CDK_MINTD_WORK_DIR env var should be set");
|
|
std::env::var("CDK_MINTD_WORK_DIR").expect("CDK_MINTD_WORK_DIR env var should be set");
|
|
|
|
|
|
@@ -412,6 +426,7 @@ async fn test_database_type() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Tests minting tokens with a valid witness signature
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_with_witness() -> Result<()> {
|
|
async fn test_fake_mint_with_witness() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -436,6 +451,7 @@ async fn test_fake_mint_with_witness() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Tests that minting without a witness signature fails with the correct error
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_without_witness() -> Result<()> {
|
|
async fn test_fake_mint_without_witness() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -450,7 +466,7 @@ async fn test_fake_mint_without_witness() -> Result<()> {
|
|
|
|
|
|
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?;
|
|
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?;
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
|
|
|
|
let active_keyset_id = wallet.get_active_mint_keyset().await?.id;
|
|
let active_keyset_id = wallet.get_active_mint_keyset().await?.id;
|
|
|
|
|
|
@@ -472,6 +488,7 @@ async fn test_fake_mint_without_witness() -> Result<()> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Tests that minting with an incorrect witness signature fails with the correct error
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_with_wrong_witness() -> Result<()> {
|
|
async fn test_fake_mint_with_wrong_witness() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -486,7 +503,7 @@ async fn test_fake_mint_with_wrong_witness() -> Result<()> {
|
|
|
|
|
|
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?;
|
|
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?;
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
|
|
|
|
let active_keyset_id = wallet.get_active_mint_keyset().await?.id;
|
|
let active_keyset_id = wallet.get_active_mint_keyset().await?.id;
|
|
|
|
|
|
@@ -512,6 +529,7 @@ async fn test_fake_mint_with_wrong_witness() -> Result<()> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Tests that attempting to mint more tokens than allowed by the quote fails
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_inflated() -> Result<()> {
|
|
async fn test_fake_mint_inflated() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -545,7 +563,7 @@ async fn test_fake_mint_inflated() -> Result<()> {
|
|
if let Some(secret_key) = quote_info.secret_key {
|
|
if let Some(secret_key) = quote_info.secret_key {
|
|
mint_request.sign(secret_key)?;
|
|
mint_request.sign(secret_key)?;
|
|
}
|
|
}
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
|
|
|
|
let response = http_client.post_mint(mint_request.clone()).await;
|
|
let response = http_client.post_mint(mint_request.clone()).await;
|
|
|
|
|
|
@@ -564,6 +582,7 @@ async fn test_fake_mint_inflated() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Tests that attempting to mint with multiple currency units in the same request fails
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_multiple_units() -> Result<()> {
|
|
async fn test_fake_mint_multiple_units() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -615,7 +634,7 @@ async fn test_fake_mint_multiple_units() -> Result<()> {
|
|
if let Some(secret_key) = quote_info.secret_key {
|
|
if let Some(secret_key) = quote_info.secret_key {
|
|
mint_request.sign(secret_key)?;
|
|
mint_request.sign(secret_key)?;
|
|
}
|
|
}
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
|
|
|
|
let response = http_client.post_mint(mint_request.clone()).await;
|
|
let response = http_client.post_mint(mint_request.clone()).await;
|
|
|
|
|
|
@@ -634,6 +653,7 @@ async fn test_fake_mint_multiple_units() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Tests that attempting to swap tokens with multiple currency units fails
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_multiple_unit_swap() -> Result<()> {
|
|
async fn test_fake_mint_multiple_unit_swap() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -677,12 +697,9 @@ async fn test_fake_mint_multiple_unit_swap() -> Result<()> {
|
|
let pre_mint =
|
|
let pre_mint =
|
|
PreMintSecrets::random(active_keyset_id, inputs.total_amount()?, &SplitTarget::None)?;
|
|
PreMintSecrets::random(active_keyset_id, inputs.total_amount()?, &SplitTarget::None)?;
|
|
|
|
|
|
- let swap_request = SwapRequest {
|
|
|
|
- inputs,
|
|
|
|
- outputs: pre_mint.blinded_messages(),
|
|
|
|
- };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(inputs, pre_mint.blinded_messages());
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
@@ -714,12 +731,9 @@ async fn test_fake_mint_multiple_unit_swap() -> Result<()> {
|
|
|
|
|
|
usd_outputs.append(&mut sat_outputs);
|
|
usd_outputs.append(&mut sat_outputs);
|
|
|
|
|
|
- let swap_request = SwapRequest {
|
|
|
|
- inputs,
|
|
|
|
- outputs: usd_outputs,
|
|
|
|
- };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(inputs, usd_outputs);
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
@@ -738,6 +752,7 @@ async fn test_fake_mint_multiple_unit_swap() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Tests that attempting to melt tokens with multiple currency units fails
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_multiple_unit_melt() -> Result<()> {
|
|
async fn test_fake_mint_multiple_unit_melt() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -787,13 +802,9 @@ async fn test_fake_mint_multiple_unit_melt() -> Result<()> {
|
|
let invoice = create_fake_invoice((input_amount - 1) * 1000, "".to_string());
|
|
let invoice = create_fake_invoice((input_amount - 1) * 1000, "".to_string());
|
|
let melt_quote = wallet.melt_quote(invoice.to_string(), None).await?;
|
|
let melt_quote = wallet.melt_quote(invoice.to_string(), None).await?;
|
|
|
|
|
|
- let melt_request = MeltBolt11Request {
|
|
|
|
- quote: melt_quote.id,
|
|
|
|
- inputs,
|
|
|
|
- outputs: None,
|
|
|
|
- };
|
|
|
|
|
|
+ let melt_request = MeltBolt11Request::new(melt_quote.id, inputs, None);
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_melt(melt_request.clone()).await;
|
|
let response = http_client.post_melt(melt_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
@@ -831,13 +842,9 @@ async fn test_fake_mint_multiple_unit_melt() -> Result<()> {
|
|
usd_outputs.append(&mut sat_outputs);
|
|
usd_outputs.append(&mut sat_outputs);
|
|
let quote = wallet.melt_quote(invoice.to_string(), None).await?;
|
|
let quote = wallet.melt_quote(invoice.to_string(), None).await?;
|
|
|
|
|
|
- let melt_request = MeltBolt11Request {
|
|
|
|
- quote: quote.id,
|
|
|
|
- inputs,
|
|
|
|
- outputs: Some(usd_outputs),
|
|
|
|
- };
|
|
|
|
|
|
+ let melt_request = MeltBolt11Request::new(quote.id, inputs, Some(usd_outputs));
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
|
|
|
|
let response = http_client.post_melt(melt_request.clone()).await;
|
|
let response = http_client.post_melt(melt_request.clone()).await;
|
|
|
|
|
|
@@ -857,7 +864,7 @@ async fn test_fake_mint_multiple_unit_melt() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-/// Test swap where input unit != output unit
|
|
|
|
|
|
+/// Tests that swapping tokens where input unit doesn't match output unit fails
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_input_output_mismatch() -> Result<()> {
|
|
async fn test_fake_mint_input_output_mismatch() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -891,12 +898,9 @@ async fn test_fake_mint_input_output_mismatch() -> Result<()> {
|
|
&SplitTarget::None,
|
|
&SplitTarget::None,
|
|
)?;
|
|
)?;
|
|
|
|
|
|
- let swap_request = SwapRequest {
|
|
|
|
- inputs,
|
|
|
|
- outputs: pre_mint.blinded_messages(),
|
|
|
|
- };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(inputs, pre_mint.blinded_messages());
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
@@ -912,7 +916,7 @@ async fn test_fake_mint_input_output_mismatch() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-/// Test swap where input is less the output
|
|
|
|
|
|
+/// Tests that swapping tokens where output amount is greater than input amount fails
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_swap_inflated() -> Result<()> {
|
|
async fn test_fake_mint_swap_inflated() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -931,12 +935,9 @@ async fn test_fake_mint_swap_inflated() -> Result<()> {
|
|
let active_keyset_id = wallet.get_active_mint_keyset().await?.id;
|
|
let active_keyset_id = wallet.get_active_mint_keyset().await?.id;
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 101.into(), &SplitTarget::None)?;
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 101.into(), &SplitTarget::None)?;
|
|
|
|
|
|
- let swap_request = SwapRequest {
|
|
|
|
- inputs: proofs,
|
|
|
|
- outputs: pre_mint.blinded_messages(),
|
|
|
|
- };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(proofs, pre_mint.blinded_messages());
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
@@ -954,7 +955,7 @@ async fn test_fake_mint_swap_inflated() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-/// Test swap after failure
|
|
|
|
|
|
+/// Tests that tokens cannot be spent again after a failed swap attempt
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_swap_spend_after_fail() -> Result<()> {
|
|
async fn test_fake_mint_swap_spend_after_fail() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -974,49 +975,33 @@ async fn test_fake_mint_swap_spend_after_fail() -> Result<()> {
|
|
|
|
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 100.into(), &SplitTarget::None)?;
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 100.into(), &SplitTarget::None)?;
|
|
|
|
|
|
- let swap_request = SwapRequest {
|
|
|
|
- inputs: proofs.clone(),
|
|
|
|
- outputs: pre_mint.blinded_messages(),
|
|
|
|
- };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(proofs.clone(), pre_mint.blinded_messages());
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
assert!(response.is_ok());
|
|
assert!(response.is_ok());
|
|
|
|
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 101.into(), &SplitTarget::None)?;
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 101.into(), &SplitTarget::None)?;
|
|
|
|
|
|
- let swap_request = SwapRequest {
|
|
|
|
- inputs: proofs.clone(),
|
|
|
|
- outputs: pre_mint.blinded_messages(),
|
|
|
|
- };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(proofs.clone(), pre_mint.blinded_messages());
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
Err(err) => match err {
|
|
Err(err) => match err {
|
|
- cdk::Error::TokenAlreadySpent => (),
|
|
|
|
- err => {
|
|
|
|
- bail!(
|
|
|
|
- "Wrong mint error returned expected already spent: {}",
|
|
|
|
- err.to_string()
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
|
|
+ cdk::Error::TransactionUnbalanced(_, _, _) => (),
|
|
|
|
+ err => bail!("Wrong mint error returned expected TransactionUnbalanced, got: {err}"),
|
|
},
|
|
},
|
|
- Ok(_) => {
|
|
|
|
- bail!("Should not have allowed swap with unbalanced");
|
|
|
|
- }
|
|
|
|
|
|
+ Ok(_) => bail!("Should not have allowed swap with unbalanced"),
|
|
}
|
|
}
|
|
|
|
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 100.into(), &SplitTarget::None)?;
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 100.into(), &SplitTarget::None)?;
|
|
|
|
|
|
- let swap_request = SwapRequest {
|
|
|
|
- inputs: proofs,
|
|
|
|
- outputs: pre_mint.blinded_messages(),
|
|
|
|
- };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(proofs, pre_mint.blinded_messages());
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
@@ -1034,7 +1019,7 @@ async fn test_fake_mint_swap_spend_after_fail() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-/// Test swap after failure
|
|
|
|
|
|
+/// Tests that tokens cannot be melted after a failed swap attempt
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_melt_spend_after_fail() -> Result<()> {
|
|
async fn test_fake_mint_melt_spend_after_fail() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -1054,49 +1039,35 @@ async fn test_fake_mint_melt_spend_after_fail() -> Result<()> {
|
|
|
|
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 100.into(), &SplitTarget::None)?;
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 100.into(), &SplitTarget::None)?;
|
|
|
|
|
|
- let swap_request = SwapRequest {
|
|
|
|
- inputs: proofs.clone(),
|
|
|
|
- outputs: pre_mint.blinded_messages(),
|
|
|
|
- };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(proofs.clone(), pre_mint.blinded_messages());
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
assert!(response.is_ok());
|
|
assert!(response.is_ok());
|
|
|
|
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 101.into(), &SplitTarget::None)?;
|
|
let pre_mint = PreMintSecrets::random(active_keyset_id, 101.into(), &SplitTarget::None)?;
|
|
|
|
|
|
- let swap_request = SwapRequest {
|
|
|
|
- inputs: proofs.clone(),
|
|
|
|
- outputs: pre_mint.blinded_messages(),
|
|
|
|
- };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(proofs.clone(), pre_mint.blinded_messages());
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
Err(err) => match err {
|
|
Err(err) => match err {
|
|
- cdk::Error::TokenAlreadySpent => (),
|
|
|
|
- err => {
|
|
|
|
- bail!("Wrong mint error returned: {}", err.to_string());
|
|
|
|
- }
|
|
|
|
|
|
+ cdk::Error::TransactionUnbalanced(_, _, _) => (),
|
|
|
|
+ err => bail!("Wrong mint error returned expected TransactionUnbalanced, got: {err}"),
|
|
},
|
|
},
|
|
- Ok(_) => {
|
|
|
|
- bail!("Should not have allowed to mint with multiple units");
|
|
|
|
- }
|
|
|
|
|
|
+ Ok(_) => bail!("Should not have allowed swap with unbalanced"),
|
|
}
|
|
}
|
|
|
|
|
|
let input_amount: u64 = proofs.total_amount()?.into();
|
|
let input_amount: u64 = proofs.total_amount()?.into();
|
|
let invoice = create_fake_invoice((input_amount - 1) * 1000, "".to_string());
|
|
let invoice = create_fake_invoice((input_amount - 1) * 1000, "".to_string());
|
|
let melt_quote = wallet.melt_quote(invoice.to_string(), None).await?;
|
|
let melt_quote = wallet.melt_quote(invoice.to_string(), None).await?;
|
|
|
|
|
|
- let melt_request = MeltBolt11Request {
|
|
|
|
- quote: melt_quote.id,
|
|
|
|
- inputs: proofs,
|
|
|
|
- outputs: None,
|
|
|
|
- };
|
|
|
|
|
|
+ let melt_request = MeltBolt11Request::new(melt_quote.id, proofs, None);
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_melt(melt_request.clone()).await;
|
|
let response = http_client.post_melt(melt_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
@@ -1114,7 +1085,7 @@ async fn test_fake_mint_melt_spend_after_fail() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-/// Test swap where input unit != output unit
|
|
|
|
|
|
+/// Tests that attempting to swap with duplicate proofs fails
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_duplicate_proofs_swap() -> Result<()> {
|
|
async fn test_fake_mint_duplicate_proofs_swap() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -1138,12 +1109,9 @@ async fn test_fake_mint_duplicate_proofs_swap() -> Result<()> {
|
|
let pre_mint =
|
|
let pre_mint =
|
|
PreMintSecrets::random(active_keyset_id, inputs.total_amount()?, &SplitTarget::None)?;
|
|
PreMintSecrets::random(active_keyset_id, inputs.total_amount()?, &SplitTarget::None)?;
|
|
|
|
|
|
- let swap_request = SwapRequest {
|
|
|
|
- inputs: inputs.clone(),
|
|
|
|
- outputs: pre_mint.blinded_messages(),
|
|
|
|
- };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(inputs.clone(), pre_mint.blinded_messages());
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
@@ -1165,9 +1133,9 @@ async fn test_fake_mint_duplicate_proofs_swap() -> Result<()> {
|
|
|
|
|
|
let outputs = vec![blinded_message[0].clone(), blinded_message[0].clone()];
|
|
let outputs = vec![blinded_message[0].clone(), blinded_message[0].clone()];
|
|
|
|
|
|
- let swap_request = SwapRequest { inputs, outputs };
|
|
|
|
|
|
+ let swap_request = SwapRequest::new(inputs, outputs);
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
let response = http_client.post_swap(swap_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|
|
@@ -1188,7 +1156,7 @@ async fn test_fake_mint_duplicate_proofs_swap() -> Result<()> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
-/// Test duplicate proofs in melt
|
|
|
|
|
|
+/// Tests that attempting to melt with duplicate proofs fails
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
async fn test_fake_mint_duplicate_proofs_melt() -> Result<()> {
|
|
async fn test_fake_mint_duplicate_proofs_melt() -> Result<()> {
|
|
let wallet = Wallet::new(
|
|
let wallet = Wallet::new(
|
|
@@ -1211,13 +1179,9 @@ async fn test_fake_mint_duplicate_proofs_melt() -> Result<()> {
|
|
|
|
|
|
let melt_quote = wallet.melt_quote(invoice.to_string(), None).await?;
|
|
let melt_quote = wallet.melt_quote(invoice.to_string(), None).await?;
|
|
|
|
|
|
- let melt_request = MeltBolt11Request {
|
|
|
|
- quote: melt_quote.id,
|
|
|
|
- inputs,
|
|
|
|
- outputs: None,
|
|
|
|
- };
|
|
|
|
|
|
+ let melt_request = MeltBolt11Request::new(melt_quote.id, inputs, None);
|
|
|
|
|
|
- let http_client = HttpClient::new(MINT_URL.parse()?);
|
|
|
|
|
|
+ let http_client = HttpClient::new(MINT_URL.parse()?, None);
|
|
let response = http_client.post_melt(melt_request.clone()).await;
|
|
let response = http_client.post_melt(melt_request.clone()).await;
|
|
|
|
|
|
match response {
|
|
match response {
|